Skip to content

Commit 74bd840

Browse files
louis-preclaudeseambot
authored
Add HTML link checking, move files to match SUMMARY nesting, fix all broken links (#1091)
* Extend link and path validators to check HTML links and SUMMARY nesting - Add HTML <a href> link checking to validate-links (both relative and absolute docs.seam.co URLs) - Stop absolute URL pattern at quote characters for HTML compatibility - Extend validate-paths to check that nested SUMMARY.md entries have file paths under their parent's directory, matching how GitBook builds published URLs from the tree structure Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Move files to match SUMMARY.md nesting for correct published URLs GitBook derives published URLs from SUMMARY.md tree nesting. Files nested under a parent must live in the parent's directory. Moved 10 brand-guide get-started pages into their parent directories and 2 guides files. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Fix all broken HTML links and asset paths Fix broken links found by the new HTML link checker: - Fix asset paths in brand-guides (wrong ../ depth after section move) - Fix cross-section asset refs pointing to guides/.gitbook/assets/ - Fix brand-guides/README.md card links to use correct local paths - Fix guides/README.md card links with correct absolute URLs - Fix cross-section API and capability guide links - Fix internal links broken by file moves Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ci: Format code --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Seam Bot <seambot@getseam.com>
1 parent c5e83c9 commit 74bd840

78 files changed

Lines changed: 215 additions & 127 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.

codegen/validate-links.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ function findSiteSection(filePath: string): SiteSection | undefined {
1313
}
1414

1515
const absoluteUrlPattern = new RegExp(
16-
`${baseUrl.replaceAll('.', '\\.')}[^)\\s]+`,
16+
`${baseUrl.replaceAll('.', '\\.')}[^)"\\s]+`,
1717
'g',
1818
)
1919

@@ -23,6 +23,15 @@ const absoluteUrlPattern = new RegExp(
2323
const relativeLinkPattern =
2424
/(?<!!)\]\((?!https?:\/\/|mailto:|#|{%|<|cursor:|file:)((?:[^)\\]|\\.)+)\)/g
2525

26+
// Matches HTML links like <a href="path"> but not external URLs or anchors.
27+
const htmlRelativeLinkPattern = /<a\s+href="(?!https?:\/\/|mailto:|#)([^"]+)"/g
28+
29+
// Matches HTML links with absolute docs.seam.co URLs.
30+
const htmlAbsoluteUrlPattern = new RegExp(
31+
`<a\\s+href="(${baseUrl.replaceAll('.', '\\.')}[^"]+)"`,
32+
'g',
33+
)
34+
2635
interface BrokenLink {
2736
file: string
2837
line: number
@@ -160,6 +169,20 @@ for (const file of files) {
160169
if (rawLink == null) continue
161170
checkRelativeLink(file, i + 1, rawLink)
162171
}
172+
173+
// Check HTML href links (relative)
174+
for (const match of lineText.matchAll(htmlRelativeLinkPattern)) {
175+
const rawLink = match[1]
176+
if (rawLink == null) continue
177+
checkRelativeLink(file, i + 1, rawLink)
178+
}
179+
180+
// Check HTML href links (absolute docs.seam.co URLs)
181+
for (const match of lineText.matchAll(htmlAbsoluteUrlPattern)) {
182+
const rawUrl = match[1]
183+
if (rawUrl == null) continue
184+
checkAbsoluteUrl(file, i + 1, rawUrl)
185+
}
163186
}
164187
}
165188

codegen/validate-paths.ts

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,18 @@ function slugify(heading: string): string {
1818
.trim()
1919
}
2020

