Skip to content

Commit bf71650

Browse files
authored
feat(docs): add em-dash + metadata validators (SD-2884, SD-2885) (#3054)
* fix(docs): sweep em-dashes at the source + add validator (SD-2885) The earlier final pass swept hand-written mdx for em-dashes but generated content (Document API reference, Document Engine SDKs overview) kept emitting them because the descriptions in packages/document-api/src/contract/operation-definitions.ts and related TS sources still contained em-dashes. This sweep covers: - packages/document-api/src/**/*.ts (excluding test files) - packages/document-api/scripts/lib/reference-docs-artifacts.ts (the placeholder em-dash for empty cells, now a hyphen) - apps/docs/scripts/generate-sdk-overview.ts (the hand-written prose blocks the generator splices into sdks.mdx) - apps/docs/document-engine/sdks.mdx (hand-written sections outside the generated marker block) - apps/docs/llms.txt and llms-full.txt - apps/docs/guides/migration/{prosemirror,breaking-changes-v1}.mdx (now visible under Resources > Upgrade guides) - apps/docs/snippets/components/*.jsx - apps/docs/docs.json banner text Regenerated reference docs are em-dash-free. Hidden pages, internal scripts, and the auto-generated openapi.json are left alone. Add scripts/validate-em-dashes.ts as a pre-commit lefthook to prevent the rule from drifting again. Skips frontmatter-hidden pages. Wired as docs-check-em-dashes. * feat(repo): add demos and examples metadata validator (SD-2884) Catches the class of drift surfaced during the SD-2873 audit: - Invalid demo-config.json (e.g. trailing comma) - Hardcoded /Users/<name>/ absolute paths in human-edited content - Stale docs.superdoc.dev URLs from the old IA (/modules, /core, /document-engine/ai-agents, /extensions/track-changes, etc.) Includes the immediate fixes the validator was written to enforce: - demos/toolbar/demo-config.json: trailing comma removed - examples/collaboration/{fastapi,liveblocks}/README.md: hardcoded /Users/nickjbernal/... paths replaced with relative or <repo-root> - Stale URL references across example READMEs swept to new IA paths (modules/* to editor/built-in-ui/*, core/* to editor/*, etc.) Wired as scripts/validate-examples-demos.ts plus a root check:examples-demos pnpm script and an examples-demos-validate lefthook pre-commit hook scoped to demos/** and examples/**. Companion to validate-em-dashes.ts and validate-icons.ts. The same pattern catches metadata drift before deploy. * fix(docs): address PR #3054 review findings (SD-2885) Five fixes flagged in code review: - apps/docs/document-engine/sdks.mdx: the em-dash sweep over the collaboration parameter table replaced 'no default' em-dash placeholders with literal colons (rendering as ': ' in the Default column). Replace with the word 'none' so the cells read as parameters with no default. - apps/docs/document-engine/sdks.mdx: a paired-em-dash parenthetical ('at workflow boundaries -- after opening, after edits, or before saving -- not in a polling loop') became two colons. Rewrite using parentheses, which the brand voice guide explicitly allows. - apps/docs/docs.json: the banner lost its separator after em-dash removal, leaving '**Introducing Document Engine** edit DOCX files...' as a run-on phrase. Add a period inside the bold so it reads as a proper sentence. - apps/docs/scripts/generate-sdk-overview.ts: an aligned ASCII comment block had paired colons after the sweep. Use hyphens to restore the intended column-separator look. - apps/docs/scripts/validate-em-dashes.ts: the hidden-page skip regex matched 'hidden: true' anywhere in the file body. Tighten to parse the YAML frontmatter block strictly via readFrontmatter(). Plus an extension flagged by Codex: the validator now also scans apps/docs/scripts/generate-sdk-overview.ts and packages/document-api/ src/contract/operation-definitions.ts -- both feed user-facing copy into the rendered docs through gen:all. A future em-dash added to either source will fail the check before deploy. Lefthook glob expanded to trigger on those paths.
1 parent 3e09cbe commit bf71650

135 files changed

Lines changed: 925 additions & 456 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/docs/docs.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@
289289
]
290290
},
291291
"banner": {
292-
"content": "**Introducing Document Engine** — edit DOCX files from code, CLI, SDKs, or AI agents. [Read the announcement →](https://www.superdoc.dev/changelog/2026-03-22-document-engine)",
292+
"content": "**Introducing Document Engine.** Edit DOCX files from code, CLI, SDKs, or AI agents. [Read the announcement →](https://www.superdoc.dev/changelog/2026-03-22-document-engine)",
293293
"dismissible": true
294294
},
295295
"redirects": [

apps/docs/document-api/reference/_generated-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1031,5 +1031,5 @@
10311031
}
10321032
],
10331033
"marker": "{/* GENERATED FILE: DO NOT EDIT. Regenerate via `pnpm run docapi:sync`. */}",
1034-
"sourceHash": "20f0873e29e8589387d0776cc53e6eea8d5fce102a3eba9a47a183c49b5f0b13"
1034+
"sourceHash": "af052d54e8a9c6865036bd63d27bba6a68cfa748a96fed3682535771e99184d3"
10351035
}

