Translate Turtle/N3 to JSON-LD for HTML data island (#344) - #345
Merged
Conversation
Phase 1 of #7 only embedded the data island when the stored content type was application/ld+json; .ttl/.n3 URLs got the mashlib wrapper without an embedded payload. Extend the embed branch to cover text/turtle and text/n3: - Try JSON.parse first. JSS converts Turtle/N3 to JSON-LD on PUT (handlePut conneg branch), so for HTTP-PUT'd .ttl/.n3 files the bytes on disk are already JSON-LD — pass the Buffer through, no extra string copy. - Fall back to turtleToJsonLd (n3.js) for files placed on the filesystem out-of-band in their native format. JSON.stringify the result compactly so it doesn't burn cap bytes on whitespace. - Both parses failing → drop the island silently. The wrapper still renders and mashlib XHR-fetches the original as before. Other RDF formats (rdf+xml, etc.) are untouched. Add integration coverage: PUT Turtle / PUT N3 → GET text/html shows the embedded JSON-LD with the original literals. The both-parses-fail branch can't be reached via HTTP (PUT validates and rejects malformed Turtle with 400 before storage), so it's covered by inspection only. All 555 tests pass (553 + 2 new).
There was a problem hiding this comment.
Pull request overview
Extends the mashlib HTML “data island” embedding path to include resources stored under .ttl and .n3 URLs by translating Turtle/N3 to JSON-LD (falling back to omitting the island on parse failure), aligning with the Phase-1 data island goals.
Changes:
- Update HTML-serving path in
handleGet()to embed a JSON-LD data island fortext/turtleandtext/n3resources by attempting JSON parse first, then falling back to Turtle→JSON-LD conversion. - Add integration tests verifying Turtle and N3 resources embed JSON-LD in the HTML wrapper.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
src/handlers/resource.js |
Adds Turtle/N3→JSON-LD conversion logic for HTML data-island embedding when serving mashlib wrapper. |
test/data-island.test.js |
Adds integration coverage for Turtle and N3 resources embedding parsed JSON-LD into the data island. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+353
to
+355
| storedContentType === 'application/ld+json' || | ||
| storedContentType === 'text/turtle' || | ||
| storedContentType === 'text/n3'; |
Comment on lines
+367
to
+373
| try { | ||
| const jsonLd = await turtleToJsonLd(text, resourceUrl); | ||
| embedJsonLd = JSON.stringify(jsonLd); | ||
| } catch { | ||
| // Both parses failed → drop the island. The wrapper | ||
| // still renders and mashlib XHR-fetches the original. | ||
| } |
Comment on lines
+360
to
+372
| const text = buf.toString('utf8'); | ||
| try { | ||
| JSON.parse(text); | ||
| // Already JSON-LD bytes — pass the Buffer through so | ||
| // dataIsland() can coerce it without an extra string copy. | ||
| embedJsonLd = buf; | ||
| } catch { | ||
| try { | ||
| const jsonLd = await turtleToJsonLd(text, resourceUrl); | ||
| embedJsonLd = JSON.stringify(jsonLd); | ||
| } catch { | ||
| // Both parses failed → drop the island. The wrapper | ||
| // still renders and mashlib XHR-fetches the original. |
Three real points addressed:
1. Use `RDF_TYPES.JSON_LD` / `.TURTLE` / `.N3` instead of hardcoded
strings. Already imported and used elsewhere in this file.
2. Avoid double-decode in the JSON-LD-on-disk hot path. Restructure
the embed branch so:
- `application/ld+json` URL: pass Buffer through (no decode,
no parse — matches pre-PR behaviour).
- `text/turtle` / `text/n3` URL: decode once, JSON.parse;
on success pass the decoded *text* through (not the Buffer)
so dataIsland() doesn't re-decode via String() coercion.
- Turtle parse fallback unchanged.
3. Add coverage for the both-parses-fail branch. The handler's
defensive guard fires when a `.ttl`/`.n3` file is placed on disk
out-of-band (bypassing the PUT validator). The new test plants
a malformed Turtle file directly into the test data dir via
node:fs and asserts the wrapper still renders without an island.
556 / 556 tests pass (553 + 3 new).
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #344.
Summary
.ttl/.n3URLs on JSS: PUT already converts to JSON-LD on store, so the embed path triesJSON.parsefirst and passes the Buffer through with no extra copy.turtleToJsonLd(n3.js, already a dep),JSON.stringifycompactly into the island.Test plan
npm test— 555 / 555 pass (553 prior + 2 new)text/turtle→ GETtext/htmlshows embedded JSON-LD with the original literaltext/n3