From 8e3b6e4992afd1f17cd69a32c402ebb3288c521a Mon Sep 17 00:00:00 2001 From: Geoff Rich Date: Fri, 13 Nov 2020 16:38:33 -0800 Subject: [PATCH] docs: remove some h4s from the table of contents --- site/content/docs/01-component-format.md | 10 ++-- site/src/routes/docs/_sections.js | 12 +++-- site/src/utils/attributes.js | 61 ++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 site/src/utils/attributes.js diff --git a/site/content/docs/01-component-format.md b/site/content/docs/01-component-format.md index 7286205bdf..7c5f423ca8 100644 --- a/site/content/docs/01-component-format.md +++ b/site/content/docs/01-component-format.md @@ -24,7 +24,7 @@ All three sections — script, styles and markup — are optional. A ` ``` -#### 2. Assignments are 'reactive' +#### 2. Assignments are 'reactive' { data-toc-ignore } --- @@ -107,7 +107,7 @@ Because Svelte's reactivity is based on assignments, using array methods like `. ``` -#### 3. `$:` marks a statement as reactive +#### 3. `$:` marks a statement as reactive { data-toc-ignore } --- @@ -143,7 +143,7 @@ If a statement consists entirely of an assignment to an undeclared variable, Sve ``` -#### 4. Prefix stores with `$` to access their values +#### 4. Prefix stores with `$` to access their values { data-toc-ignore } --- @@ -172,7 +172,7 @@ Local variables (that do not represent store values) must *not* have a `$` prefi ``` -#### Store contract +#### Store contract { data-toc-ignore } ```js store = { subscribe: (subscription: (value: any) => void) => (() => void), set?: (value: any) => void } diff --git a/site/src/routes/docs/_sections.js b/site/src/routes/docs/_sections.js index 3657ba85ac..b730abbe2f 100644 --- a/site/src/routes/docs/_sections.js +++ b/site/src/routes/docs/_sections.js @@ -3,6 +3,7 @@ import path from 'path'; import { SLUG_PRESERVE_UNICODE, SLUG_SEPARATOR } from '../../../config'; import { extract_frontmatter, extract_metadata, link_renderer } from '@sveltejs/site-kit/utils/markdown.js'; import { make_session_slug_processor } from '@sveltejs/site-kit/utils/slug'; +import { extract_attributes } from '../../utils/attributes'; import { highlight } from '../../utils/highlight'; import marked from 'marked'; @@ -85,6 +86,10 @@ export default function() { renderer.heading = (text, level, rawtext) => { let slug; + let extracted = extract_attributes(text, rawtext); + text = extracted.text; + rawtext = extracted.raw; + const match = /]*>(.+)<\/a>/.exec(text); if (match) { slug = match[1]; @@ -93,7 +98,8 @@ export default function() { slug = make_slug(rawtext); } - if (level === 3 || level === 4) { + const tocIgnore = 'data-toc-ignore' in extracted.attrs; + if ((level === 3 || level === 4) && !tocIgnore) { const title = text .replace(/<\/?code>/g, '') .replace(/\.(\w+)(\((.+)?\))?/, (m, $1, $2, $3) => { @@ -106,8 +112,8 @@ export default function() { } return ` - - 4 ? 'data-scrollignore' : ''}> + + 4 || tocIgnore ? 'data-scrollignore' : ''}> ${text} `; diff --git a/site/src/utils/attributes.js b/site/src/utils/attributes.js new file mode 100644 index 0000000000..1a823cab11 --- /dev/null +++ b/site/src/utils/attributes.js @@ -0,0 +1,61 @@ +const ATTRS_REGEX = /^(.+)\s+\{(.+)\}$/; +/** + * Extracts attributes from markdown text to be applied to the resulting HTML. + * @example + * // returns { + * // text: 'Heading', + * // raw: 'Heading', + * // attrs: { id: 'important', class: 'red', test: 'true' }, + * // attrstring: 'id="important" class="red" test="true"' + * // } + * extract_attributes( + * 'Heading { #important .red test=true }', + * 'Heading { #important .red test=true }' + * ); + * ``` + * @param {string} text + * @param {string} raw + */ +export function extract_attributes(text, raw) { + try { + const textMatch = text.match(ATTRS_REGEX); + const rawMatch = raw && raw.match(ATTRS_REGEX); + const attrs = textMatch ? parse_attributes(textMatch[2]) : {}; + + return { + text: textMatch ? textMatch[1] : text, + raw: rawMatch ? rawMatch[1] : raw, + attrs, + attrstring: Object.keys(attrs).map(key => `${key}="${attrs[key].trim()}"`).join(' ') + } + } catch (err) { + console.log(err); + return { + text, + raw, + attrs: {}, + attrstring: '' + }; + } +} + +function parse_attributes(raw_attributes) { + const attributes = raw_attributes.split(' '); + const result = { }; + attributes.forEach(attr => { + if (!attr) return; + if (attr.startsWith('#')) { + result.id = attr.substring(1); + } else if (attr.startsWith('.')) { + if (!result.class) { + result.class = ''; + } + result.class += attr.substring(1) + ' '; + } else { + let [key, value = ''] = attr.split('='); + result[key] = value; + } + }) + + return result; +} \ No newline at end of file