Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions scripts/check-library-content.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ describe('check-library-content', () => {
[
'## Overview',
'See [the guide](/library/kept-guide) and https://www.sim.ai/library/kept-guide#intro.',
'Read https://www.sim.ai/library/kept-guide. Then https://www.sim.ai/library/moved-post, too.',
'![diagram](/library/clean/diagram.png) and [tags](/library/tags) are not posts.',
'An apex https://sim.ai/library/missing link belongs to check:site-urls.',
'| a | b |',
Expand Down Expand Up @@ -177,6 +178,8 @@ describe('check-library-content', () => {
'[b](https://www.sim.ai/library/old-guide)',
'<a href="/blog/moved-post">c</a>',
'[d](/blog/kept-guide)',
'Also see https://www.sim.ai/library/gone.',
'[e](/library/kept-guide.) and <a href="https://www.sim.ai/library/kept-guide.">f</a>',
].join('\n')
)
expect(await findingsFor('library', 'post')).toEqual([
Expand All @@ -200,6 +203,23 @@ describe('check-library-content', () => {
rule: 'internal-link',
message: '/blog/kept-guide does not exist (no apps/sim/content/blog/kept-guide/index.mdx).',
},
{
line: 14,
rule: 'internal-link',
message: '/library/gone does not exist (no apps/sim/content/library/gone/index.mdx).',
},
{
line: 15,
rule: 'internal-link',
message:
'/library/kept-guide. does not exist (no apps/sim/content/library/kept-guide./index.mdx).',
},
{
line: 15,
rule: 'internal-link',
message:
'/library/kept-guide. does not exist (no apps/sim/content/library/kept-guide./index.mdx).',
},
])
})

Expand Down
7 changes: 6 additions & 1 deletion scripts/check-library-content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ export interface PostRef {
*/
const INTERNAL_LINK =
/(?:https?:\/\/www\.sim\.ai|(?<=\]\(\s*|href=\{?["'`]))\/(library|blog|customers)\/([^\s)"'`#?/<>\]]+)(\/[^\s)"'`#?<>\]]*)?/g
/** Sentence punctuation that ends a bare URL in prose (`…see https://www.sim.ai/library/x.`). */
const TRAILING_PUNCTUATION = /[.,;:!]+$/
/** Text just before a Markdown link target or `href` value, whose URL ends at its delimiter. */
const LINK_TARGET_OPENER = /(?:\]\(\s*|href=\{?["'`])$/
Comment thread
waleedlatif1 marked this conversation as resolved.
const MARKDOWN_LINK = /\[[^\]\n]*\]\([^)\n]*\)/
const FAQ_HEADING = /^#{1,6}\s+FAQs?\s*:?\s*$/i
const CODE_FENCE = /^\s*(```|~~~)/
Expand Down Expand Up @@ -330,7 +334,8 @@ export async function checkPost(
}
for (const match of text.matchAll(INTERNAL_LINK)) {
const linkSection = match[1] as Section
const target = match[2]
const isBareUrl = !LINK_TARGET_OPENER.test(text.slice(0, match.index))
Comment thread
waleedlatif1 marked this conversation as resolved.
Comment thread
waleedlatif1 marked this conversation as resolved.
const target = isBareUrl ? match[2].replace(TRAILING_PUNCTUATION, '') : match[2]
const rest = match[3] ?? ''
// A deeper path is a public asset (`/library/<slug>/cover.jpg`) or a static sub-route.
if (rest !== '' && rest !== '/') continue
Expand Down
Loading