apps/docs/document-api/reference/authorities/entries-insert.mdx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Returns an AuthorityEntryMutationResult indicating success with the entry addres
2929
| `at` | TextTarget | yes | TextTarget |
3030
| `at.kind` | `"text"` | yes | Constant: `"text"` |
3131
| `at.segments` | TextSegment[] | yes | |
32+
| `at.story` | StoryLocator | no | StoryLocator |
3233
| `entry` | object | yes | |
3334
| `entry.bold` | boolean | no | |
3435
| `entry.category` | string \\| integer | yes | One of: string, integer |
@@ -50,7 +51,11 @@ Returns an AuthorityEntryMutationResult indicating success with the entry addres
5051
"start": 0
5152
}
5253
}
53-
]
54+
],
55+
"story": {
56+
"kind": "story",
57+
"storyType": "body"
58+
}
5459
},
5560
"entry": {
5661
"bold": true,

apps/docs/document-api/reference/bookmarks/get.mdx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ Returns a BookmarkInfo object with the bookmark's name, range, and optional tabl
3030
| `target.entityType` | `"bookmark"` | yes | Constant: `"bookmark"` |
3131
| `target.kind` | `"entity"` | yes | Constant: `"entity"` |
3232
| `target.name` | string | yes | |
33+
| `target.story` | StoryLocator | no | StoryLocator |
3334

3435
### Example request
3536

@@ -38,7 +39,11 @@ Returns a BookmarkInfo object with the bookmark's name, range, and optional tabl
3839
"target": {
3940
"entityType": "bookmark",
4041
"kind": "entity",
41-
"name": "example"
42+
"name": "example",
43+
"story": {
44+
"kind": "story",
45+
"storyType": "body"
46+
}
4247
}
4348
}
4449
```
@@ -80,6 +85,9 @@ _No fields._
8085
},
8186
"name": {
8287
"type": "string"
88+
},
89+
"story": {
90+
"$ref": "#/$defs/StoryLocator"
8391
}
8492
},
8593
"required": [

apps/docs/document-api/reference/bookmarks/insert.mdx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Returns a BookmarkMutationResult indicating success with the bookmark address or
2929
| `at` | TextTarget | yes | TextTarget |
3030
| `at.kind` | `"text"` | yes | Constant: `"text"` |
3131
| `at.segments` | TextSegment[] | yes | |
32+
| `at.story` | StoryLocator | no | StoryLocator |
3233
| `name` | string | yes | |
3334
| `tableColumn` | object | no | |
3435
| `tableColumn.colFirst` | integer | no | |
@@ -48,7 +49,11 @@ Returns a BookmarkMutationResult indicating success with the bookmark address or
4849
"start": 0
4950
}
5051
}
51-
]
52+
],
53+
"story": {
54+
"kind": "story",
55+
"storyType": "body"
56+
}
5257
},
5358
"name": "example",
5459
"tableColumn": {
@@ -68,6 +73,7 @@ Returns a BookmarkMutationResult indicating success with the bookmark address or
6873
| `bookmark.entityType` | `"bookmark"` | yes | Constant: `"bookmark"` |
6974
| `bookmark.kind` | `"entity"` | yes | Constant: `"entity"` |
7075
| `bookmark.name` | string | yes | |
76+
| `bookmark.story` | StoryLocator | no | StoryLocator |
7177
| `success` | `true` | yes | Constant: `true` |
7278

7379
### Variant 2 (success=false)
@@ -87,7 +93,11 @@ Returns a BookmarkMutationResult indicating success with the bookmark address or
8793
"bookmark": {
8894
"entityType": "bookmark",
8995
"kind": "entity",
90-
"name": "example"
96+
"name": "example",
97+
"story": {
98+
"kind": "story",
99+
"storyType": "body"
100+
}
91101
},
92102
"success": true
93103
}
@@ -161,6 +171,9 @@ Returns a BookmarkMutationResult indicating success with the bookmark address or
161171
},
162172
"name": {
163173
"type": "string"
174+
},
175+
"story": {
176+
"$ref": "#/$defs/StoryLocator"
164177
}
165178
},
166179
"required": [
@@ -231,6 +244,9 @@ Returns a BookmarkMutationResult indicating success with the bookmark address or
231244
},
232245
"name": {
233246
"type": "string"
247+
},
248+
"story": {
249+
"$ref": "#/$defs/StoryLocator"
234250
}
235251
},
236252
"required": [

apps/docs/document-api/reference/bookmarks/list.mdx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Returns a BookmarksListResult containing discovered bookmarks with address and d
2626

2727
| Field | Type | Required | Description |
2828
| --- | --- | --- | --- |
29+
| `in` | StoryLocator | no | StoryLocator |
2930
| `limit` | integer | no | |
3031
| `offset` | integer | no | |
3132

@@ -64,6 +65,9 @@ _No fields._
6465
{
6566
"additionalProperties": false,
6667
"properties": {
68+
"in": {
69+
"$ref": "#/$defs/StoryLocator"
70+
},
6771
"limit": {
6872
"minimum": 1,
6973
"type": "integer"

apps/docs/document-api/reference/bookmarks/remove.mdx

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ Returns a BookmarkMutationResult indicating success or a failure.
3030
| `target.entityType` | `"bookmark"` | yes | Constant: `"bookmark"` |
3131
| `target.kind` | `"entity"` | yes | Constant: `"entity"` |
3232
| `target.name` | string | yes | |
33+
| `target.story` | StoryLocator | no | StoryLocator |
3334

3435
### Example request
3536

@@ -38,7 +39,11 @@ Returns a BookmarkMutationResult indicating success or a failure.
3839
"target": {
3940
"entityType": "bookmark",
4041
"kind": "entity",
41-
"name": "example"
42+
"name": "example",
43+
"story": {
44+
"kind": "story",
45+
"storyType": "body"
46+
}
4247
}
4348
}
4449
```
@@ -53,6 +58,7 @@ Returns a BookmarkMutationResult indicating success or a failure.
5358
| `bookmark.entityType` | `"bookmark"` | yes | Constant: `"bookmark"` |
5459
| `bookmark.kind` | `"entity"` | yes | Constant: `"entity"` |
5560
| `bookmark.name` | string | yes | |
61+
| `bookmark.story` | StoryLocator | no | StoryLocator |
5662
| `success` | `true` | yes | Constant: `true` |
5763

