diff --git a/sites/svelte.dev/package-lock.json b/sites/svelte.dev/package-lock.json index 05781d383c..b362543efd 100644 --- a/sites/svelte.dev/package-lock.json +++ b/sites/svelte.dev/package-lock.json @@ -15,6 +15,7 @@ "do-not-zip": "^1.0.0", "flexsearch": "^0.7.31", "flru": "^1.0.2", + "slugify": "^1.6.5", "sourcemap-codec": "^1.4.8", "svelte-local-storage-store": "^0.4.0" }, @@ -3453,6 +3454,14 @@ "node": ">= 10" } }, + "node_modules/slugify": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.5.tgz", + "integrity": "sha512-8mo9bslnBO3tr5PEVFzMPIWwWnipGS0xVbYf65zxDqfNwmzYn1LpiKNrR6DlClusuvo+hDHd1zKpmfAe83NQSQ==", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/sorcery": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.11.0.tgz", @@ -6520,6 +6529,11 @@ "totalist": "^3.0.0" } }, + "slugify": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.5.tgz", + "integrity": "sha512-8mo9bslnBO3tr5PEVFzMPIWwWnipGS0xVbYf65zxDqfNwmzYn1LpiKNrR6DlClusuvo+hDHd1zKpmfAe83NQSQ==" + }, "sorcery": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.11.0.tgz", diff --git a/sites/svelte.dev/package.json b/sites/svelte.dev/package.json index e93bac371e..792ad728a5 100644 --- a/sites/svelte.dev/package.json +++ b/sites/svelte.dev/package.json @@ -23,6 +23,7 @@ "do-not-zip": "^1.0.0", "flexsearch": "^0.7.31", "flru": "^1.0.2", + "slugify": "^1.6.5", "sourcemap-codec": "^1.4.8", "svelte-local-storage-store": "^0.4.0" }, diff --git a/sites/svelte.dev/src/lib/search/content.js b/sites/svelte.dev/src/lib/search/content.js index d9c229588b..2de86eac7f 100644 --- a/sites/svelte.dev/src/lib/search/content.js +++ b/sites/svelte.dev/src/lib/search/content.js @@ -1,8 +1,8 @@ +import { normalizeSlugify, removeMarkdown } from '$lib/server/docs'; +import { extract_frontmatter, transform } from '$lib/server/markdown'; import fs from 'node:fs'; import path from 'node:path'; import glob from 'tiny-glob/sync.js'; -import { extract_frontmatter, transform } from '$lib/server/markdown'; -import { slugify } from '$lib/server/docs/index.js'; const base = '../../site/content/'; @@ -47,7 +47,7 @@ export function content() { const rank = +metadata.rank || undefined; blocks.push({ - breadcrumbs: [...breadcrumbs, metadata.title], + breadcrumbs: [...breadcrumbs, removeMarkdown(metadata.title ?? '')], href: category.href([slug]), content: plaintext(intro), rank, @@ -63,8 +63,8 @@ export function content() { const intro = subsections.shift().trim(); blocks.push({ - breadcrumbs: [...breadcrumbs, metadata.title, h3], - href: category.href([slug, slugify(h3)]), + breadcrumbs: [...breadcrumbs, removeMarkdown(metadata.title), removeMarkdown(h3)], + href: category.href([slug, normalizeSlugify(h3)]), content: plaintext(intro), rank, }); @@ -74,8 +74,13 @@ export function content() { const h4 = lines.shift(); blocks.push({ - breadcrumbs: [...breadcrumbs, metadata.title, h3, h4], - href: category.href([slug, slugify(h3), slugify(h4)]), + breadcrumbs: [ + ...breadcrumbs, + removeMarkdown(metadata.title), + removeMarkdown(h3), + removeMarkdown(h4), + ], + href: category.href([slug, normalizeSlugify(h3), normalizeSlugify(h4)]), content: plaintext(lines.join('\n').trim()), rank, }); diff --git a/sites/svelte.dev/src/lib/server/docs/index.js b/sites/svelte.dev/src/lib/server/docs/index.js index 6a4163f2b5..2a10a5a8ce 100644 --- a/sites/svelte.dev/src/lib/server/docs/index.js +++ b/sites/svelte.dev/src/lib/server/docs/index.js @@ -13,6 +13,25 @@ import ts, { ScriptTarget } from 'typescript'; import MagicString from 'magic-string'; import { fileURLToPath } from 'url'; import { createHash } from 'crypto'; +import slugify from 'slugify'; + +/** @param {string} markdown */ +export function removeMarkdown(markdown) { + return markdown + .replace(/\*\*(.+?)\*\*/g, '$1') + .replace(/\*(.+?)\*/g, '$1') + .replace(/`(.+?)`/g, '$1') + .replace(/~~(.+?)~~/g, '$1') + .replace(/\[(.+?)\]\(.+?\)/g, '$1') + .replace(/\n/g, ' ') + .replace(/ {2,}/g, ' ') + .trim(); +} + +/** @param {string} str */ +export const normalizeSlugify = (str) => { + return slugify(removeMarkdown(str)); +}; const base = '../../site/content/docs/'; @@ -286,19 +305,6 @@ export async function read_file(file) { }; } -/** @param {string} title */ -export function slugify(title) { - return title - .toLowerCase() - .replace(/'/g, '') - .replace(/</g, '') - .replace(/>/g, '') - .replace(/[^a-z0-9-$]/g, '-') - .replace(/-{2,}/g, '-') - .replace(/^-/, '') - .replace(/-$/, ''); -} - /** * @param {{ * file: string; @@ -326,7 +332,7 @@ function parse({ file, body, code, codespan }) { * @param {string} html * @param {number} level */ - heading(html, level) { + heading(html, level, raw) { const title = html .replace(/<\/?code>/g, '') .replace(/"/g, '"') @@ -335,7 +341,7 @@ function parse({ file, body, code, codespan }) { current = title; - const normalized = slugify(title); + const normalized = normalizeSlugify(raw).replace(/(<([^>]+)>)/gi, ''); headings[level - 1] = normalized; headings.length = level; diff --git a/sites/svelte.dev/src/routes/+layout.svelte b/sites/svelte.dev/src/routes/+layout.svelte index 1750c0a4ac..59b45a065d 100644 --- a/sites/svelte.dev/src/routes/+layout.svelte +++ b/sites/svelte.dev/src/routes/+layout.svelte @@ -18,15 +18,6 @@