starlight-obsidian 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.ts +67 -19
- package/libs/integration.ts +17 -3
- package/libs/rehype.ts +25 -3
- package/libs/starlight.ts +7 -5
- package/libs/vite.ts +21 -0
- package/overrides/PageSidebar.astro +67 -0
- package/package.json +10 -2
- package/styles/autolinks-headings.css +68 -0
- package/virtual.d.ts +5 -0
- /package/{styles.css → styles/common.css} +0 -0
package/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { StarlightPlugin, StarlightUserConfig } from '@astrojs/starlight/types'
|
|
2
|
+
import type { AstroIntegrationLogger } from 'astro'
|
|
2
3
|
import { z } from 'astro/zod'
|
|
3
4
|
|
|
4
5
|
import { starlightObsidianIntegration } from './libs/integration'
|
|
@@ -7,6 +8,12 @@ import { throwUserError } from './libs/plugin'
|
|
|
7
8
|
import { addObsidianFiles, getSidebarFromConfig, getSidebarGroupPlaceholder } from './libs/starlight'
|
|
8
9
|
|
|
9
10
|
const starlightObsidianConfigSchema = z.object({
|
|
11
|
+
/**
|
|
12
|
+
* Add links to Starlight headings to make it easier to share a link to a specific section of a page.
|
|
13
|
+
*
|
|
14
|
+
* @default false
|
|
15
|
+
*/
|
|
16
|
+
autoLinkHeadings: z.boolean().default(false),
|
|
10
17
|
/**
|
|
11
18
|
* The name of the Obsidian vault configuration folder if different from the default one.
|
|
12
19
|
*
|
|
@@ -30,6 +37,15 @@ const starlightObsidianConfigSchema = z.object({
|
|
|
30
37
|
* @default 'notes'
|
|
31
38
|
*/
|
|
32
39
|
output: z.string().default('notes'),
|
|
40
|
+
/**
|
|
41
|
+
* Whether the Starlight Obsidian plugin should skip the generation of the Obsidian vault pages.
|
|
42
|
+
*
|
|
43
|
+
* This is useful to disable generating the Obsidian vault pages when deploying on platforms that do not have access
|
|
44
|
+
* to the Obsidian vault. This will require you to build and commit the pages locally ahead of time.
|
|
45
|
+
*
|
|
46
|
+
* @default false
|
|
47
|
+
*/
|
|
48
|
+
skipGeneration: z.boolean().default(false),
|
|
33
49
|
/**
|
|
34
50
|
* The generated vault pages sidebar group configuration.
|
|
35
51
|
*/
|
|
@@ -55,6 +71,14 @@ const starlightObsidianConfigSchema = z.object({
|
|
|
55
71
|
label: z.string().default('Notes'),
|
|
56
72
|
})
|
|
57
73
|
.default({}),
|
|
74
|
+
/**
|
|
75
|
+
* Determines if the table of contents top-level heading should be the Starlight default one ("Overview") or the page
|
|
76
|
+
* title.
|
|
77
|
+
* This option is useful when the Obsidian vault pages already have a top-level heading named "Overview".
|
|
78
|
+
*
|
|
79
|
+
* @default 'title'
|
|
80
|
+
*/
|
|
81
|
+
tableOfContentsOverview: z.union([z.literal('default'), z.literal('title')]).default('default'),
|
|
58
82
|
/**
|
|
59
83
|
* The absolute or relative path to the Obsidian vault to publish.
|
|
60
84
|
*/
|
|
@@ -82,44 +106,68 @@ export default function starlightObsidianPlugin(userConfig: StarlightObsidianUse
|
|
|
82
106
|
return
|
|
83
107
|
}
|
|
84
108
|
|
|
109
|
+
const customCss = [...(starlightConfig.customCss ?? []), 'starlight-obsidian/styles/common']
|
|
110
|
+
|
|
111
|
+
if (config.autoLinkHeadings) {
|
|
112
|
+
customCss.push('starlight-obsidian/styles/autolinks-headings')
|
|
113
|
+
}
|
|
114
|
+
|
|
85
115
|
const updatedStarlightConfig: Partial<StarlightUserConfig> = {
|
|
86
|
-
customCss
|
|
116
|
+
customCss,
|
|
87
117
|
sidebar: getSidebarFromConfig(config, starlightConfig.sidebar),
|
|
88
118
|
}
|
|
89
119
|
|
|
120
|
+
if (!updatedStarlightConfig.components) {
|
|
121
|
+
updatedStarlightConfig.components = {}
|
|
122
|
+
}
|
|
123
|
+
|
|
90
124
|
if (starlightConfig.components?.PageTitle) {
|
|
91
|
-
logger
|
|
92
|
-
'It looks like you already have a `PageTitle` component override in your Starlight configuration.',
|
|
93
|
-
)
|
|
94
|
-
logger.warn('To use `starlight-obsidian`, remove the override for the `PageTitle` component.\n')
|
|
125
|
+
logComponentOverrideWarning(logger, 'PageTitle')
|
|
95
126
|
} else {
|
|
96
|
-
updatedStarlightConfig.components =
|
|
97
|
-
|
|
127
|
+
updatedStarlightConfig.components.PageTitle = 'starlight-obsidian/overrides/PageTitle.astro'
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (config.tableOfContentsOverview === 'title') {
|
|
131
|
+
if (starlightConfig.components?.PageSidebar) {
|
|
132
|
+
logComponentOverrideWarning(logger, 'PageSidebar')
|
|
133
|
+
} else {
|
|
134
|
+
updatedStarlightConfig.components.PageSidebar = 'starlight-obsidian/overrides/PageSidebar.astro'
|
|
98
135
|
}
|
|
99
136
|
}
|
|
100
137
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
138
|
+
if (config.skipGeneration) {
|
|
139
|
+
logger.warn(
|
|
140
|
+
`Skipping generation of Starlight pages from Obsidian vault as the 'skipGeneration' option is enabled.`,
|
|
141
|
+
)
|
|
142
|
+
} else {
|
|
143
|
+
try {
|
|
144
|
+
const start = performance.now()
|
|
145
|
+
logger.info('Generating Starlight pages from Obsidian vault…')
|
|
104
146
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
147
|
+
const vault = await getVault(config)
|
|
148
|
+
const obsidianPaths = await getObsidianPaths(vault, config.ignore)
|
|
149
|
+
await addObsidianFiles(config, vault, obsidianPaths, logger)
|
|
108
150
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
151
|
+
const duration = Math.round(performance.now() - start)
|
|
152
|
+
logger.info(`Starlight pages generated from Obsidian vault in ${duration}ms.`)
|
|
153
|
+
} catch (error) {
|
|
154
|
+
logger.error(error instanceof Error ? error.message : String(error))
|
|
113
155
|
|
|
114
|
-
|
|
156
|
+
throwUserError('Failed to generate Starlight pages from Obsidian vault.')
|
|
157
|
+
}
|
|
115
158
|
}
|
|
116
159
|
|
|
117
|
-
addIntegration(starlightObsidianIntegration())
|
|
160
|
+
addIntegration(starlightObsidianIntegration(config))
|
|
118
161
|
updateConfig(updatedStarlightConfig)
|
|
119
162
|
},
|
|
120
163
|
},
|
|
121
164
|
}
|
|
122
165
|
}
|
|
123
166
|
|
|
167
|
+
function logComponentOverrideWarning(logger: AstroIntegrationLogger, component: string) {
|
|
168
|
+
logger.warn(`It looks like you already have a \`${component}\` component override in your Starlight configuration.`)
|
|
169
|
+
logger.warn(`To use \`starlight-obsidian\`, remove the override for the \`${component}\` component.\n`)
|
|
170
|
+
}
|
|
171
|
+
|
|
124
172
|
export type StarlightObsidianUserConfig = z.input<typeof starlightObsidianConfigSchema>
|
|
125
173
|
export type StarlightObsidianConfig = z.output<typeof starlightObsidianConfigSchema>
|
package/libs/integration.ts
CHANGED
|
@@ -1,19 +1,33 @@
|
|
|
1
|
+
import { rehypeHeadingIds } from '@astrojs/markdown-remark'
|
|
1
2
|
import type { AstroIntegration } from 'astro'
|
|
3
|
+
import rehypeAutolinkHeadings from 'rehype-autolink-headings'
|
|
2
4
|
import rehypeKatex from 'rehype-katex'
|
|
3
5
|
import remarkMath from 'remark-math'
|
|
4
6
|
|
|
5
|
-
import {
|
|
7
|
+
import type { StarlightObsidianConfig } from '..'
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
import { getRehypeAutolinkHeadingsOptions, rehypeStarlightObsidian } from './rehype'
|
|
10
|
+
import { vitePluginStarlightObsidianConfig } from './vite'
|
|
11
|
+
|
|
12
|
+
export function starlightObsidianIntegration(config: StarlightObsidianConfig): AstroIntegration {
|
|
8
13
|
return {
|
|
9
14
|
name: 'starlight-obsidian-integration',
|
|
10
15
|
hooks: {
|
|
11
16
|
'astro:config:setup': ({ updateConfig }) => {
|
|
12
17
|
updateConfig({
|
|
13
18
|
markdown: {
|
|
14
|
-
rehypePlugins: [
|
|
19
|
+
rehypePlugins: [
|
|
20
|
+
...(config.autoLinkHeadings
|
|
21
|
+
? [rehypeHeadingIds, [rehypeAutolinkHeadings, getRehypeAutolinkHeadingsOptions()]]
|
|
22
|
+
: []),
|
|
23
|
+
rehypeStarlightObsidian,
|
|
24
|
+
rehypeKatex,
|
|
25
|
+
],
|
|
15
26
|
remarkPlugins: [remarkMath],
|
|
16
27
|
},
|
|
28
|
+
vite: {
|
|
29
|
+
plugins: [vitePluginStarlightObsidianConfig(config)],
|
|
30
|
+
},
|
|
17
31
|
})
|
|
18
32
|
},
|
|
19
33
|
},
|
package/libs/rehype.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import type { Element, ElementContent, Root } from 'hast'
|
|
2
|
+
import { toString } from 'hast-util-to-string'
|
|
3
|
+
import { h } from 'hastscript'
|
|
4
|
+
import { escape } from 'html-escaper'
|
|
2
5
|
import type { Literal } from 'mdast'
|
|
6
|
+
import type { Options as RehypeAutolinkHeadingsOptions } from 'rehype-autolink-headings'
|
|
3
7
|
import { CONTINUE, SKIP, visit } from 'unist-util-visit'
|
|
4
8
|
|
|
5
9
|
const blockIdentifierRegex = /(?<identifier> *\^(?<name>[\w-]+))$/
|
|
@@ -25,12 +29,12 @@ export function rehypeStarlightObsidian() {
|
|
|
25
29
|
const lastGrandChild = lastChild.children.at(-1)
|
|
26
30
|
|
|
27
31
|
if (lastChild.tagName === 'p') {
|
|
28
|
-
transformBlockIdentifier(node, lastGrandChild)
|
|
32
|
+
return transformBlockIdentifier(node, lastGrandChild)
|
|
29
33
|
} else if (lastGrandChild?.type === 'element' && lastGrandChild.tagName === 'li') {
|
|
30
|
-
transformBlockIdentifier(node, lastGrandChild.children.at(-1))
|
|
34
|
+
return transformBlockIdentifier(node, lastGrandChild.children.at(-1))
|
|
31
35
|
}
|
|
32
36
|
} else if (node.tagName === 'p' || node.tagName === 'li') {
|
|
33
|
-
transformBlockIdentifier(node, node.children.at(-1))
|
|
37
|
+
return transformBlockIdentifier(node, node.children.at(-1))
|
|
34
38
|
}
|
|
35
39
|
|
|
36
40
|
return CONTINUE
|
|
@@ -38,6 +42,24 @@ export function rehypeStarlightObsidian() {
|
|
|
38
42
|
}
|
|
39
43
|
}
|
|
40
44
|
|
|
45
|
+
// https://hideoo.dev/notes/starlight-heading-links
|
|
46
|
+
// https://github.com/withastro/docs/blob/main/plugins/rehype-autolink.ts
|
|
47
|
+
// https://amberwilson.co.uk/blog/are-your-anchor-links-accessible/
|
|
48
|
+
export function getRehypeAutolinkHeadingsOptions(): RehypeAutolinkHeadingsOptions {
|
|
49
|
+
return {
|
|
50
|
+
behavior: 'after',
|
|
51
|
+
content: (heading) => {
|
|
52
|
+
return [
|
|
53
|
+
h('span', { ariaHidden: 'true' }, '§'),
|
|
54
|
+
h('span', { class: 'sr-only' }, `Section titled ${escape(toString(heading))}`),
|
|
55
|
+
]
|
|
56
|
+
},
|
|
57
|
+
group: ({ tagName }) =>
|
|
58
|
+
h('div', { class: `sl-obs-section sl-obs-section-level-${tagName.slice(1)}`, tabIndex: -1 }),
|
|
59
|
+
properties: { class: 'sl-obs-heading-link' },
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
41
63
|
function transformBlockIdentifier(reference: Element, node: ElementContent | undefined) {
|
|
42
64
|
if (!isNodeWithValue(node)) {
|
|
43
65
|
return CONTINUE
|
package/libs/starlight.ts
CHANGED
|
@@ -209,19 +209,21 @@ async function addAlias(
|
|
|
209
209
|
await ensureDirectory(starlightDirPath)
|
|
210
210
|
|
|
211
211
|
// Based on https://github.com/withastro/astro/blob/57ab578bc7bdac6c65c2315365c0e94bc98af2b3/packages/astro/src/core/build/generate.ts#L584-L591
|
|
212
|
-
// but tweaked to add an `<html>` element so that Pagefind does not emit a warning
|
|
212
|
+
// but tweaked to add an `<html>` element so that Pagefind does not emit a warning and ignore the page.
|
|
213
213
|
await fs.writeFile(
|
|
214
214
|
starlightPath,
|
|
215
215
|
`<!doctype html>
|
|
216
|
-
<html>
|
|
216
|
+
<html lang="en">
|
|
217
217
|
<head>
|
|
218
|
-
<title
|
|
218
|
+
<title>${vaultFile.stem}</title>
|
|
219
219
|
<meta http-equiv="refresh" content="0;url=${to}">
|
|
220
220
|
<meta name="robots" content="noindex">
|
|
221
221
|
<link rel="canonical" href="${to}">
|
|
222
222
|
</head>
|
|
223
|
-
<body>
|
|
224
|
-
<
|
|
223
|
+
<body data-pagefind-body>
|
|
224
|
+
<h2 id="alias">Alias</h2>
|
|
225
|
+
<code>(name: ${alias})</code>
|
|
226
|
+
<a href="${to}" data-pagefind-ignore>Redirecting from <code>${from}</code> to "<code>${to}</code>"</a>
|
|
225
227
|
</body>
|
|
226
228
|
</html>`,
|
|
227
229
|
)
|
package/libs/vite.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ViteUserConfig } from 'astro'
|
|
2
|
+
|
|
3
|
+
import type { StarlightObsidianConfig } from '..'
|
|
4
|
+
|
|
5
|
+
export function vitePluginStarlightObsidianConfig(config: StarlightObsidianConfig): VitePlugin {
|
|
6
|
+
const moduleId = 'virtual:starlight-obsidian-config'
|
|
7
|
+
const resolvedModuleId = `\0${moduleId}`
|
|
8
|
+
const moduleContent = `export default ${JSON.stringify(config)}`
|
|
9
|
+
|
|
10
|
+
return {
|
|
11
|
+
name: 'vite-plugin-starlight-obsidian-config',
|
|
12
|
+
load(id) {
|
|
13
|
+
return id === resolvedModuleId ? moduleContent : undefined
|
|
14
|
+
},
|
|
15
|
+
resolveId(id) {
|
|
16
|
+
return id === moduleId ? resolvedModuleId : undefined
|
|
17
|
+
},
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
type VitePlugin = NonNullable<ViteUserConfig['plugins']>[number]
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
import MobileTableOfContents from '@astrojs/starlight/components/MobileTableOfContents.astro'
|
|
3
|
+
import TableOfContents from '@astrojs/starlight/components/TableOfContents.astro'
|
|
4
|
+
import type { Props } from '@astrojs/starlight/props'
|
|
5
|
+
import config from 'virtual:starlight-obsidian-config'
|
|
6
|
+
|
|
7
|
+
const toc = Astro.props.toc
|
|
8
|
+
|
|
9
|
+
if (config.tableOfContentsOverview === 'title' && toc) {
|
|
10
|
+
const firstTocItem = toc.items.at(0)
|
|
11
|
+
|
|
12
|
+
if (firstTocItem) {
|
|
13
|
+
firstTocItem.text = Astro.props.entry['data'].title
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
{
|
|
19
|
+
Astro.props.toc && (
|
|
20
|
+
<>
|
|
21
|
+
<div class="lg:sl-hidden">
|
|
22
|
+
<MobileTableOfContents {...Astro.props} {toc} />
|
|
23
|
+
</div>
|
|
24
|
+
<div class="right-sidebar-panel sl-hidden lg:sl-block">
|
|
25
|
+
<div class="sl-container">
|
|
26
|
+
<TableOfContents {...Astro.props} {toc} />
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
</>
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
<style>
|
|
34
|
+
.right-sidebar-panel {
|
|
35
|
+
padding: 1rem var(--sl-sidebar-pad-x);
|
|
36
|
+
}
|
|
37
|
+
.sl-container {
|
|
38
|
+
width: calc(var(--sl-sidebar-width) - 2 * var(--sl-sidebar-pad-x));
|
|
39
|
+
}
|
|
40
|
+
.right-sidebar-panel :global(h2) {
|
|
41
|
+
color: var(--sl-color-white);
|
|
42
|
+
font-size: var(--sl-text-h5);
|
|
43
|
+
font-weight: 600;
|
|
44
|
+
line-height: var(--sl-line-height-headings);
|
|
45
|
+
margin-bottom: 0.5rem;
|
|
46
|
+
}
|
|
47
|
+
.right-sidebar-panel :global(:where(a)) {
|
|
48
|
+
display: block;
|
|
49
|
+
font-size: var(--sl-text-xs);
|
|
50
|
+
text-decoration: none;
|
|
51
|
+
color: var(--sl-color-gray-3);
|
|
52
|
+
overflow-wrap: anywhere;
|
|
53
|
+
}
|
|
54
|
+
.right-sidebar-panel :global(:where(a):hover) {
|
|
55
|
+
color: var(--sl-color-white);
|
|
56
|
+
}
|
|
57
|
+
@media (min-width: 72rem) {
|
|
58
|
+
.sl-container {
|
|
59
|
+
max-width: calc(
|
|
60
|
+
(
|
|
61
|
+
(100vw - var(--sl-sidebar-width) - 2 * var(--sl-content-pad-x) - 2 * var(--sl-sidebar-pad-x)) * 0.25
|
|
62
|
+
/* MAGIC NUMBER 🥲 */
|
|
63
|
+
)
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
</style>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "starlight-obsidian",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Starlight plugin to publish Obsidian vaults.",
|
|
6
6
|
"author": "HiDeoo <github@hideoo.dev> (https://hideoo.dev)",
|
|
@@ -9,22 +9,29 @@
|
|
|
9
9
|
".": "./index.ts",
|
|
10
10
|
"./components/Twitter.astro": "./components/Twitter.astro",
|
|
11
11
|
"./components/Youtube.astro": "./components/Youtube.astro",
|
|
12
|
+
"./overrides/PageSidebar.astro": "./overrides/PageSidebar.astro",
|
|
12
13
|
"./overrides/PageTitle.astro": "./overrides/PageTitle.astro",
|
|
13
14
|
"./schema": "./schema.ts",
|
|
14
|
-
"./styles": "./styles.css",
|
|
15
|
+
"./styles/common": "./styles/common.css",
|
|
16
|
+
"./styles/autolinks-headings": "./styles/autolinks-headings.css",
|
|
15
17
|
"./package.json": "./package.json"
|
|
16
18
|
},
|
|
17
19
|
"dependencies": {
|
|
18
20
|
"@astro-community/astro-embed-twitter": "0.5.3",
|
|
19
21
|
"@astro-community/astro-embed-youtube": "0.4.4",
|
|
22
|
+
"@astrojs/markdown-remark": "4.2.1",
|
|
20
23
|
"github-slugger": "2.0.0",
|
|
21
24
|
"globby": "14.0.0",
|
|
22
25
|
"hast-util-to-html": "9.0.0",
|
|
26
|
+
"hast-util-to-string": "3.0.0",
|
|
27
|
+
"hastscript": "9.0.0",
|
|
28
|
+
"html-escaper": "3.0.3",
|
|
23
29
|
"is-absolute-url": "4.0.1",
|
|
24
30
|
"mdast-util-find-and-replace": "3.0.1",
|
|
25
31
|
"mdast-util-to-hast": "13.1.0",
|
|
26
32
|
"nanoid": "5.0.4",
|
|
27
33
|
"rehype": "13.0.1",
|
|
34
|
+
"rehype-autolink-headings": "7.1.0",
|
|
28
35
|
"rehype-katex": "7.0.0",
|
|
29
36
|
"rehype-mermaid": "2.1.0",
|
|
30
37
|
"remark": "15.0.1",
|
|
@@ -38,6 +45,7 @@
|
|
|
38
45
|
"devDependencies": {
|
|
39
46
|
"@astrojs/starlight": "0.16.0",
|
|
40
47
|
"@types/hast": "3.0.3",
|
|
48
|
+
"@types/html-escaper": "3.0.2",
|
|
41
49
|
"@types/mdast": "4.0.3",
|
|
42
50
|
"@types/unist": "3.0.2",
|
|
43
51
|
"astro": "4.2.1",
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
.sl-markdown-content :not(.sl-obs-section) + :is(.sl-obs-section):not(:where(.not-content *)) {
|
|
2
|
+
margin-top: 1.5em;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.sl-markdown-content .sl-obs-section {
|
|
6
|
+
--sl-obs-heading-link-spacing: 0.25em;
|
|
7
|
+
|
|
8
|
+
line-height: var(--sl-line-height-headings);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.sl-markdown-content .sl-obs-section.sl-obs-section-level-1 {
|
|
12
|
+
font-size: var(--sl-text-h1);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.sl-markdown-content .sl-obs-section.sl-obs-section-level-2 {
|
|
16
|
+
font-size: var(--sl-text-h2);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.sl-markdown-content .sl-obs-section.sl-obs-section-level-3 {
|
|
20
|
+
font-size: var(--sl-text-h3);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.sl-markdown-content .sl-obs-section.sl-obs-section-level-4 {
|
|
24
|
+
font-size: var(--sl-text-h4);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.sl-markdown-content .sl-obs-section.sl-obs-section-level-5 {
|
|
28
|
+
font-size: var(--sl-text-h5);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.sl-markdown-content .sl-obs-section.sl-obs-section-level-6 {
|
|
32
|
+
font-size: var(--sl-text-h6);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.sl-markdown-content .sl-obs-section > :first-child {
|
|
36
|
+
display: inline;
|
|
37
|
+
margin-inline-end: var(--sl-obs-heading-link-spacing);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.sl-markdown-content .sl-obs-heading-link {
|
|
41
|
+
color: var(--sl-color-gray-3);
|
|
42
|
+
text-decoration: none;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.sl-markdown-content .sl-obs-heading-link:is(:hover, :focus) {
|
|
46
|
+
color: var(--sl-color-text-accent);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@media (hover: hover) {
|
|
50
|
+
.sl-markdown-content .sl-obs-heading-link {
|
|
51
|
+
opacity: 0;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.sl-markdown-content .sl-obs-section:hover > .sl-obs-heading-link,
|
|
56
|
+
.sl-markdown-content .sl-obs-heading-link:focus {
|
|
57
|
+
opacity: 1;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@media (min-width: 95em) {
|
|
61
|
+
.sl-markdown-content .sl-obs-section {
|
|
62
|
+
display: flex;
|
|
63
|
+
flex-direction: row-reverse;
|
|
64
|
+
gap: var(--sl-obs-heading-link-spacing);
|
|
65
|
+
justify-content: flex-end;
|
|
66
|
+
margin-inline-start: calc(-1 * (1ch + var(--sl-obs-heading-link-spacing)));
|
|
67
|
+
}
|
|
68
|
+
}
|
package/virtual.d.ts
ADDED
|
File without changes
|