21+
function slugFromPath(linkPath: string): string {
22+
return (
23+
linkPath
24+
.replace(/README\.md$/, '')
25+
.replace(/\.md$/, '')
26+
.replace(/\/$/, '')
27+
.split('/')
28+
.filter(Boolean)
29+
.pop() ?? ''
30+
)
31+
}
32+
2133
interface PathMismatch {
2234
section: string
2335
line: number
@@ -37,6 +49,11 @@ for (const section of siteSections) {
3749

3850
let currentGroup: string | null = null
3951

52+
// Track nesting: each entry is { level, slug, path }
53+
// GitBook builds URLs by joining ancestor slugs, so child file paths
54+
// should be under their parent's directory.
55+
const parentStack: Array<{ level: number; slug: string; path: string }> = []
56+
4057
for (let i = 0; i < lines.length; i++) {
4158
const lineText = lines[i]
4259
if (lineText == null) continue
@@ -48,7 +65,14 @@ for (const section of siteSections) {
4865
continue
4966
}
5067

51-
for (const match of lineText.matchAll(summaryLinkPattern)) {
68+
// Only process list items
69+
const stripped = lineText.trimStart()
70+
if (!stripped.startsWith('* [')) continue
71+
72+
const indent = lineText.length - stripped.length
73+
const level = Math.floor(indent / 2)
74+
75+
for (const match of stripped.matchAll(summaryLinkPattern)) {
5276
const title = match[1] ?? ''
5377
const linkPath = match[2] ?? ''
5478

@@ -79,6 +103,47 @@ for (const section of siteSections) {
79103
reason: `Path should start with "${currentGroup}/" (listed under "## ${currentGroup}")`,
80104
})
81105
}
106+
107+
// Check 3: nested items should have paths under their parent's directory.
108+
// GitBook builds published URLs from the SUMMARY.md tree, so a child
109+
// nested under a parent gets a URL like /parent-slug/child-slug.
110+
// The file path must match this structure.
111+
// Trim stack to current level
112+
while (parentStack.length > 0) {
113+
const top = parentStack[parentStack.length - 1]
114+
if (top != null && top.level >= level) parentStack.pop()
115+
else break
116+
}
117+
118+
const slug = slugFromPath(linkPath)
119+
const parent =
120+
parentStack.length > 0 ? parentStack[parentStack.length - 1] : undefined
121+
122+
if (parent != null) {
123+
// The parent's path determines the expected directory prefix.
124+
// e.g., parent path "access_codes/simulate/README.md" means
125+
// children should start with "access_codes/simulate/".
126+
const parentDir = parent.path
127+
.replace(/README\.md$/, '')
128+
.replace(/\.md$/, '/')
129+
if (!linkPath.startsWith(parentDir)) {
130+
const publishedUrl =
131+
section.urlPrefix +
132+
'/' +
133+
[...parentStack.map((p) => p.slug), slug].join('/')
134+
mismatches.push({
135+
section: section.name,
136+
line: i + 1,
137+
title,
138+
path: linkPath,
139+
reason: `Path should start with "${parentDir}" to match published URL ${publishedUrl}`,
140+
})
141+
}
142+
}
143+
144+
if (slug !== '') {
145+
parentStack.push({ level, slug, path: linkPath })
146+
}
82147
}
83148
}
84149
}

docs/brand-guides/2n-intercom-systems/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ The setup guide covers:
3636
* Creating API credentials
3737
* Connecting to Seam through the Connect Webview
3838

39-
<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-cover data-type="image">Cover image</th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>System Set Up Guide</strong></td><td><a href="../../.gitbook/assets/image (29).png">image (29).png</a></td><td><a href="./2n-system-set-up-instructions.md">2n-system-set-up-instructions.md</a></td></tr></tbody></table>
39+
<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-cover data-type="image">Cover image</th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>System Set Up Guide</strong></td><td><a href="../.gitbook/assets/image (29).png">image (29).png</a></td><td><a href="./2n-system-set-up-instructions.md">2n-system-set-up-instructions.md</a></td></tr></tbody></table>
4040

4141
***
4242

@@ -52,4 +52,4 @@ For more details, see [Customize Brands in Connect Webviews](https://docs.seam.c
5252

5353
Find your local 2N distributor using the following page:
5454

55-
<table data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td></td><td><strong>Locate Your 2N Distributor</strong></td><td></td><td><a href="https://www.2n.com/en_GB/how-to-buy/where-to-buy">https://www.2n.com/en_GB/how-to-buy/where-to-buy</a></td><td><a href="../../.gitbook/assets/2n-logo.png">2n-logo.png</a></td></tr></tbody></table>
55+
<table data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td></td><td><strong>Locate Your 2N Distributor</strong></td><td></td><td><a href="https://www.2n.com/en_GB/how-to-buy/where-to-buy">https://www.2n.com/en_GB/how-to-buy/where-to-buy</a></td><td><a href="../.gitbook/assets/2n-logo.png">2n-logo.png</a></td></tr></tbody></table>

docs/brand-guides/2n-intercom-systems/get-started-with-2n-intercoms.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -575,11 +575,11 @@ Now that you've completed this guide, you can try to connect a real 2N device. T
575575

576576
In addition, if you'd like to explore other aspects of Seam, here is a list of helpful resources:
577577

578-
* [Yale Getting Started Guide](../get-started-with-yale-locks.md)
579-
* [August Getting Started Guide](../get-started-with-august-locks.md)
578+
* [Yale Getting Started Guide](../yale-locks/get-started-with-yale-locks.md)
579+
* [August Getting Started Guide](../august-locks/get-started-with-august-locks.md)
580580
* [Schlage Getting Started Guide](../schlage-locks/get-started-with-schlage-locks.md)
581581
* [SmartThings Getting Started Guide](../smartthings-hubs-+-devices/get-started-with-smartthings-hubs-+-smart-locks.md)
582-
* [Minut Getting Started Guide](../get-started-with-minut-sensors.md)
582+
* [Minut Getting Started Guide](../minut-sensors/get-started-with-minut-sensors.md)
583583
* [Receiving webhook](https://docs.seam.co/latest/developer-tools/webhooks) for [device events](https://docs.seam.co/latest/api/events/list)
584584
* [Core Concepts](https://docs.seam.co/latest/core-concepts/overview)
585585

docs/brand-guides/33-lock-devices/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,12 @@ To control 33 Lock devices using Seam, you must prompt owners of these devices t
6060

6161
## Troubleshooting
6262

63-
For errors and warnings that are relevant to 33 Lock devices, see [Troubleshooting](../ttlock-locks.md#troubleshooting) in the TTLock device integration guide.
63+
For errors and warnings that are relevant to 33 Lock devices, see [Troubleshooting](../ttlock-locks/#troubleshooting) in the TTLock device integration guide.
6464

6565
***
6666

6767
## Where to Order
6868

6969
To purchase 33 Lock devices, contact the 33 Lock sales team..
7070

71-
<table data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td></td><td><strong>33 Lock Contact Page</strong></td><td></td><td><a href="https://www.33lock.com/contact">https://www.33lock.com/contact</a></td><td><a href="../../.gitbook/assets/33-lock-logo.png">33-lock-logo.png</a></td></tr></tbody></table>
71+
<table data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td></td><td><strong>33 Lock Contact Page</strong></td><td></td><td><a href="https://www.33lock.com/contact">https://www.33lock.com/contact</a></td><td><a href="../.gitbook/assets/33-lock-logo.png">33-lock-logo.png</a></td></tr></tbody></table>

docs/brand-guides/33-lock-devices/get-started-with-33-lock-devices.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1418,4 +1418,4 @@ If you have any questions or want to report an issue, email us at [support@seam.
14181418

14191419
## Quick links
14201420

1421-
<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th data-hidden></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Get an API Key</strong> (free)</td><td>Sign up for the Seam Console and get your API keys. →</td><td></td><td><a href="../../.gitbook/assets/seam-api-key.png">seam-api-key.png</a></td><td><a href="https://console.seam.co/">https://console.seam.co/</a></td></tr><tr><td><strong>Contact Sales</strong></td><td>Got a project or a specific question? Contact our team to get answers. →</td><td></td><td><a href="../../.gitbook/assets/seam-contact-us-light.png">seam-contact-us-light.png</a></td><td><a href="https://www.seam.co/contact-us">https://www.seam.co/contact-us</a></td></tr></tbody></table>
1421+
<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th data-hidden></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Get an API Key</strong> (free)</td><td>Sign up for the Seam Console and get your API keys. →</td><td></td><td><a href="../../guides/.gitbook/assets/seam-api-key.png">seam-api-key.png</a></td><td><a href="https://console.seam.co/">https://console.seam.co/</a></td></tr><tr><td><strong>Contact Sales</strong></td><td>Got a project or a specific question? Contact our team to get answers. →</td><td></td><td><a href="../.gitbook/assets/seam-contact-us-light.png">seam-contact-us-light.png</a></td><td><a href="https://www.seam.co/contact-us">https://www.seam.co/contact-us</a></td></tr></tbody></table>

docs/brand-guides/4suites-locks/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,6 @@ To control 4SUITES devices using Seam, you must prompt owners of these devices t
4646

4747
To purchase 4SUITES devices, request a quote using the 4SUITES **Contact Us Form**.
4848

49-
<table data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td></td><td><strong>4SUITES Contact Us Form</strong></td><td></td><td><a href="https://www.4suiteshq.com/contact-us/">https://www.4suiteshq.com/contact-us/</a></td><td><a href="../../.gitbook/assets/4suites-logo.png">4suites-logo.png</a></td></tr></tbody></table>
49+
<table data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td></td><td><strong>4SUITES Contact Us Form</strong></td><td></td><td><a href="https://www.4suiteshq.com/contact-us/">https://www.4suiteshq.com/contact-us/</a></td><td><a href="../.gitbook/assets/4suites-logo.png">4suites-logo.png</a></td></tr></tbody></table>
5050

5151
***

docs/brand-guides/4suites-locks/get-started-with-4suites-locks.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1036,4 +1036,4 @@ If you have any questions or want to report an issue, email us at [support@seam.
10361036

10371037
## Quick links
10381038

1039-
<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th data-hidden></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Get an API Key</strong> (free)</td><td>Sign up for the Seam Console and get your API keys. →</td><td></td><td><a href="../../.gitbook/assets/seam-api-key.png">seam-api-key.png</a></td><td><a href="https://console.seam.co/">https://console.seam.co/</a></td></tr><tr><td><strong>Contact Sales</strong></td><td>Got a project or a specific question? Contact our team to get answers. →</td><td></td><td><a href="../../.gitbook/assets/seam-contact-us-light.png">seam-contact-us-light.png</a></td><td><a href="https://www.seam.co/contact-us">https://www.seam.co/contact-us</a></td></tr></tbody></table>
1039+
<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th data-hidden></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Get an API Key</strong> (free)</td><td>Sign up for the Seam Console and get your API keys. →</td><td></td><td><a href="../../guides/.gitbook/assets/seam-api-key.png">seam-api-key.png</a></td><td><a href="https://console.seam.co/">https://console.seam.co/</a></td></tr><tr><td><strong>Contact Sales</strong></td><td>Got a project or a specific question? Contact our team to get answers. →</td><td></td><td><a href="../.gitbook/assets/seam-contact-us-light.png">seam-contact-us-light.png</a></td><td><a href="https://www.seam.co/contact-us">https://www.seam.co/contact-us</a></td></tr></tbody></table>

0 commit comments

Comments
 (0)