5864
### Variant 2 (success=false)
@@ -72,7 +78,11 @@ Returns a BookmarkMutationResult indicating success or a failure.
7278
"bookmark": {
7379
"entityType": "bookmark",
7480
"kind": "entity",
75-
"name": "example"
81+
"name": "example",
82+
"story": {
83+
"kind": "story",
84+
"storyType": "body"
85+
}
7686
},
7787
"success": true
7888
}
@@ -106,6 +116,9 @@ Returns a BookmarkMutationResult indicating success or a failure.
106116
},
107117
"name": {
108118
"type": "string"
119+
},
120+
"story": {
121+
"$ref": "#/$defs/StoryLocator"
109122
}
110123
},
111124
"required": [
@@ -142,6 +155,9 @@ Returns a BookmarkMutationResult indicating success or a failure.
142155
},
143156
"name": {
144157
"type": "string"
158+
},
159+
"story": {
160+
"$ref": "#/$defs/StoryLocator"
145161
}
146162
},
147163
"required": [
@@ -212,6 +228,9 @@ Returns a BookmarkMutationResult indicating success or a failure.
212228
},
213229
"name": {
214230
"type": "string"
231+
},
232+
"story": {
233+
"$ref": "#/$defs/StoryLocator"
215234
}
216235
},
217236
"required": [

apps/docs/document-api/reference/bookmarks/rename.mdx

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Returns a BookmarkMutationResult indicating success with the updated bookmark ad
3131
| `target.entityType` | `"bookmark"` | yes | Constant: `"bookmark"` |
3232
| `target.kind` | `"entity"` | yes | Constant: `"entity"` |
3333
| `target.name` | string | yes | |
34+
| `target.story` | StoryLocator | no | StoryLocator |
3435

3536
### Example request
3637

@@ -40,7 +41,11 @@ Returns a BookmarkMutationResult indicating success with the updated bookmark ad
4041
"target": {
4142
"entityType": "bookmark",
4243
"kind": "entity",
43-
"name": "example"
44+
"name": "example",
45+
"story": {
46+
"kind": "story",
47+
"storyType": "body"
48+
}
4449
}
4550
}
4651
```
@@ -55,6 +60,7 @@ Returns a BookmarkMutationResult indicating success with the updated bookmark ad
5560
| `bookmark.entityType` | `"bookmark"` | yes | Constant: `"bookmark"` |
5661
| `bookmark.kind` | `"entity"` | yes | Constant: `"entity"` |
5762
| `bookmark.name` | string | yes | |
63+
| `bookmark.story` | StoryLocator | no | StoryLocator |
5864
| `success` | `true` | yes | Constant: `true` |
5965

6066
### Variant 2 (success=false)
@@ -74,7 +80,11 @@ Returns a BookmarkMutationResult indicating success with the updated bookmark ad
7480
"bookmark": {
7581
"entityType": "bookmark",
7682
"kind": "entity",
77-
"name": "example"
83+
"name": "example",
84+
"story": {
85+
"kind": "story",
86+
"storyType": "body"
87+
}
7888
},
7989
"success": true
8090
}
@@ -112,6 +122,9 @@ Returns a BookmarkMutationResult indicating success with the updated bookmark ad
112122
},
113123
"name": {
114124
"type": "string"
125+
},
126+
"story": {
127+
"$ref": "#/$defs/StoryLocator"
115128
}
116129
},
117130
"required": [
@@ -149,6 +162,9 @@ Returns a BookmarkMutationResult indicating success with the updated bookmark ad
149162
},
150163
"name": {
151164
"type": "string"
165+
},
166+
"story": {
167+
"$ref": "#/$defs/StoryLocator"
152168
}
153169
},
154170
"required": [
@@ -219,6 +235,9 @@ Returns a BookmarkMutationResult indicating success with the updated bookmark ad
219235
},
220236
"name": {
221237
"type": "string"
238+
},
239+
"story": {
240+
"$ref": "#/$defs/StoryLocator"
222241
}
223242
},
224243
"required": [

apps/docs/document-api/reference/citations/insert.mdx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Returns a CitationMutationResult indicating success with the citation address or
2929
| `at` | TextTarget | yes | TextTarget |
3030
| `at.kind` | `"text"` | yes | Constant: `"text"` |
3131
| `at.segments` | TextSegment[] | yes | |
32+
| `at.story` | StoryLocator | no | StoryLocator |
3233
| `sourceIds` | string[] | yes | |
3334

3435
### Example request
@@ -45,7 +46,11 @@ Returns a CitationMutationResult indicating success with the citation address or
4546
"start": 0
4647
}
4748
}
48-
]
49+
],
50+
"story": {
51+
"kind": "story",
52+
"storyType": "body"
53+
}
4954
},
5055
"sourceIds": [
5156
"example"

apps/docs/document-api/reference/comments/get.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ Returns a CommentInfo object with the comment text, author, date, and thread met
5656
| `target` | TextTarget | no | TextTarget |
5757
| `target.kind` | `"text"` | no | Constant: `"text"` |
5858
| `target.segments` | TextSegment[] | no | |
59+
| `target.story` | StoryLocator | no | StoryLocator |
5960
| `text` | string | no | |
6061

6162
### Example response

0 commit comments

Comments
 (0)