記事の見た目をいじる の履歴(No.2)
更新いろいろきれいに見えるようにする†
メモ: style の :global について†
svelte の style 定義には自動的にコンポーネントインスタンスの id が追加されるため、 そのコンポーネントに直接含まれる(子コンポーネントは除外)エレメントにしか効果を及ぼさない。
コンポーネントを超えて効果を期待する場合には :global を付ける。
https://svelte.jp/docs/svelte-components#style
LANG: html <style> :global(strong) { /* これはすべての <strong> に適用されます */ margin: 0; } div :global(strong) { /* これは「このコンポーネント内の <div> 要素」の中にある 「すべての <strong> 要素」に 適用されます */ color: goldenrod; } </style>
上記の例では div に :global がかかっていないため、div にはコンポーネントインスタンスの ID が付き、その下にあることが条件になっている。
「このコンポーネントの子供」に適用したい場合にはこのテクニックが役に立ちそう。
ArticleElement コンポーネントを作成†
db の Article と同名だとややこしいことになるようなので ArticleElement とした。
src/routes/articles/ArticleElement.svelte に置くことも考えたのだけれど、 関連コードが増えてフォルダーを掘りたくなる気もしたので
src/lib/components/ArticleElement.svelte にした
LANG: html <script lang="ts" context="module"> import { marked } from 'marked'; import { baseUrl } from 'marked-base-url'; import markedLinkifyIt from 'marked-linkify-it'; import { markedHighlight } from 'marked-highlight'; import hljs from 'highlight.js'; import markedKatex from 'marked-katex-extension'; import { page } from '$app/stores'; import 'highlight.js/styles/stackoverflow-dark.min.css'; marked.use(baseUrl('https://example.com/folder/')); const linkifyItSchemas = {}; const linkifyItOptions = {}; marked.use(markedLinkifyIt(linkifyItSchemas, linkifyItOptions)); marked.use( markedHighlight({ langPrefix: 'hljs language-', highlight(code, lang) { const language = hljs.getLanguage(lang) ? lang : 'plaintext'; return hljs.highlight(code, { language }).value; }, }) ); marked.use( markedKatex({ throwOnError: false, }) ); </script> <script lang="ts"> export let title: string; export let author: string; export let date: Date; export let body: string; export let permLink: string; </script> <article class="prose max-w-full p-4"> <h1>{title}</h1> <div> <span>{author}</span> <span>{date.toLocaleString()}</span> <span><a href={permLink + '/edit'}>編集</a></span> </div> <content> {@html marked.parse(body)} </content> </article>
src/routes/articles/[...titleOrId]/+page.svelte
LANG: html <script lang="ts"> import type { PageData } from './$types'; import ArticleElement from '$lib/components/ArticleElement.svelte'; import { encodeTitle } from '../lib'; export let data: PageData; </script> <ArticleElement title={data.article.title} body={data.article.body} author={data.article.author.name} date={data.article.createdAt} permLink={data.urlRoot + '/articles/' + encodeTitle(data.article.title)} />
見出しのレベルを調整†
ブログ記事ではタイトルが h1 なので本文中では一番大きいのが h2 になる。
LANG: ts // デフォルトのレンダラ const vanillaRenderer = new marked.Renderer(); // 見出しの階層を1つ下げる marked.use({ renderer: { heading(text, level, raw) { return vanillaRenderer.heading(text, level + 1, raw); } } });
ベース URL†
LANG: ts import { baseUrl } from 'marked-base-url'; import { PUBLIC_URL_ROOT } from '$env/static/public'; ... // ベースアドレス marked.use(baseUrl(PUBLIC_URL_ROOT));
シンタックスハイライト†
痒い所に手が届くよう、marked-highlight を使わず自分でやろう。
$ pnpm rm marked-highlight
Counter: 1015 (from 2010/06/03),
today: 1,
yesterday: 3