Skip to content

Releases

v0.7.0

Choose a tag to compare

@github-actions github-actions released this 09 Nov 09:26

Minor changes

  • cca58f9: JSON input with a lone surrogate escape is rejected. JSON.parse accepts "\ud800", half of a UTF-16 surrogate pair escaped without its other half, and kgdiff used to carry it through ids and labels into its diffs and deltas; such text is not Unicode, and the Rust implementation (RFC 0002) cannot hold it. parseGraph now throws invalid-input for one in JSON and JSON-LD, located at the escape (Invalid JSON on line 6, column 35: the escape \ud83d is a lone surrogate (half of a UTF-16 pair), which kgdiff does not accept.), and so does a JSON-LD context text a documentLoader returns; kgdiff apply refuses a delta that has one. Escaped surrogate pairs ("😀") read as before.

    @kgdiff/cli · @kgdiff/formats

  • d01c4e0: Matching gives the same result in every JavaScript engine. Its neighbour and key weights (1 / log₂(2 + degree), 1 / log₂(1 + postings)) now use a log₂ built from exactly rounded operations only, the one the layout already used, instead of Math.log2, which engines may approximate differently: V8 ports FreeBSD's e_log2.c, while an engine that calls the platform's C library gets that library's rounding (Apple's differs from V8 on 439 of the integers up to 2,000,000). A diff computed in a browser, as the playground does, now equals the CLI's whatever the engine. The new log₂ differs from V8's by one unit in the last place on about 2% of integers; no match, suggestion or score changes in the conformance corpus, the example datasets or 144 synthetic diffs, but a score that sits exactly on a rounding boundary or a tie can move. The function is exported as log2, and @kgdiff/layout uses it from core.

    @kgdiff/core

  • 7586808: Reports open the same way whatever Unicode version the browser has. diffFromJSON takes the labels, aliases and types of a document's snapshots as written instead of composing them to NFC again with the runtime's ICU, and the content hashes in the delta check that text: a report made with Node 24 (Unicode 17) no longer fails to open in a browser with older tables when a label holds a character whose composition changed in between, and a snapshot whose text was edited or is not in NFC is still rejected. To restore a label it left out without Unicode tables either, kgdiff JSON (diffs, graphs and deltas) now leaves an edge label out only when it equals predicateLabel(predicate) before its NFC step; a predicate whose readable part is written decomposed keeps its label in the document. A diff written by an earlier version for such a predicate, with that label left out, no longer opens: write it again. normalize composes API input to NFC as before.

    @kgdiff/core · @kgdiff/viewer

  • cca58f9: Numbers beyond the range of a double in JSON graphs are kept instead of lost. JSON may write 1e400, which JSON.parse reads as Infinity; the JSON reader used to drop such a number without a word (an attribute or meta member disappeared, an array item became null), so a diff could report nothing for a value that changed, or a change that did not happen. It now keeps the value as the string "Infinity" or "-Infinity", as normalize keeps a non-finite number an API caller passes, and reports how many with a json-non-finite warning (ParseWarningCode), in every JSON dialect.

    @kgdiff/formats

  • 9ebb278: layoutFromJSON reads version 2 of the layout document, which kgdiff's Rust layout engine will write. Version 2 is version 1's members plus generator, a non-empty string such as "kgdiff-layout/1" that names the engine generation that computed the positions. It becomes the new optional LayoutResult.generator. Positions read from either version are valid pins for anchored layouts and extendLayout. A version 2 document without a generator is rejected (invalid-input), and versions other than 1 and 2 are rejected as before (unsupported-version). layoutToJSON still writes version 1, so a layout read from version 2 is written back as version 1 without its generator. Types: LayoutJSON is now the union of the documents layoutFromJSON reads, LayoutJSONV1 | LayoutJSONV2, and layoutToJSON returns LayoutJSONV1. Code that relied on LayoutJSON['version'] being 1 should use LayoutJSONV1. Through ReportPayload.layout (a LayoutJSON), the viewer opens reports whose layout is version 2.

    @kgdiff/layout

  • e510258: Report payloads may leave their layout out. ReportPayload.layout is optional: a payload without one (the member left out) is laid out in the browser when the viewer reads it, with layoutDiff's default options, so an application that computed a diff itself can show it by passing its diff.v1 JSON as a payload. The ESM build imports the compute module on demand for it; the standalone viewer takes it from the @kgdiff/viewer/standalone/compute add-on (globalThis.KgdiffCompute), and without the add-on shows an error that says what is missing instead of failing to read the layout. The diff engine never runs for a payload, and payloads with a layout open exactly as before, without loading the compute module. A layout that is present but not an object (null, for instance) is rejected. The CLI keeps writing the layout into its reports.

    @kgdiff/viewer


Every package is at 0.7.0: @kgdiff/cli · @kgdiff/core · @kgdiff/formats · @kgdiff/layout · @kgdiff/scene · @kgdiff/renderer · @kgdiff/viewer · @kgdiff/g6.

GitHub Action: uses: iiwish/kgdiff@v0.7.0.

v0.6.0

Choose a tag to compare

@github-actions github-actions released this 07 Nov 08:34
8722477

Minor changes

  • 325afea: The viewer's layout can be arranged, and its parts placed one by one. Every region of <kgdiff-viewer> (the change list, the detail panel, the search, the filters, the view dock, the replay transport, the legend, the zoom buttons, the minimap, the title, the actions) is open, collapsed or hidden through one attribute, panels="detail:collapsed minimap:hidden", or the property viewer.panels = { detail: 'collapsed' } (reading it gives the page's declaration back; the new read-only viewer.layout has every region's state and the sizes); sidebar="closed", header="compact" and chrome="none" keep working as presets of it. The detail panel can now be collapsed to a bar of its own, the sidebar's width and the split between the change list and the details can be dragged (or moved with the arrow keys), and kgdiff-layout reports every change. The viewer remembers what the reader changes (panels, sizes, theme, palette, language) in localStorage for the next visit, unless the page sets them or persist="none"; persist-key gives an app on a shared origin a store of its own. shortcuts="scoped|global|none" says where keyboard shortcuts apply (global-shortcuts still works) and keymap="x:none r:review" rebinds single keys (a letter in both cases, so Shift+J / K now step through the changes too); the kgdiff-* events are typed on every element, the document and the window (KgdiffEventMap; KgdiffViewerEventMap stays as a deprecated alias); refreshTheme() redraws the canvas after the page changed --kgdiff-* tokens, which are now documented, public CSS custom properties. Four of them are renamed to whole words before they become public: --kgdiff-bg → --kgdiff-background, --kgdiff-mono → --kgdiff-font-mono, --kgdiff-text-2 → --kgdiff-text-secondary and --kgdiff-text-3 → --kgdiff-text-muted; a page that set the old names sets the new ones instead. New, experimental elements compose a layout of your own: <kgdiff-root> holds the session, and <kgdiff-stage> (with five slots for your content over the canvas, which the graph is framed clear of, and panels for its own chrome: dock, transport, legend, zoom, minimap), <kgdiff-change-list>, <kgdiff-change-detail>, <kgdiff-search> and <kgdiff-filters> show its parts, inside it or anywhere on the page with for="<root id>". @kgdiff/viewer/elements/<name> defines a single element, and @kgdiff/viewer/panels is the panels syntax (no DOM). The CLI's --panels sets a report's initial panel states; reports now carry their theme and language in the payload only, so a reader's earlier choice wins over them.

    @kgdiff/cli · @kgdiff/viewer

  • 8b0538c: Several views of one diff, and the canvas chrome as elements (experimental). A <kgdiff-root> now draws every <kgdiff-stage> bound to it, each with its own canvas, camera, zoom buttons and minimap, all sharing the selection, the hover, the filters, the search and the replay; version="before" or version="after" pins a stage to one version, for before and after side by side. The view dock, the replay transport, the legend, the zoom buttons, the minimap, the title and the actions are elements of their own (each says which root it shows with rootElement): <kgdiff-view-dock>, <kgdiff-transport>, <kgdiff-legend> (variant="full|mini", open), <kgdiff-zoom> and <kgdiff-minimap> (bound to the nearest stage or to the one stage="<id>" names: stage, stageElement, rootElement; the minimap is in the custom state :state(overview) while the whole graph is in view), <kgdiff-title> and <kgdiff-actions>, each with a subpath @kgdiff/viewer/elements/<name>. Slotted into a stage or a <kgdiff-viewer>, one of them replaces the built-in region of its kind (in the viewer the title and the actions too) while panels keeps applying to the rest; placed anywhere else it is no obstacle to fits and flights unless registered with registerObstacle. <kgdiff-viewer> gets the stage's five slots: your content in slot="top-end" (and top-start, bottom-start, bottom-center, bottom-end) goes over the canvas and the graph is framed clear of it. The shortcuts dialog lists the keys bound after keymap, and ? in a composed root opens the dialog of its <kgdiff-actions>. Accessibility: the zoom toolbar, the appearance menu and the search's results have names, a <kgdiff-stage> is a named region rather than a main landmark, the end of a replay is announced once, and the page's content in the top corners comes first in the tab order. @kgdiff/viewer/elements/root no longer carries the renderer (64 kB instead of 88 kB, min + gzip): each stage brings its own.

    @kgdiff/viewer

  • 69a0975: The viewer describes its elements for tools. The package ships a Custom Elements Manifest (custom-elements.json, named by the new customElements field), generated from the sources: every element's attributes and the properties they reflect, its methods, the roots' events with their detail types, the slots, the --kgdiff-* CSS custom properties and <kgdiff-minimap>'s :state(overview), with each experimental part marked. Generated from it: vscode.html-custom-data.json, which VS Code reads through html.customData to complete and describe the tags and their attributes; and @kgdiff/viewer/react (experimental), React 19's JSX types for the elements, their properties and their onkgdiff-* events, enabled with import type {} from '@kgdiff/viewer/react' (@types/react is an optional peer dependency). The elements stay experimental in 0.6 and become stable in 0.7. The docs gain a reference of every element generated from the manifest, and tested recipes for React 19, Vue 3 and Svelte 5.

    @kgdiff/viewer


Every package is at 0.6.0: @kgdiff/cli · @kgdiff/core · @kgdiff/formats · @kgdiff/layout · @kgdiff/scene · @kgdiff/renderer · @kgdiff/viewer · @kgdiff/g6.

GitHub Action: uses: iiwish/kgdiff@v0.6.0.

v0.5.0

Choose a tag to compare

@github-actions github-actions released this 06 Nov 06:56
4905eec

Minor changes

  • 764535e: The terminal summary and the Markdown summary (so the GitHub Action's pull request comment too) list the possible matches: pairings kgdiff considered but did not apply, between a node listed as removed and one listed as added. Until now only the viewer's detail panel showed them, so "removed “Saudi Aramco”, added “Aramco”" gave no hint that the two may be one entity. Each line names both nodes (with their ids when the names are equal), the score, why it was not applied (below --threshold, or too close to another candidate) and the label and neighbourhood evidence, and a closing line says how to pair one: a synonym, a replacement link or a lower threshold. At most 10 in the terminal (all with --limit 0) and 20 in Markdown; --json keeps every suggestion.

    @kgdiff/cli

  • 3f6e7d8: Changes to definitions are flagged ⚑ for review first. A reworded definition can change what existing data means while the diff looks small, and it used to be folded into ~1 attribute among the other edits. Now a line under the diffstat bar counts the hunks that change one (⚑ Review first: definition changed in 9 hunks, also in --stat), each of their rows says so before its summary (content · ⚑ definition · ~2 attributes), and the Markdown summary, so the GitHub Action's pull request comment too, lists them in a ⚑ Review first block before the phase groups. By default kgdiff watches def (OBO), definition (kgdiff JSON), IAO:0000115 and skos:definition; the new --watch-attr <key> (repeatable) replaces that list, e.g. --watch-attr rdfs:comment for schema.org-style vocabularies. TextContext and MarkdownOptions take the same list as watch, and DEFAULT_WATCH_ATTRS and watchedChanges are exported.

    @kgdiff/cli

  • 6ed2b9c: HTML reports are smaller: they embed the diff packed (packDiffJSON, format kgdiff.diff.packed, schema schema/diff-packed.v1.json), with its unchanged elements, which are most of a large diff, stored as tables of indices into one string table. For 100k nodes / 300k edges the embedded diff goes from 68.7 MB to 19.3 MB, 6.8 MB to 3.2 MB gzipped, and the report opens as fast. unpackDiffJSON gives the DiffJSON back byte for byte; the viewer reads packed and unpacked payloads (ReportPayload.diff is either), so older reports still open. The standalone viewer bundle budget goes from 100 kB to 105 kB (min + gzip) for the unpacking and the consistency checks of diffFromJSON.

    @kgdiff/cli · @kgdiff/core · @kgdiff/viewer

  • f957a49: diffFromJSON checks that a diff document is consistent before it returns, and throws invalid-input naming the first contradiction: an element whose versions do not fit its status (an added node with a before id, a removed edge with an after snapshot), an unchanged element with facets or a hunk, a changed one outside every hunk, a repeated id, an edge whose endpoints are not union nodes or disagree with its snapshots, a hunk that lists elements that are not its own, delta ops owned by two hunks or out of range, hunks out of review order, a summary or stats that do not match the elements, or a delta whose base or target is another graph (by content hash). Until now such a document was read as it was, and a viewer could show wrong counts or export a delta for other graphs. Everything kgdiff writes passes. diffFromJSON is also about 10% faster on large diffs: edges are found by their key instead of by a canonical JSON fingerprint. schema/diff.v1.json states the same rules per element (versions by status; facets and hunk by status).

    @kgdiff/core

  • 212c48c: UnionNode and UnionEdge are now unions by status, so the types say which versions an element is in: an added node has afterId and after and no before version, a removed one only beforeId and before, an unchanged or modified one both; the same for edges, where only edges in both versions can have sourceBefore, targetBefore or predicateBefore. Narrow on status to read before / after without ?. or casts (AddedUnionNode, RemovedUnionNode, MatchedUnionNode and the edge counterparts name the cases). The objects themselves are unchanged; code that builds union elements by hand (test fixtures, mocks) now has to give each status the versions it implies.

    @kgdiff/core

Patch changes

  • 86f4583: The bug report link of an unexpected error takes the platform and the Node.js version from CliIO.runtime instead of reading process in main, so main keeps taking every side effect from io and runs in hosts other than Node.js. nodeIO() fills it in, so the link is unchanged for the kgdiff command; a custom io without runtime gets a link that names only the CLI version.

    @kgdiff/cli

  • 088671c: Link unexpected CLI errors to a bug-report form prefilled with public version and runtime
    metadata, without including error messages or input paths in the URL.

    @kgdiff/cli

  • f02bc72: Similarity matching no longer pairs two same-named nodes on their label alone when their types conflict. With --match similarity nothing is matched in the first round, so the neighbour evidence was missing for every pair and an equal label outweighed disjoint types: “Mercury” the planet (orbiting the Sun) and “Mercury” the element (with symbol Hg) were reported as one node whose type changed. Such a pair (both nodes typed, no type and no attribute in common, neighbours not matched yet) now waits for the next round, when propagation brings in the neighbours; the two Mercurys share none, so they are reported as removed and added with a possible match below the threshold, as --match auto already did. A type change that the neighbours confirm is still matched, and nodes without edges are matched as before.

    @kgdiff/cli · @kgdiff/core

  • 638c617: diffFromJSON is about 30% faster on large diffs, so HTML reports open about 20% sooner: a report of 100k nodes / 300k edges is ready in 1.0 s instead of 1.24 s in headless Chrome. Rebuilding the two graphs was most of diffFromJSON. The snapshots diffToJSON writes are already canonical, so they are now read straight into graphs, and each union edge keeps the edge it was read into instead of looking it up again. A document normalize would change (parallel edges, a repeated id, a dangling end, a hand-edited snapshot) is normalized as before, as fast as before. The result is the same, field for field and in the same order: diffToJSON(diffFromJSON(j)) is still j, byte for byte, the graph hashes are unchanged, and every consistency check still runs.

    @kgdiff/core · @kgdiff/viewer

  • ed1c3c9: Normalized graphs take about 30% less memory: a graph of 100k nodes and 300k edges now keeps about 111 MB of heap instead of 157 MB. Structural edge keys were built by concatenation, which V8 stores as a rope of many small strings that stays allocated behind every key; they are now built as flat strings, which are also quicker to hash. Keys, diffs, deltas and their JSON are unchanged, byte for byte.

    @kgdiff/core

  • 6d34966: The standalone viewer bundle, which every HTML report inlines, no longer carries the facet names
    of facetLabel: they are kept apart from the hunk phrasebooks that formatHunk reads, which
    saves 0.2 kB (min + gzip). Behaviour is unchanged. The bundle's size ceiling goes from 105 kB to
    130 kB, so a feature no longer has to raise it, and the HTML report overhead budget (without data
    or compute add-on) from 120 kB to 135 kB gzip, so it still covers the bundle.

    @kgdiff/core · @kgdiff/viewer

  • 5286e02: The viewer's CSS custom properties are renamed from --kg-* to --kgdiff-*. They are not documented API yet; a page that set one of the old names on <kgdiff-viewer> sets the new name instead, and the canvas now follows it too, not only the panels. Styles are one shared constructable stylesheet, parsed once for every viewer on the page, instead of <style> elements in each. Inside, <kgdiff-viewer> is now built from a headless session and regions bound to it (RFC 0001, phase 1); its attributes, properties, methods, events and HTML reports are unchanged.

    @kgdiff/viewer


Every package is at 0.5.0: @kgdiff/cli · @kgdiff/core · @kgdiff/formats · @kgdiff/layout · @kgdiff/scene · @kgdiff/renderer · @kgdiff/viewer · @kgdiff/g6.

GitHub Action: uses: iiwish/kgdiff@v0.5.0.

@kgdiff/viewer@0.4.0

Choose a tag to compare

@github-actions github-actions released this 03 Nov 07:44
a03340d

Minor Changes

  • 86fe0da: Changes only is now a scope that combines with any mode instead of a fourth mode: mode is overlay | swipe | replay and the new scope (all | changes) shows only the changes, in overlay, swipe or replay alike. mode="changes" still works (overlay + scope="changes"), as do old #kgdiff=…;mode:changes links; kgdiff-mode reports { mode, scope }. The CLI gains --scope (--mode changes keeps working).

    The canvas loses its header bar: the title floats top left, the actions top right, and the modes, the Changes only toggle with its context hops, and replay's transport live in one dock at the bottom. The diffstat pills (the sidebar's filter chips show the same counts) and the second fit button are gone, the chips wear the legend's swatches, the legend starts collapsed and the minimap appears only while part of the graph is out of view. Unchanged node labels use the muted text color, so the changes stand out.

