Skip to content

feat: replace the hand-rolled N3 parser with N3.js across the Turtle/N3 family - #831

Open
jeswr wants to merge 6 commits into
mainfrom
feat/n3-parser-migration
Open

feat: replace the hand-rolled N3 parser with N3.js across the Turtle/N3 family#831
jeswr wants to merge 6 commits into
mainfrom
feat/n3-parser-migration

Conversation

@jeswr

@jeswr jeswr commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Agent-generated draft PR for @jeswr to review — nothing merges without his sign-off. Part of the triaged-backlog programme (#823 / #824). The mandate, per @jeswr's steer: "rip out the current n3parser code entirely … where possible remove as much custom code from RDFlib as you can and make use of the N3.js API instead." The behavioural calls below need explicit sign-off; nothing here is final.

Replaces the hand-rolled 2005-era N3 parser with N3.js across the whole Turtle/N3 family, so parse(), Fetcher.load() and sparqlUpdateParser agree with each other for the first time — one parser, net −1,022 lines under src/.

What is deleted / added

File Lines Fate
src/n3parser.js −1,610 deleted — no fallback kept
src/lists.ts (convertFirstRestNil, substituteInDoc, substituteNillsInDoc) −121 deleted — replaced by N3.js Store#extractLists (it was not exported from the package index)
src/patch-parser.js 94 → 192 rewritten: no longer drives legacy-parser internals (p.skipSpace/p.node/p.directive); it rewrites the patch to N3 and reuses the same N3.js pipeline
fetcher.ts N3Handler inline parser now delegates to parse()
src/n3-adapter.ts +398 (new) the single N3.js↔rdflib adapter everything routes through
src/utils/literalValue.ts +156 (new) value-space literal helpers + the opt-in canonicalize flag (the migration path — see mitigation M3 below)

How it uses the N3.js API (not custom code)

  • Parsing: one N3.Parser call per document, with the format string enforcing the right grammar per content type — text/turtle (+application/x-turtle), text/n3 (+application/n3), application/n-triples, application/n-quads (+nquads), application/trig. N-Triples/TriG support is new; the ad-hoc n-quads callback path is gone. Synchronous, using N3.js's array-returning mode with { onPrefix } for prefix capture.
  • Lists: N3.Store#extractLists({ remove: true }) finds, validates and removes rdf:first/rest/nil chains; the adapter resolves the returned head→items map (recursively, for nested lists) into rdflib Collection terms, and turns lone rdf:nil into an empty Collection — matching the legacy parser's output, including for explicitly reified chains and rdf:nil-as-element (the existing lists-test.js expectations all pass unchanged). Folding is gated on the factory's COLLECTIONS support exactly as before, and skipped entirely when a document never mentions rdf:nil (no intermediate store on the hot path). Line-dump formats (N-Triples/N-Quads/TriG) are never folded — quad dumps round-trip verbatim.
  • Formulae (text/n3): N3.js emits each { … } as quads under a fresh blank-node graph label; the adapter rebuilds them into rdflib Formula sub-stores (recursively for nesting, with the empty-formula {} marker special-cased). =owl:sameAs, =>log:implies, <= → reversed log:implies, !/^ paths, and ?xVariable are all N3.js-native.
  • Quantifiers: parsed with explicitQuantifiers: true; the reified declarations in urn:n3:quantifiers are read back into newUniversal() / declareExistential() on the right scope (store or formula), keeping the legacy representation (terms stay NamedNodes).
  • SPARQL-Update patches: sparqlUpdateParser scans only the top-level keywords (INSERT/DELETE/WHERE, optional DATA, @prefix, and now SPARQL-style PREFIX), rewrites the document to <#query> patch:where { … } . N3, and hands it to the same adapter — clause { … } bodies are parsed by N3.js, not by hand.

Issues closed

Behavioural changes (need your sign-off)

  1. text/turtle is now strict Turtle. The legacy code parsed full N3 under a turtle content type (same parser for both), and the Fetcher routed all fetched turtle through it. Mislabelled N3-in-turtle documents now fail with N3.js's descriptive errors. Escape hatch if you want wire-compat instead: route turtle content types to format: 'text/n3' in the adapter (n3 mode is a turtle superset) — a one-line change; my recommendation is strict.
  2. Literal lexical forms are preserved (12.0, 3.141e0, true stay as written; the legacy parser normalised to 12, 3.141, 1). This is what Turtle 1.1 requires, but it changes term identity ("12"^^xsd:decimal"12.0"^^xsd:decimal) and serializer output. The Turtle serializer had a latent bug here — it emitted false for "true"^^xsd:boolean because it only knew the legacy '1' form — fixed in serializer.js. Mitigation M3 (below) is the migration path for consumers that match on the normalised forms; the wider read-lenient/write-strict question is under discussion in this thread.
  3. N-Quads default-graph statements are attributed to the document graph kb.sym(base) (rdflib's provenance convention) instead of the old callback path's DefaultGraph term. Consistent with every other format; flagged as breaking for anyone matching on the default graph.
  4. N3Parser is no longer exported (breaking API; a throwing stub with a descriptive pointer remains — M5 below). sparqlUpdateParser keeps its exact signature/return shape ({query, insert?, delete?, where?} with Formula values, plus the <#query> patch:* statements on the store).
  5. Empty-prefix leniency kept, reimplemented safely: :name without @prefix : still resolves against <base#>. Instead of a document-wide regex + unconditional input mutation, the adapter parses strictly first and retries once only on N3.js's specific Undefined prefix ":" error — zero cost and zero false positives on conforming documents, and mid-document @prefix : declarations override exactly like the legacy sequential semantics. (TimBL's own structures.n3 fixture depends on this leniency.)
  6. Dropped cwm-era leniencies — now loud, descriptive parse errors (each with a test asserting the error): @keywords, bareword date/dateTime literals (2026-07-01 → write "2026-07-01"^^xsd:date), has … / is … of (write the inverse triple; the modern N3 CG spec dropped them), string-literal subjects, undeclared non-empty prefixes (note: these already errored in v2.4.0 — only the error message/type changes).
  7. Upstream N3.js bug found & worked around (a candidate for a fix in N3.js itself): in n3 mode, a document-labelled bnode _:c mentioned inside a [ … ] property list gets the graph label as its scope prefix (top level: label .c), splitting it from its other mentions. Repro: new N3.Parser({format:'text/n3'}).parse('_:c <urn:p> 1. [ <urn:q> _:c ] <urn:r> 2.'). The adapter passes an explicit blankNodePrefix and repairs .-prefixed labels; formula-scoped labels (correct per N3 semantics) are untouched.
  8. RDF-star: N3.js parses quoted triples but rdflib's store has no term type for them — the adapter throws a descriptive error rather than crashing mid-store as main does today. (Real support would be a store-model project.)
  9. Lists inside N3 formulae are now folded into Collection terms (surfaced by the independent review pass; v2.4.0 left raw rdf:first/rdf:rest triples inside formula sub-stores — verified by repro against the published 2.4.0). Consistent with the migration and arguably a fix, but it changes formula contents for consumers that match on first/rest inside clauses (e.g. SPARQL-update WHERE bodies).

Breaking changes, semver and mitigations

A full breaking-change assessment ran against this branch (probe-by-probe vs built v2.4.0, plus consumer hunts across the SolidOS stack, @ldflex/rdflib, NSS, and npm/GitHub reverse-deps): see the assessment comment. Verdicts: 4 BREAKING (strict text/turtle vs legacy pod files; literal lexical preservation flipping solid-ui boolean reads; dropped cwm leniencies vs live text/n3 documents; re-parse bnode accumulation at force-reload sites), 10 potentially-breaking with no live consumer hit found, the rest safe or strict fixes.

This must ship as v3.0.0 — solid-ui/mashlib/solid-logic/solid-panes (^2.3.x) and @ldflex/rdflib (^2.2.0) all auto-adopt any 2.x release.

The full mitigation set recommended by the assessment is on the branch:

Mitigation Commit
M1force: true now implies clearPreviousData: true in Fetcher.load — de-breaks the 81 observed force-reload sites (bnode accumulation) 0ccb5d7
M2 — fix for a regression this branch had introduced: sparqlUpdateParser under a fragment-bearing base silently dropped its insert/delete clauses; regression test added 0ccb5d7
M3 (per @jeswr: both helper + opt-in flag) — value-space helpers isTrue(term), literalToBoolean(term), literalToNumber(term) (also exposed as Literal.toBoolean / Literal.toNumber), plus an opt-in parse(str, kb, base, contentType, { canonicalize: true }) flag that restores the ≤2.x parse-time normalisation of boolean/numeric lexical forms (true"1", 12.0"12", 3.141e0"3.141") across the Turtle family — off by default, so lexical preservation stays the shipped behaviour. isTrue(kb.any(s, p)) is the one-line fix for ^2.x patterns like term.value === '1' c9ec6a6
M5 — deprecated N3Parser export stub that throws a descriptive pointer to parse() 0ccb5d7
M8 — docs: Documentation/turtle-intro.html updated for the two removed extensions (0ccb5d7); reference/README.md marks dumpParser.js / ldpatchParser.js / fetcher-classes.js as archived relics that drive N3Parser internals which no longer exist (2b10b5b) 0ccb5d7 / 2b10b5b
Bundle hygiene — the adapter deep-imports n3/lib/{N3Parser,N3Store,N3DataFactory}.js, preserving #836's #449 deep-import discipline (no N3StreamWriter/readable-stream in browser bundles); a source-level hygiene test now fails any future root 'n3' import under src/; verified zero stream/writer/readable-stream occurrences in the built dist/rdflib.min.js 5a6bce9

Test changes — all justified, none loosened

  • parse-turtle-family-test.js (new): 30+ cases — the conformance suite plus formulae (=>/<=/=, nesting, empty {}), variables, quantifier scoping, nested/reified/empty collections, Error when parsing valid shacl/ttl file #352, the label-repair regression, and explicit "documented gap" error assertions for is…of / bareword dates / @keywords.
  • patch-parser-test.js: +6 cases (variables, @prefix/PREFIX, INSERT DATA, ; separators + braces-inside-strings, store side-effects, error reporting).
  • literal-value-test.js, parse-canonicalize-test.js, tests/types/value-space.ts (new): the M3 helpers and canonicalize flag, value- and type-level.
  • n3parser-stub-test.js, n3-import-hygiene-test.js (new): the M5 stub's error pointer; the no-root-'n3'-import source guard.
  • fetcher-test.js: the N3 fixture used a bareword date — modernised to "2012-03-12"^^xsd:date (same graph; the old syntax is a documented gap, behavioural change 6). New Can't store N3 triple with subject formula because of incompatible isSubject #567 formula-subject load test.
  • lists-test.js: expectations unchanged; only the redundant post-parse convertFirstRestNil() calls were removed (the function is deleted; parse() itself folds).
  • serialize-test.js: the RDF/XML expectation now uses the preserved lexical forms (12.0/3.141e0) — the old expectation encoded the legacy normalisation; the JSON-LD expectation in the same file already used the preserved forms.
  • indexed-formula-test.js: the store under test is now DataFactory.graph() (the previous new IndexedFormula() version passed vacuously because the legacy parser misfiled the status list into the default graph), plus a new companion test pinning the non-collection-store outcome explicitly (raw first/rest triples survive removeMetadata — the pre-existing deleteDocument() : Error : Statement to be removed is not on store #631 gap, now visible instead of hidden).
  • tests/serialize golden fixtures changed — flagging every ref-file diff explicitly. Sources t1.ttl, t2.ttl, t7.n3, structures.n3 used bareword dates / is…of and are rewritten to express the same graphs in standard syntax; the regenerated references are t1-ref.xml, t2-ref.xml, t7-ref.nt, t11-ref.xml, t12-ref.ttl, t13-ref.ttl, t17-ref.xml. Every delta was hand-checked to be one of exactly two classes: (a) preserved lexical forms (10.0, 1.45e5, true), (b) parser-generated bnode label names (_:dl1_coretta vs _:_g_L4C88). The t11 structures ref also exposed the serializer boolean bug fixed above (behavioural change 2).

Gates

CI is green on the branch head (Node 22.x + 24.x). Full local runs, all exit 0: at the migration commit, npm run build · test:unit (349 passing, 0 failing) · test:serialize (all 17) · test:types · build:types · build:esm · lint (0 errors; 5 pre-existing warnings untouched); re-verified with the M1/M2/M5 mitigations at 0ccb5d7 (355 unit passing, serialize/types/lint clean). The bundle-hygiene commit (5a6bce9) additionally verified the built dist/rdflib.min.js contains no stream/writer code.

@jeswr

jeswr commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

This tripped into using opus halfway through so I am asking fable to rewrite it.

@bourgeoa

bourgeoa commented Jul 4, 2026

Copy link
Copy Markdown
Member

If I understand well this is a major change that breaks parsing of existing turtle files with 0/1 as Boolean values in rdflib context.

…N3 family

Delete src/n3parser.js (1,610 lines) and src/lists.ts (121 lines) and route
every Turtle-family content type through the N3.js parser via a single
adapter (src/n3-adapter.ts):

  - text/turtle, application/x-turtle      strict Turtle
  - text/n3, application/n3                full Notation3
  - application/n-triples                  (new)
  - application/n-quads (+nquads alias)    unified
  - application/trig                       (new)

The adapter maps N3.js's flat quad stream onto rdflib's model: ( ... )
collections are folded into Collection terms with N3.js's own
Store#extractLists machinery; N3 formulae { ... } are rebuilt into Formula
sub-stores; @forAll/@Forsome (reified by N3.js under explicitQuantifiers)
are registered via newUniversal/declareExistential; ?x becomes a Variable;
=, =>, <= map natively to owl:sameAs / (reversed) log:implies.

The Fetcher's N3Handler now delegates to parse() instead of driving the
legacy parser, and sparqlUpdateParser builds its clause formulae by
rewriting the patch into N3 and running it through the same adapter
(gaining SPARQL-style PREFIX support, #651).

Legacy leniencies preserved: the empty prefix ":" still defaults to
<base#> (retry-once on N3.js's specific "Undefined prefix" error), and
lone rdf:nil / reified first-rest chains still fold into collections.
Dropped, now loud parse errors (see PR body): @Keywords, bareword
date/dateTime literals, `has`/`is ... of`, string-literal subjects, and
lexical normalisation of numeric/boolean literals.

Also fixes the Turtle serializer to accept the spec lexical forms
"true"/"false" for xsd:boolean, and repairs an N3.js n3-mode label-scoping
bug for `_:x` mentioned inside [ ... ] property lists.

Breaking: the N3Parser export is gone; n-quads default-graph statements
are now attributed to the document graph; text/turtle is now strict
Turtle (full N3 under a turtle content type no longer parses).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jeswr
jeswr force-pushed the feat/n3-parser-migration branch from 1b3f679 to 0fd4b99 Compare July 4, 2026 15:35
@jeswr jeswr changed the title feat: Parse Turtle-family formats via the N3.js parser feat: replace the hand-rolled N3 parser with N3.js across the Turtle/N3 family Jul 4, 2026
@jeswr

jeswr commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

If I understand well this is a major change that breaks parsing of existing turtle files with 0/1 as Boolean values in rdflib context.

N3.js is compliant to the current RDF 1.1/1.2 test suites for turtle and N3 CG test suites for Notation3.

Looking at the changes to the test files it seems like there might indeed be some deviations in this parser from those suites. I'll take your guidance on whether that is considered a patch or breaking change - I see the merit in holding this PR for a next mver.

@jeswr

jeswr commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

Breaking-change assessment (v2.4.0 → this branch)

We diffed runtime behavior probe-by-probe against built v2.4.0 and this branch, then hunted consumers (SolidOS stack, @ldflex/rdflib, node-solid-server, npm/GitHub reverse-deps). Full report with repros, per-delta migration snippets, and mitigation costings is in the linked document. Verdicts:

Delta Verdict Evidence
Strict text/turtle (N3 syntax rejected) BREAKING mashlib issue-tracker fixtures (TBL-era pod copies with @keywords, is…of) now FetchError; NSS 500s on PATCH of stored N3-flavoured .ttl; 221 log:implies .ttl files on GitHub
Literal lexical preservation BREAKING 4 solid-ui sites silently read stored true as false (preferences.js:211, forms.js:1892/:192, booleanField holds()); rdflib's own serializer emits true, so pods hold the breaking form
cwm leniencies dropped (is…of, barewords, @keywords) BREAKING @ldflex/rdflib recorded tests replay TimBL's card as text/n3 with is doap:developer of (line 235) → parse throws; the live w3.org card's N3 variant still uses it today
Re-parse duplicates bnode subgraphs BREAKING fetcher.load(doc, {force:true}) never clears → stores grow every refresh; 81 call sites incl. solid-ui chat, pod-chat-client (per ACL check), gitter-solid daemons. Repro: 3→3 stmts old, 3→5 new
nquads graph attribution, N3Parser removal, lists-in-formulae→Collection, sync nquads callback, bnode label instability/merging, langtag lowercasing, patch why, fragment-base patch regression potentially breaking plausible patterns; adversarial search found no live consumer hit (details in report)
Everything else (empty-prefix leniency, RDF-star rejection, new content types, Turtle 1.1 fixes, #352 boolean collections, SPARQL PREFIX patches, perf) safe parity, additive, or strict fixes — #352 fix resolves the known mashlib data-pane crash, and the old \U escape silently produced empty-string literals, so several changes are corruption fixes

Semver: this needs to be v3.0.0. solid-ui/mashlib/solid-logic/solid-panes (^2.3.x) and @ldflex/rdflib (^2.2.0) all auto-adopt a 2.x release on their next fresh install.

Cheap mitigations worth adopting in this PR:

  1. Make force: true imply clearPreviousData: true in Fetcher.load — one line, de-breaks all 81 observed force-reload sites (the accumulation delta).
  2. Fix a regression this branch introduces: sparqlUpdateParser with a fragment-bearing base URI silently returns a patch without its insert/delete clauses (<#query> resolves inconsistently) — one-line fix; NSS/solid-rest only survive because they strip fragments first.
  3. Ship a boolean value-space helper (and/or an opt-in canonicalize parse flag) so ^2.x consumers have a one-line fix for the literal-identity change.
  4. Keep a deprecated N3Parser export that throws a pointer to parse().
  5. Docs/body: Documentation/turtle-intro.html still documents two now-throwing extensions (naked dates, is…of); body nits — undeclared prefixes already errored in 2.4.0 (message-only change), n-quads RDF-star previously corrupted the store silently rather than crashing, "Closes Can't store N3 triple with subject formula because of incompatible isSubject #567" isn't reproducible as a 2.4.0 regression, and the dropped-leniency list should add the bareword datetime form (which also worked under text/turtle).

cc @jeswr — this assessment was agent-assisted (Claude Code). Every verdict was produced by running identical probes against both built checkouts; consumer hits are cited to file:line or reproduced against the consumers' own fixtures.

…ad, stub N3Parser

Follow-up to the breaking-change assessment on this PR, landing its cheap
mitigations (M1/M2/M4/M8):

- sparqlUpdateParser: build the <#query> sym from the fragment-stripped
  base and write it as an absolute IRI in the generated N3, so insertion
  and lookup can never diverge. Previously a fragment-bearing base URI
  (e.g. .../card#me) made the clause lookup miss and the returned patch
  silently lost its insert/delete/where clauses (regression introduced by
  this branch; U7 in the assessment). Regression test added.

- Fetcher.load: force: true now implies clearPreviousData: true unless
  the caller explicitly sets it to false. Parsed blank-node labels are no
  longer stable across parses, so re-parsing without clearing duplicated
  bnode subgraphs on every forced reload (U3/M1); this restores the net
  behaviour 2.x callers of load(uri, {force: true}) actually observed.
  Tests: statement count stable across a forced reload; explicit
  clearPreviousData: false still accumulates.

- index: restore a deprecated N3Parser export as a stub that always
  throws 'N3Parser was removed in rdflib 3.0; use parse(text, store,
  base, contentType) or the n3 package directly', converting the silent
  'undefined is not a constructor' failure into an actionable message
  (D4/M5). Throw message tested for both new and plain-call forms.

- Documentation/turtle-intro.html: mark the naked date/dateTime and
  is...of extensions as removed in rdflib 3.0 (they now raise parse
  errors under every content type) with their standard replacements;
  note the empty-prefix default is still supported (M8).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e flag

The N3.js-based parsers preserve literal lexical forms, so stored `true` /
`12.0` literals no longer compare equal to canonically-constructed ones
(`"1"^^xsd:boolean`, `"12"^^xsd:decimal`). This ships the two transition
aids from the breaking-change assessment (mitigation M3):

- Value-space helpers `isTrue(term)`, `literalToBoolean(term)` and
  `literalToNumber(term)` (also exposed as `Literal.toBoolean` /
  `Literal.toNumber`, the inverses of `fromBoolean` / `fromNumber`). They
  accept every lexical form the datatype allows, giving ^2.x consumers a
  one-line fix for patterns like `term.value === '1'`.

- An opt-in `canonicalize` parse option — `parse(str, kb, base, type,
  { canonicalize: true })` or as a sixth argument after a callback —
  that restores rdflib <=2's parse-time normalisation of xsd:boolean /
  integer / decimal / double / float lexical forms (`true` -> "1",
  `12.0` -> "12", `3.141e0` -> "3.141") across the Turtle family. Off by
  default; lexical preservation remains the shipped behaviour. Integer
  canonicalisation is done lexically so arbitrary-precision values keep
  their exact digits, and ill-typed forms are left untouched.

Covered by a helper truth table, canonicalize on/off store-comparison
tests and a tests/types compile check of the new exports.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@bourgeoa

bourgeoa commented Jul 4, 2026

Copy link
Copy Markdown
Member

If I understand well this is a major change that breaks parsing of existing turtle files with 0/1 as Boolean values in rdflib context.

N3.js is compliant to the current RDF 1.1/1.2 test suites for turtle and N3 CG test suites for Notation3.

Looking at the changes to the test files it seems like there might indeed be some deviations in this parser from those suites. I'll take your guidance on whether that is considered a patch or breaking change - I see the merit in holding this PR for a next mver.

@jeswr I'm not sure we are on the same line.
My main issue is user data related.
The new N3.js parsing cannot break actual data parsing
This means that Boolean 0/1 should still be parseable
true/false should also be parsed correctly
And then may be serialise could always render true/false. With may be apps updates.

We cannot decide that years of data are not parseable rdflib turtle anymore.

Boolean is may be not the only issue. But this is an old one. And ran in a blocker to solve it

Completes the M8 documentation mitigation for the N3.js migration:
reference/{dumpParser,ldpatchParser,fetcher-classes}.js document the legacy
hand-rolled parser's internals, which no longer exist. A README now marks the
directory as archived reference material and points at parse()/N3.js.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jeswr
jeswr marked this pull request as ready for review July 5, 2026 01:24
Copilot AI review requested due to automatic review settings July 5, 2026 01:24

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@jeswr

jeswr commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

Ah I am with you now @bourgeoa - I can think of two things that we can do here:

    1. Target that the next non-breaking release of rdflib is "read lenient" and "write strict"; so that apps are "cleaning up" files to be as compliant to current RDF 1.1 / 1.2 / N3 CG standards as possible (noting that there may be some cases where this is not possible); whilst also being able to work with the existing data.
    1. Write a data migration app if we ever did introduce breaking functionality; so that app authors can link their users to the data migration app when the app encounters a file it can't parse. The migration app would make its way through files in the Pod and clean them up to use RDF 1.1 / 1.2 / N3 CG standards complaint syntax.

@jeswr
jeswr marked this pull request as ready for review July 5, 2026 12:59
A root `import ... from 'n3'` in n3-adapter.ts pulled n3's package index
into downstream browser bundles, dragging N3StreamWriter and its
readable-stream/Node polyfill chain back in and undoing the #449
deep-import discipline. The adapter now deep-imports exactly what it
uses (n3/lib/{N3Parser,N3Store,N3DataFactory}.js), and a source-level
hygiene test fails any future root 'n3' import under src/.

Verified on the built browser bundle: zero occurrences of
N3StreamWriter/N3StreamParser/N3Writer/readable-stream in
dist/rdflib.min.js; full suite green (382 passing).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@bourgeoa

bourgeoa commented Jul 5, 2026

Copy link
Copy Markdown
Member

This is is a very long open issue. See nodeSolidServer/node-solid-server#1468 (comment).

It needs a more open discussion.

Not sure that serialization to false/true will not introduce more bugs.
Among all issues reported it is the only one that is really touchy.

@jeswr

jeswr commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

Not sure that serialization to false/true will not introduce more bugs.

Ah .... I see. I'll look at this more closely in a bit to see if there is a way of going about this that doesn't break anything or annoy anoyone.

jeswr added a commit that referenced this pull request Jul 5, 2026
Output-level guard in the browser e2e: dist/rdflib.min.js must contain
zero occurrences of N3StreamWriter/N3StreamParser/readable-stream, so a
regression of the deep-import pattern (e.g. via #831's n3-adapter) fails
the browser-e2e CI job loudly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants