diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 0215369..a997bfc 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -39,6 +39,9 @@ jobs: # Zola fails the build on broken internal links. run: zola build + - name: Verify editor, demo outputs and publication downloads + run: python3 -m unittest discover -s scripts -p 'test_*.py' -v + - name: Verify the build produced pages run: | pages=$(find public -name '*.html' | wc -l) @@ -64,4 +67,4 @@ jobs: uses: actions/checkout@v6 - name: Verify advertised downloads exist on the public channel - run: python3 scripts/check-release-links.py \ No newline at end of file + run: python3 scripts/check-release-links.py diff --git a/config.toml b/config.toml index 8878c85..d8014fe 100644 --- a/config.toml +++ b/config.toml @@ -51,7 +51,7 @@ include_content = true [extra] version = "1.21.16" -release_version = "1.21.18" +release_version = "1.21.19" navbar_items = [ { code = "en", nav_items = [ diff --git a/content/how-tos/synonym-search.md b/content/how-tos/synonym-search.md index 32bf89a..8ca51cc 100644 --- a/content/how-tos/synonym-search.md +++ b/content/how-tos/synonym-search.md @@ -5,6 +5,8 @@ date = 2026-10-11 [taxonomies] categories = ["How-tos"] tags = ["editor", "knowledge-graph", "search"] +[extra] +social_image = "/demos/synonym-search/poster.jpg" +++ Your project brief says **risk**. Later, you search for **concern**. Terraphim connects the two so a change of wording does not hide the decisions you need. @@ -32,12 +34,12 @@ Download the graph and the clean text. This explicitly shares the document's aut Use the graph downloaded from that editing session: ```sh -terraphim-grep concern --thesaurus knowledge-graph.json --paths corpus -C 2 --json +terraphim-grep concern --thesaurus knowledge-graph.json --paths corpus -C 2 --search-only --json ``` The actual result contains three risk passages and their related decisions, with file and line locations. No generated answer is requested. -Add `--answer` to the same command for synthesis: +Replace `--search-only` with `--answer` for synthesis: ```sh terraphim-grep concern --thesaurus knowledge-graph.json --paths corpus -C 2 --json --answer @@ -54,9 +56,17 @@ Editing and local search use your local data. Optional synthesis sends the retri - [Saved Markdown with alternatives](/demos/synonym-search/annotated.md) - [Actual result without synthesis](/demos/synonym-search/without-synthesis.json) - [Actual result with synthesis](/demos/synonym-search/with-synthesis.json) +- [Download the complete example ZIP](/demos/synonym-search/synonym-search-example.zip), including a step-by-step README +- [English subtitles (SRT)](/demos/synonym-search/captions.srt) The community garden brief is authored public sample input. The alternatives, downloaded graph, retrieved passages and generated answer are actual outputs. The command-line section displays those JSON fields in a readable presentation; it is not a separate Terraphim interface. The voice is synthetic British English (Emma). Setup is omitted, and the recorded interaction runs at its original speed. [Recording details and file identities](/demos/synonym-search/manifest.json). -This is a preview of the new export and search flow. It uses the [editor graph-sharing candidate](https://git.terraphim.cloud/terraphim/terraphim-editor/pulls/131) and the [grep synonym/synthesis candidate](https://git.terraphim.cloud/terraphim/terraphim-clients/pulls/385); older installed binaries may differ. A fresh synthesis run may produce different wording. +## Reproduce it with released builds + +The recording preserves its original candidate-build identities. The same flow was separately verified on 12 October 2026 using the published [Editor v0.1.0-rc.1 prerelease](https://github.com/terraphim/terraphim-editor/releases/tag/v0.1.0-rc.1) and [terraphim-grep v1.21.19](https://github.com/terraphim/terraphim-clients/releases/tag/v1.21.19). The editor is still an RC; the video is not a claim that every host or feature is fully qualified. + +Download the example ZIP, extract it, and follow `README.md`. It uses the same graph and clean brief as the recording. Verify `terraphim-grep --version` before running the two commands above. The release includes macOS and Linux builds; Windows is not claimed by this example. + +Inspect the separate released-binary outputs: [before sharing the synonym graph](/demos/synonym-search/released-before-sharing.json), [without synthesis](/demos/synonym-search/released-without-synthesis.json), and [with synthesis](/demos/synonym-search/released-with-synthesis.json). The baseline used the editor's default role, which lacks the authored synonym: zero passages became three when the exported graph was supplied. The paired modes retrieved the same passages. [Released-build identities, commands and file checksums](/demos/synonym-search/reproduction.json) distinguish this verification from the original recording. A fresh synthesis run may produce different wording. [Earlier browser and Zed host walkthroughs](/how-tos/knowledge-work-editor/) retain their own recorded versions and limitations. This focused story does not qualify all 41 source-video requirements. The Zed fork remains separate. diff --git a/scripts/test_synonym_publication.py b/scripts/test_synonym_publication.py new file mode 100644 index 0000000..596f4ee --- /dev/null +++ b/scripts/test_synonym_publication.py @@ -0,0 +1,80 @@ +"""Exercise the built page and the downloadable reproduction kit.""" +import hashlib +from html.parser import HTMLParser +import json +from pathlib import Path +import subprocess +import tempfile +import unittest +import zipfile + +ROOT = Path(__file__).resolve().parents[1] +MEDIA = ROOT / "static/demos/synonym-search" + + +class HeadParser(HTMLParser): + def __init__(self): + super().__init__() + self.meta = {} + self.canonicals = [] + + def handle_starttag(self, tag, attrs): + attrs = dict(attrs) + if tag == "meta": + self.meta[attrs.get("property", attrs.get("name"))] = attrs.get("content") + if tag == "link" and attrs.get("rel") == "canonical": + self.canonicals.append(attrs["href"]) + + +class PublicationTests(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls.output = tempfile.TemporaryDirectory() + built = Path(cls.output.name) / "site" + subprocess.run(["zola", "build", "--output-dir", str(built)], cwd=ROOT, check=True, text=True) + cls.html = (built / "how-tos/synonym-search/index.html").read_text() + + @classmethod + def tearDownClass(cls): + cls.output.cleanup() + + def test_production_metadata_and_privacy_wording(self): + head = HeadParser() + head.feed(self.html) + url = "https://terraphim.ai/how-tos/synonym-search/" + self.assertEqual(head.canonicals, [url]) + self.assertEqual(head.meta["og:url"], url) + self.assertEqual(head.meta["og:title"], "Different words. The same idea.") + self.assertEqual(head.meta["og:image"], "https://terraphim.ai/demos/synonym-search/poster.jpg") + self.assertEqual(head.meta["twitter:card"], "summary_large_image") + self.assertNotIn("All data processed locally", self.html) + self.assertIn("Optional synthesis uses your configured model provider", self.html) + self.assertNotIn("editor graph-sharing candidate", self.html) + self.assertIn("v0.1.0-rc.1", self.html) + self.assertIn("v1.21.19", self.html) + + def test_released_evidence_and_bundle_match_actual_files(self): + receipt = json.loads((MEDIA / "reproduction.json").read_text()) + self.assertEqual(receipt["grepVersion"], "1.21.19") + self.assertEqual(receipt["editorVersion"], "0.1.0-rc.1") + before = json.loads((MEDIA / "released-before-sharing.json").read_text()) + off = json.loads((MEDIA / "released-without-synthesis.json").read_text()) + on = json.loads((MEDIA / "released-with-synthesis.json").read_text()) + self.assertEqual(before["chunks"], []) + self.assertEqual(off["chunks"], on["chunks"]) + self.assertEqual(len(off["chunks"]), 3) + self.assertIsNone(off["answer"]) + self.assertTrue(on["answer"]["answer"]) + self.assertEqual(len(on["answer"]["citations"]), 3) + with zipfile.ZipFile(MEDIA / "synonym-search-example.zip") as bundle: + self.assertEqual(set(bundle.namelist()), set(receipt["bundleFiles"])) + for name in receipt["bundleFiles"]: + self.assertEqual(bundle.read(name), (MEDIA / name).read_bytes()) + for item in receipt["files"]: + self.assertEqual(hashlib.sha256((MEDIA / item["file"]).read_bytes()).hexdigest(), item["sha256"]) + for name in ["reproduction.json", "synonym-search-example.zip", "captions.srt"]: + self.assertIn("/demos/synonym-search/" + name, self.html) + + +if __name__ == "__main__": + unittest.main() diff --git a/static/demos/synonym-search/README.md b/static/demos/synonym-search/README.md new file mode 100644 index 0000000..3ae366e --- /dev/null +++ b/static/demos/synonym-search/README.md @@ -0,0 +1,70 @@ +# Different words. The same idea. + +Source: https://terraphim.ai/how-tos/synonym-search/ + +This kit contains the actual graph and clean brief exported in the 80-second +recording, and separate evidence from released builds. The brief is public sample +input. The graph and search results are actual outputs. + +## Reproduce local retrieval + +1. Download terraphim-grep v1.21.19 for your macOS or Linux architecture: + https://github.com/terraphim/terraphim-clients/releases/tag/v1.21.19 + Check the archive against that release's SHA256SUMS, then extract it and put + terraphim-grep on PATH. No Windows build is claimed by this kit. +2. In this extracted directory, run: + +```sh +terraphim-grep --version +mkdir -p corpus +cp project-brief.md corpus/project-brief.md +terraphim-grep concern --thesaurus baseline-role.json --paths corpus -C 2 --search-only --json +terraphim-grep concern --thesaurus knowledge-graph.json --paths corpus -C 2 --search-only --json +``` + +The first search uses the editor's default role, which lacks this authored +synonym. It returns zero passages. The exported graph connects Risk and Concern; +the second search returns three Risk passages even though Concern is absent +from the clean brief. `released-before-sharing.json` and +`released-without-synthesis.json` contain those actual outputs. + +## Compare optional synthesis + +Configure a model provider using the client release documentation. Then run: + +```sh +terraphim-grep concern --thesaurus knowledge-graph.json --paths corpus -C 2 --json --answer +``` + +Optional synthesis sends the retrieved passages to your configured model +provider and may incur provider charges. The released verification used +DeepSeek (deepseek-v4-flash-0731). No credentials are included. Generated wording +can vary. Compare the chunks and citations, not an exact answer string: +`released-with-synthesis.json` has the same three chunks as the search-only run. +Decisions in the source do not prove that the actions have been completed. + +## Recreate the editor export + +Use https://terraphim.ai/editor/ or the published v0.1.0-rc.1 editor prerelease: +https://github.com/terraphim/terraphim-editor/releases/tag/v0.1.0-rc.1 + +Open the brief, add Concern as an alternative to Risk, swap between them, and +retain Risk in the final text. Choose Knowledge graph from the Markdown export +menu. The definition is `synonyms:: Risk, Concern`. Export the graph and clean +text, then use your exported filenames in the commands above. This explicitly +shares document synonyms; it does not silently update the active role. +`annotated.md` preserves the alternatives for reopening. + +## Provenance + +- `manifest.json`, `without-synthesis.json`, and `with-synthesis.json` describe + the original candidate-build recording. They have not been relabelled as + released-binary evidence. +- `reproduction.json` and the `released-*.json` files describe the separate + v0.1.0-rc.1 / v1.21.19 verification on 12 October 2026. +- `captions.vtt`, `captions.srt`, and `transcript.txt` accompany the original video. + The British female narration is synthetic (Emma, Kokoro). +- Video and poster are available on the source page; they are not in this ZIP. + +This focused flow does not qualify all 41 requirements or every extension. +The Zed fork remains separate. diff --git a/static/demos/synonym-search/baseline-role.json b/static/demos/synonym-search/baseline-role.json new file mode 100644 index 0000000..a8c1b2c --- /dev/null +++ b/static/demos/synonym-search/baseline-role.json @@ -0,0 +1,91 @@ +{ + "name": "terraphim-editor-default", + "data": { + "alternative": { + "id": 100, + "nterm": "alternatives" + }, + "alternatives": { + "id": 100, + "nterm": "alternatives" + }, + "caf\u00e9": { + "id": 4, + "nterm": "caf\u00e9" + }, + "choice": { + "id": 1, + "nterm": "decision" + }, + "coffee shop": { + "id": 4, + "nterm": "caf\u00e9" + }, + "coffeehouse": { + "id": 4, + "nterm": "caf\u00e9" + }, + "decision": { + "id": 1, + "nterm": "decision" + }, + "employ": { + "id": 8, + "nterm": "use" + }, + "eraser": { + "id": 2, + "nterm": "eraser" + }, + "honour": { + "id": 5, + "nterm": "honour" + }, + "judgment": { + "id": 1, + "nterm": "decision" + }, + "large language model": { + "id": 3, + "nterm": "llm", + "display_value": "LLM" + }, + "llm": { + "id": 3, + "nterm": "llm", + "display_value": "LLM" + }, + "option": { + "id": 1, + "nterm": "decision" + }, + "options set": { + "id": 100, + "nterm": "alternatives" + }, + "paperclip": { + "id": 7, + "nterm": "paperclip" + }, + "privilege": { + "id": 5, + "nterm": "honour" + }, + "rubber": { + "id": 2, + "nterm": "eraser" + }, + "use": { + "id": 8, + "nterm": "use" + }, + "utilise": { + "id": 8, + "nterm": "use" + }, + "variants": { + "id": 100, + "nterm": "alternatives" + } + } +} diff --git a/static/demos/synonym-search/captions.srt b/static/demos/synonym-search/captions.srt new file mode 100644 index 0000000..42e48a8 --- /dev/null +++ b/static/demos/synonym-search/captions.srt @@ -0,0 +1,75 @@ +1 +00:00:00,250 --> 00:00:04,443 +When people use different words for the same idea, useful decisions can + +2 +00:00:04,443 --> 00:00:06,190 +become surprisingly hard to find. + +3 +00:00:07,250 --> 00:00:10,852 +Here is our community garden brief. It records three risks, and the + +4 +00:00:10,852 --> 00:00:13,553 +decisions we have made to deal with each one. + +5 +00:00:15,250 --> 00:00:18,996 +I add concern as an alternative to risk. Now I can swap + +6 +00:00:18,996 --> 00:00:22,742 +between the two words, choosing the wording that fits without losing the + +7 +00:00:22,742 --> 00:00:23,366 +other option. + +8 +00:00:26,250 --> 00:00:30,840 +The editor connects those alternatives to one idea in the knowledge graph. + +9 +00:00:30,840 --> 00:00:35,047 +Here is the actual synonym definition: risk and concern belong together. + +10 +00:00:37,250 --> 00:00:41,059 +I download that graph and the finished text. Notice that I leave + +11 +00:00:41,059 --> 00:00:43,915 +risk in the document. The word concern is absent. + +12 +00:00:46,250 --> 00:00:50,497 +Now I search for concern using the graph I just downloaded. It + +13 +00:00:50,497 --> 00:00:54,744 +finds all three risk passages, including the related decisions, even though the + +14 +00:00:54,744 --> 00:00:55,805 +wording is different. + +15 +00:00:58,250 --> 00:01:02,632 +Without synthesis, I get the original passages and their locations. Adding the + +16 +00:01:02,632 --> 00:01:07,014 +answer flag gives me a summary from the same evidence, with source + +17 +00:01:07,014 --> 00:01:07,379 +references. + +18 +00:01:10,250 --> 00:01:14,735 +The summary keeps decisions distinct from completed actions. From choosing a word + +19 +00:01:14,735 --> 00:01:19,219 +to finding a decision, the same knowledge graph keeps the meaning connected. diff --git a/static/demos/synonym-search/released-before-sharing.json b/static/demos/synonym-search/released-before-sharing.json new file mode 100644 index 0000000..e88fb9a --- /dev/null +++ b/static/demos/synonym-search/released-before-sharing.json @@ -0,0 +1,13 @@ +{ + "chunks": [], + "answer": null, + "concepts": [], + "sufficiency": "RlmInsufficient", + "sufficiency_explanation": "No chunks or knowledge-graph concepts matched the query; there is nothing to synthesise an answer from.", + "stats": { + "search_latency_ms": 4, + "rlm_latency_ms": null, + "chunks_returned": 0, + "kg_hits": 0 + } +} diff --git a/static/demos/synonym-search/released-with-synthesis.json b/static/demos/synonym-search/released-with-synthesis.json new file mode 100644 index 0000000..7776363 --- /dev/null +++ b/static/demos/synonym-search/released-with-synthesis.json @@ -0,0 +1,71 @@ +{ + "chunks": [ + { + "content": "Risk: Timber may arrive late. Decision: Keep a backup supplier.", + "source": "project-brief.md", + "line_start": 7, + "line_end": 7, + "relevance_score": 2.0, + "haystack": "code" + }, + { + "content": "Risk: Rain may delay planting. Decision: Reserve a covered area.", + "source": "project-brief.md", + "line_start": 10, + "line_end": 10, + "relevance_score": 2.0, + "haystack": "code" + }, + { + "content": "Risk: Volunteers may cancel. Decision: Keep a reserve list.", + "source": "project-brief.md", + "line_start": 13, + "line_end": 13, + "relevance_score": 2.0, + "haystack": "code" + } + ], + "answer": { + "answer": "The project brief records three concerns/risks, each paired with a decision. It does not establish whether any of these decisions have been implemented or completed. The concerns are: timber may arrive late, rain may delay planting, and volunteers may cancel. The corresponding decisions are: keep a backup supplier, reserve a covered area, and keep a reserve list.", + "citations": [ + { + "source": "project-brief.md", + "line": 7, + "excerpt": "Risk: Timber may arrive late. Decision: Keep a backup supplier." + }, + { + "source": "project-brief.md", + "line": 10, + "excerpt": "Risk: Rain may delay planting. Decision: Reserve a covered area." + }, + { + "source": "project-brief.md", + "line": 13, + "excerpt": "Risk: Volunteers may cancel. Decision: Keep a reserve list." + } + ], + "confidence": 1.0 + }, + "concepts": [ + { + "id": 0, + "name": "concern", + "display_value": null, + "score": 1.0 + }, + { + "id": 0, + "name": "risk", + "display_value": null, + "score": 1.0 + } + ], + "sufficiency": "RlmSynthesis", + "sufficiency_explanation": "Found 3 chunks (coverage 1.00, KG confidence 1.00); the answer was synthesised by the LLM in 15349ms.", + "stats": { + "search_latency_ms": 15354, + "rlm_latency_ms": 15349, + "chunks_returned": 3, + "kg_hits": 2 + } +} diff --git a/static/demos/synonym-search/released-without-synthesis.json b/static/demos/synonym-search/released-without-synthesis.json new file mode 100644 index 0000000..3d1b2b5 --- /dev/null +++ b/static/demos/synonym-search/released-without-synthesis.json @@ -0,0 +1,51 @@ +{ + "chunks": [ + { + "content": "Risk: Timber may arrive late. Decision: Keep a backup supplier.", + "source": "project-brief.md", + "line_start": 7, + "line_end": 7, + "relevance_score": 2.0, + "haystack": "code" + }, + { + "content": "Risk: Rain may delay planting. Decision: Reserve a covered area.", + "source": "project-brief.md", + "line_start": 10, + "line_end": 10, + "relevance_score": 2.0, + "haystack": "code" + }, + { + "content": "Risk: Volunteers may cancel. Decision: Keep a reserve list.", + "source": "project-brief.md", + "line_start": 13, + "line_end": 13, + "relevance_score": 2.0, + "haystack": "code" + } + ], + "answer": null, + "concepts": [ + { + "id": 0, + "name": "concern", + "display_value": null, + "score": 1.0 + }, + { + "id": 0, + "name": "risk", + "display_value": null, + "score": 1.0 + } + ], + "sufficiency": "SearchOnly", + "sufficiency_explanation": "Found 3 chunks but diversity 1 < 2; returning search results only (pass --answer or --force-rlm to synthesise).", + "stats": { + "search_latency_ms": 2, + "rlm_latency_ms": null, + "chunks_returned": 3, + "kg_hits": 2 + } +} diff --git a/static/demos/synonym-search/reproduction.json b/static/demos/synonym-search/reproduction.json new file mode 100644 index 0000000..e174a56 --- /dev/null +++ b/static/demos/synonym-search/reproduction.json @@ -0,0 +1,152 @@ +{ + "schema": 1, + "verifiedAt": "2026-10-12", + "source": "https://terraphim.ai/how-tos/synonym-search/", + "editorVersion": "0.1.0-rc.1", + "grepVersion": "1.21.19", + "editorSourceHead": "05d0aa50151c131db4a3b30b56aba67c00add5fc", + "clientsSourceHead": "2d1820e81d2a9458d4d5eca012e7d0e0d2accf49", + "editorArchiveSha256": "a514f45276397b93f38d8e14c9e3bde6203bd9c625bc13c81829de31ffa9eb79", + "grepMacArmArchiveSha256": "2e9c8fc8b54124458a54120134ae5437f8b7e023df28fc1d515dd059c8f86a3e", + "checks": { + "graphSha256": "f8648b16470e764bdff5c95064078419d71e8d41d2ca30d4b1508017c166a45d", + "textSha256": "ea78a26e4d5a1105891bed67288a924cbbd5656defc95de4c511f4302b8d0d8f", + "binarySha256": "ce20e2bf87c6753c717dade4ac7baac98b05d0be9cb39af1f3afbcbf6e5c47de", + "binaryVersion": "terraphim-grep 1.21.19", + "status": "PASS", + "literalConcernAbsent": true, + "beforeSharingNoResults": true, + "aliasRetrieval": true, + "sameRetrievedChunks": true, + "sourceExcerptsExact": true, + "actualSynthesis": true, + "provider": "deepseek/deepseek-v4-flash-0731" + }, + "commands": [ + [ + "terraphim-grep", + "concern", + "--thesaurus", + "baseline-role.json", + "--paths", + "corpus", + "-C", + "2", + "--json", + "--search-only" + ], + [ + "terraphim-grep", + "concern", + "--thesaurus", + "knowledge-graph.json", + "--paths", + "corpus", + "-C", + "2", + "--json", + "--search-only" + ], + [ + "terraphim-grep", + "concern", + "--thesaurus", + "knowledge-graph.json", + "--paths", + "corpus", + "-C", + "2", + "--json", + "--answer" + ] + ], + "bundleFiles": [ + "README.md", + "annotated.md", + "baseline-role.json", + "knowledge-graph.json", + "project-brief.md", + "without-synthesis.json", + "with-synthesis.json", + "released-before-sharing.json", + "released-without-synthesis.json", + "released-with-synthesis.json", + "captions.vtt", + "captions.srt", + "transcript.txt", + "manifest.json", + "reproduction.json" + ], + "files": [ + { + "file": "README.md", + "bytes": 3267, + "sha256": "f4ac5c7d681ad5a99e688da04575bf21aae2cdc1dfded4395c7a20ee3b5d07fb" + }, + { + "file": "annotated.md", + "bytes": 793, + "sha256": "036d8e65b847fc03c68814b610be94e2b7a27573188947451348f9f674150e6e" + }, + { + "file": "baseline-role.json", + "bytes": 1506, + "sha256": "e850422ec72faa06aae0d6c2893a9f1d2e36d60a5aef79bd8f863daa2d71b015" + }, + { + "file": "knowledge-graph.json", + "bytes": 281, + "sha256": "f8648b16470e764bdff5c95064078419d71e8d41d2ca30d4b1508017c166a45d" + }, + { + "file": "project-brief.md", + "bytes": 265, + "sha256": "ea78a26e4d5a1105891bed67288a924cbbd5656defc95de4c511f4302b8d0d8f" + }, + { + "file": "without-synthesis.json", + "bytes": 1248, + "sha256": "302eb12c12e9f8a68daca280ee783c152221214969d630929d4666c5236c5365" + }, + { + "file": "with-synthesis.json", + "bytes": 2288, + "sha256": "d6381390ae7ce09b91cf406195b01ade90a753aad72594a7c3a1676443bf5b82" + }, + { + "file": "released-before-sharing.json", + "bytes": 344, + "sha256": "c79167288ff37166e9bb9e6c0d19bab2b86454d959db13680e3786349e58b7ae" + }, + { + "file": "released-without-synthesis.json", + "bytes": 1247, + "sha256": "6dd67609b8443b6f750788988d1d2433b83cb8e8016654424fab07ccb073570c" + }, + { + "file": "released-with-synthesis.json", + "bytes": 2151, + "sha256": "722bdd2b8aaf6e5f9910b8fecb84ae39ccb6d7dabd2a61a87b767e5347210352" + }, + { + "file": "captions.vtt", + "bytes": 1704, + "sha256": "8c1c3013e992032bcc8fa93c72718303bdc9e492142feaede595c70d2292cf28" + }, + { + "file": "captions.srt", + "bytes": 1744, + "sha256": "1842758bdc5b65be32400f47d8fb71401759f3826ecaa01621a3e5f03d084173" + }, + { + "file": "transcript.txt", + "bytes": 1540, + "sha256": "1eb1999a04add460c1474a2889e7fb12238b0cafd07a77ef6246ad97ce07c9b4" + }, + { + "file": "manifest.json", + "bytes": 4236, + "sha256": "af6ff6f0719b560d0eee3c71a3ba60ffed81857185ff1817f9839729ad170f9b" + } + ] +} diff --git a/static/demos/synonym-search/synonym-search-example.zip b/static/demos/synonym-search/synonym-search-example.zip new file mode 100644 index 0000000..61821c0 Binary files /dev/null and b/static/demos/synonym-search/synonym-search-example.zip differ diff --git a/themes/WarpDrive/templates/base.html b/themes/WarpDrive/templates/base.html index e789fc1..8cdf7c9 100644 --- a/themes/WarpDrive/templates/base.html +++ b/themes/WarpDrive/templates/base.html @@ -35,6 +35,31 @@ {% endblock title %} + {% set share_title = config.title %} + {% set share_description = config.description %} + {% set share_image = config.base_url ~ "/images/terraphim_logo.png" %} + {% if page %} + {% set share_title = page.title %} + {% if page.description %}{% set share_description = page.description %}{% endif %} + {% if page.extra.social_image %}{% set share_image = config.base_url ~ page.extra.social_image %}{% endif %} + {% elif section %} + {% if section.title %}{% set share_title = section.title %}{% endif %} + {% if section.description %}{% set share_description = section.description %}{% endif %} + {% endif %} + {% set canonical_path = current_path | default(value="/404.html") %} + {% set canonical = config.base_url ~ canonical_path %} + + + + + + + + + + + + {% if config.extra.analytics.google %}