Patch Changes

  • Updated dependencies [86fe0da]
    • @kgdiff/scene@0.4.0
    • @kgdiff/renderer@0.4.0
    • @kgdiff/core@0.4.0
    • @kgdiff/formats@0.4.0
    • @kgdiff/layout@0.4.0

@kgdiff/scene@0.4.0

Choose a tag to compare

@github-actions github-actions released this 03 Nov 07:44
a03340d

Patch Changes

  • 86fe0da: Changes only is now a scope that combines with any mode instead of a fourth mode: mode is overlay | swipe | replay and the new scope (all | changes) shows only the changes, in overlay, swipe or replay alike. mode="changes" still works (overlay + scope="changes"), as do old #kgdiff=…;mode:changes links; kgdiff-mode reports { mode, scope }. The CLI gains --scope (--mode changes keeps working).

    The canvas loses its header bar: the title floats top left, the actions top right, and the modes, the Changes only toggle with its context hops, and replay's transport live in one dock at the bottom. The diffstat pills (the sidebar's filter chips show the same counts) and the second fit button are gone, the chips wear the legend's swatches, the legend starts collapsed and the minimap appears only while part of the graph is out of view. Unchanged node labels use the muted text color, so the changes stand out.

  • @kgdiff/core@0.4.0

    • @kgdiff/layout@0.4.0

@kgdiff/renderer@0.4.0

Choose a tag to compare

@github-actions github-actions released this 03 Nov 07:44
a03340d

Patch Changes

  • Updated dependencies [86fe0da]
    • @kgdiff/scene@0.4.0
    • @kgdiff/core@0.4.0

@kgdiff/layout@0.4.0

Choose a tag to compare

@github-actions github-actions released this 03 Nov 07:43
a03340d

Patch Changes

  • @kgdiff/core@0.4.0

@kgdiff/g6@0.4.0

Choose a tag to compare

@github-actions github-actions released this 03 Nov 07:44
a03340d

Patch Changes

  • Updated dependencies [86fe0da]
    • @kgdiff/scene@0.4.0
    • @kgdiff/core@0.4.0

@kgdiff/formats@0.4.0

Choose a tag to compare

@github-actions github-actions released this 03 Nov 07:43
a03340d

Patch Changes

  • @kgdiff/core@0.4.0

@kgdiff/core@0.4.0

Choose a tag to compare

@github-actions github-actions released this 03 Nov 07:43
a03340d

No changes in this release.