From 5813248e5a958670c8c22648697e04e2efa17dc0 Mon Sep 17 00:00:00 2001 From: Luca Bonavita Date: Sun, 28 Apr 2019 20:12:01 +0100 Subject: [PATCH] Site: add anchors to blog posts Closes #2609 --- site/src/routes/blog/[slug].svelte | 44 +++++++++++++++++++++++++++++- site/src/routes/blog/_posts.js | 18 +++++++++++- site/src/utils/slug.js | 8 +++++- 3 files changed, 67 insertions(+), 3 deletions(-) diff --git a/site/src/routes/blog/[slug].svelte b/site/src/routes/blog/[slug].svelte index c64130efe5..610fb6506b 100644 --- a/site/src/routes/blog/[slug].svelte +++ b/site/src/routes/blog/[slug].svelte @@ -133,6 +133,48 @@ border: 0.8rem solid var(--second); } + /* headers anchors */ + + .post :global(.offset-anchor) { + position: relative; + display: block; + top: calc(-1 * (var(--nav-h) + var(--top-offset) - 1rem)); + width: 0; + height: 0; + } + + .post :global(.anchor) { + position: absolute; + display: block; + background: url(/icons/link.svg) 0 50% no-repeat; + background-size: 1em 1em; + width: 1.4em; + height: 1em; + top: calc((var(--h3) - 24px) / 2); + left: -1.4em; + opacity: 0; + transition: opacity 0.2s; + border: none !important; /* TODO get rid of linkify */ + } + + .post :global(h2):hover :global(.anchor), + .post :global(h3):hover :global(.anchor), + .post :global(h4):hover :global(.anchor), + .post :global(h5):hover :global(.anchor), + .post :global(h6):hover :global(.anchor) { + opacity: 1; + } + + + @media (max-width: 768px) { + .post :global(.anchor) { + transform: scale(0.6); + opacity: 1; + top: calc((1em - 0.6 * 24px) / 2); + left: -1.0em; + } + } + @media (min-width: 910px) { .post :global(.max) { width: calc(100vw - 2 * var(--side-nav)); @@ -164,4 +206,4 @@ height: 640px; } } */ - \ No newline at end of file + diff --git a/site/src/routes/blog/_posts.js b/site/src/routes/blog/_posts.js index 7a99011c95..bc8c479f1b 100644 --- a/site/src/routes/blog/_posts.js +++ b/site/src/routes/blog/_posts.js @@ -1,10 +1,15 @@ import fs from 'fs'; import path from 'path'; -import { extract_frontmatter, langs, link_renderer } from '../../utils/markdown.js'; import marked from 'marked'; import PrismJS from 'prismjs'; import 'prismjs/components/prism-bash'; +import { extract_frontmatter, langs, link_renderer } from '../../utils/markdown'; +import { makeSlugProcessor } from '../../utils/slug'; +import { SLUG_PRESERVE_UNICODE } from '../../../config'; + +const makeSlug = makeSlugProcessor(SLUG_PRESERVE_UNICODE); + export default function get_posts() { return fs .readdirSync('content/blog') @@ -39,6 +44,17 @@ export default function get_posts() { return `
${highlighted}
`; }; + renderer.heading = (text, level, rawtext) => { + const fragment = makeSlug(rawtext); + + return ` + + + + ${text} + `; + }; + const html = marked( content.replace(/^\t+/gm, match => match.split('\t').join(' ')), { renderer } diff --git a/site/src/utils/slug.js b/site/src/utils/slug.js index 79b82c12ce..d99bc50ecb 100644 --- a/site/src/utils/slug.js +++ b/site/src/utils/slug.js @@ -55,10 +55,16 @@ export const unicodeSafeProcessor = string => }, []) .join(SLUG_SEPARATOR); +/* processor */ + +export const makeSlugProcessor = (preserveUnicode = false) => preserveUnicode + ? unicodeSafeProcessor + : urlsafeSlugProcessor; + /* session processor */ export const makeSessionSlugProcessor = (preserveUnicode = false) => { - const processor = preserveUnicode ? unicodeSafeProcessor : urlsafeSlugProcessor; + const processor = makeSlugProcessor(preserveUnicode); const seen = new Set(); return string => {