記事の見た目をいじる の履歴(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: 1927 (from 2010/06/03),
today: 3,
yesterday: 3