diff --git a/src/N3Writer.js b/src/N3Writer.js index b4f2bf61..d6990e8d 100644 --- a/src/N3Writer.js +++ b/src/N3Writer.js @@ -125,7 +125,7 @@ export default class N3Writer { // ### `quadToString` serializes a quad as a string quadToString(subject, predicate, object, graph) { return `${this._encodeSubject(subject)} ${ - this._encodeIriOrBlank(predicate)} ${ + this._encodeTerm(predicate)} ${ this._encodeObject(object) }${graph && !isDefaultGraph(graph) ? ` ${this._encodeIriOrBlank(graph)} .\n` : ' .\n'}`; } @@ -140,8 +140,7 @@ export default class N3Writer { // ### `_encodeSubject` represents a subject _encodeSubject(entity) { - return entity.termType === 'Quad' ? - this._encodeQuad(entity) : this._encodeIriOrBlank(entity); + return this._encodeTerm(entity); } // ### `_encodeIriOrBlank` represents an IRI or blank node @@ -215,18 +214,23 @@ export default class N3Writer { // ### `_encodePredicate` represents a predicate _encodePredicate(predicate) { - return predicate.value === rdf.type ? 'a' : this._encodeIriOrBlank(predicate); + return predicate.value === rdf.type ? 'a' : this._encodeTerm(predicate); } // ### `_encodeObject` represents an object _encodeObject(object) { - switch (object.termType) { + return this._encodeTerm(object); + } + + // ### `_encodeTerm` represents an arbitrary term + _encodeTerm(term) { + switch (term.termType) { case 'Quad': - return this._encodeQuad(object); + return this._encodeQuad(term); case 'Literal': - return this._encodeLiteral(object); + return this._encodeLiteral(term); default: - return this._encodeIriOrBlank(object); + return this._encodeIriOrBlank(term); } } diff --git a/test/N3Writer-test.js b/test/N3Writer-test.js index 4e1fc556..333a0a40 100644 --- a/test/N3Writer-test.js +++ b/test/N3Writer-test.js @@ -990,6 +990,45 @@ describe('Writer', () => { ).toBe(' <<( )>> .\n'); }); + it('should serialize a triple with a literal as subject', + shouldSerialize([`"123"^^${xsd.boolean}`, 'b', 'c'], `"123"^^<${xsd.boolean}> .\n`)); + + it('should serialize a triple with a literal as predicate', + shouldSerialize(['a', `"123"^^${xsd.boolean}`, 'c'], ` "123"^^<${xsd.boolean}> .\n`)); + + it('should serialize a triple with a language-tagged literal as subject', + shouldSerialize(['"hello"@en-us', 'b', 'c'], '"hello"@en-us .\n')); + + it('should serialize a triple with a literal as subject in N3 mode', + shouldSerialize({ format: 'text/n3' }, + [`"123"^^${xsd.boolean}`, 'b', 'c'], + `"123"^^<${xsd.boolean}> .\n`)); + + it('should serialize a triple with a literal as subject via quadToString', () => { + const writer = new Writer(); + expect( + writer.quadToString(termFromId(`"123"^^${xsd.boolean}`), new NamedNode('b'), new NamedNode('c')), + ).toBe(`"123"^^<${xsd.boolean}> .\n`); + }); + + it('should serialize a triple with a literal as predicate via quadToString', () => { + const writer = new Writer(); + expect( + writer.quadToString(new NamedNode('a'), termFromId(`"123"^^${xsd.boolean}`), new NamedNode('c')), + ).toBe(` "123"^^<${xsd.boolean}> .\n`); + }); + + it('should round-trip a triple with a literal as subject in N3 mode', done => { + const quad = new Quad(termFromId(`"1"^^${xsd.boolean}`), + new NamedNode('http://example.com/p'), new NamedNode('http://example.com/o')); + const writer = new Writer({ format: 'text/n3' }); + writer.addQuad(quad); + writer.end((error, output) => { + expect(new Parser({ format: 'text/n3' }).parse(output)).toEqual([quad]); + done(error); + }); + }); + /* * Test relativization of IRIs *