starlight-theme-nova 0.2.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/lib/styles.gen.css +5 -1
- package/package.json +3 -1
- package/src/components/CodeTabs.astro +10 -4
- package/src/components/rehype-code-tabs.ts +56 -0
- package/src/constants.ts +4 -0
- package/src/shiki-config.ts +4 -1
- package/src/shiki-meta-title.ts +6 -0
- package/src/shiki-transformer-container.ts +70 -0
- package/src/shiki-transformer-copy-button.ts +18 -36
package/lib/styles.gen.css
CHANGED
|
@@ -99,7 +99,8 @@
|
|
|
99
99
|
.nova-pagination-link-icon-right{--nova-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m9 18l6-6l-6-6'/%3E%3C/svg%3E");-webkit-mask:var(--nova-icon) no-repeat;mask:var(--nova-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em;display:block;min-width:1.25rem;min-height:1.25rem;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:150ms;}
|
|
100
100
|
.nova-theme-select-icon-dark{--nova-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M12 1.992a10 10 0 1 0 9.236 13.838c.341-.82-.476-1.644-1.298-1.31a6.5 6.5 0 0 1-6.864-10.787l.077-.08c.551-.63.113-1.653-.758-1.653h-.266l-.068-.006z'/%3E%3C/svg%3E");-webkit-mask:var(--nova-icon) no-repeat;mask:var(--nova-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em;}
|
|
101
101
|
.nova-theme-select-icon-light{--nova-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M12 19a1 1 0 0 1 1 1v2a1 1 0 0 1-2 0v-2a1 1 0 0 1 1-1m-4.95-2.05a1 1 0 0 1 0 1.414l-1.414 1.414a1 1 0 1 1-1.414-1.414l1.414-1.414a1 1 0 0 1 1.414 0m11.314 0l1.414 1.414a1 1 0 0 1-1.414 1.414l-1.414-1.414a1 1 0 0 1 1.414-1.414m-5.049-9.836a5 5 0 1 1-2.532 9.674a5 5 0 0 1 2.532-9.674M4 11a1 1 0 0 1 0 2H2a1 1 0 0 1 0-2zm18 0a1 1 0 0 1 0 2h-2a1 1 0 0 1 0-2zM5.636 4.222L7.05 5.636A1 1 0 0 1 5.636 7.05L4.222 5.636a1 1 0 0 1 1.414-1.414m14.142 0a1 1 0 0 1 0 1.414L18.364 7.05a1 1 0 0 1-1.414-1.414l1.414-1.414a1 1 0 0 1 1.414 0M12 1a1 1 0 0 1 1 1v2a1 1 0 0 1-2 0V2a1 1 0 0 1 1-1'/%3E%3C/svg%3E");-webkit-mask:var(--nova-icon) no-repeat;mask:var(--nova-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:1em;height:1em;}
|
|
102
|
-
.nova-code-container{position:relative;}
|
|
102
|
+
.nova-code-container{position:relative;overflow:hidden;border-width:1px;border-color:var(--sl-color-gray-5);border-radius:0.375rem;border-style:solid;}
|
|
103
|
+
.nova-code-container pre{position:relative;}
|
|
103
104
|
.nova-code-copy-button{position:absolute;right:0.5rem;top:0.5rem;margin:0;width:1.5rem;height:1.5rem;border-width:1px;border-color:var(--sl-color-gray-5);border-radius:0.25rem;border-style:solid;background-color:rgb(243 244 246 / 0.3) /* #f3f4f6 */;padding:0.25rem;--nova-text-opacity:1;color:rgb(0 0 0 / var(--nova-text-opacity)) /* #000 */;--nova-backdrop-blur:blur(4px);-webkit-backdrop-filter:var(--nova-backdrop-blur) var(--nova-backdrop-brightness) var(--nova-backdrop-contrast) var(--nova-backdrop-grayscale) var(--nova-backdrop-hue-rotate) var(--nova-backdrop-invert) var(--nova-backdrop-opacity) var(--nova-backdrop-saturate) var(--nova-backdrop-sepia);backdrop-filter:var(--nova-backdrop-blur) var(--nova-backdrop-brightness) var(--nova-backdrop-contrast) var(--nova-backdrop-grayscale) var(--nova-backdrop-hue-rotate) var(--nova-backdrop-invert) var(--nova-backdrop-opacity) var(--nova-backdrop-saturate) var(--nova-backdrop-sepia);transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:150ms;}
|
|
104
105
|
.nova-link-card{position:relative;display:flex;flex-direction:column;gap:0.5rem;border-width:1px;border-color:var(--sl-color-gray-5);border-radius:0.75rem;border-style:solid;--nova-bg-opacity:1;background-color:rgb(255 255 255 / var(--nova-bg-opacity)) /* #fff */;padding-left:1.25rem;padding-right:1.25rem;padding-top:1rem;padding-bottom:1rem;--nova-text-opacity:1;color:rgb(55 65 81 / var(--nova-text-opacity)) /* #374151 */;--nova-shadow:var(--nova-shadow-inset) 0 1px 2px 0 var(--nova-shadow-color, rgb(0 0 0 / 0.05));box-shadow:var(--nova-ring-offset-shadow), var(--nova-ring-shadow), var(--nova-shadow);transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:150ms;transition-duration:200ms;}
|
|
105
106
|
.nova-page-frame-header{position:fixed;inset:0;z-index:var(--sl-z-index-navbar);box-sizing:border-box;width:100%;height:var(--sl-nav-height);border-width:0px;border-bottom-width:1px;border-color:var(--sl-color-hairline);border-style:solid;background-color:var(--sl-color-bg-nav) /* var(--sl-color-bg-nav) */;padding-top:var(--sl-nav-pad-y);padding-bottom:var(--sl-nav-pad-y);padding-left:var(--sl-nav-pad-x);padding-right:var(--sl-nav-pad-x);--nova-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--nova-backdrop-blur) var(--nova-backdrop-brightness) var(--nova-backdrop-contrast) var(--nova-backdrop-grayscale) var(--nova-backdrop-hue-rotate) var(--nova-backdrop-invert) var(--nova-backdrop-opacity) var(--nova-backdrop-saturate) var(--nova-backdrop-sepia);backdrop-filter:var(--nova-backdrop-blur) var(--nova-backdrop-brightness) var(--nova-backdrop-contrast) var(--nova-backdrop-grayscale) var(--nova-backdrop-hue-rotate) var(--nova-backdrop-invert) var(--nova-backdrop-opacity) var(--nova-backdrop-saturate) var(--nova-backdrop-sepia);}
|
|
@@ -108,6 +109,8 @@
|
|
|
108
109
|
.nova-pagination-link{margin:0;display:flex;align-items:center;justify-content:flex-end;gap:0.5rem;border-radius:0.75rem;padding:0.5rem;color:var(--sl-color-gray-2) /* var(--sl-color-gray-2) */;font-weight:500;text-decoration:none;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:150ms;transition-duration:100ms;}
|
|
109
110
|
.nova-link-button{margin-inline-end:0.5rem;margin-top:0.5rem;margin-bottom:0.5rem;display:inline-flex;align-items:center;justify-content:space-between;gap:0.5rem;border-width:1px;border-color:transparent;border-radius:0.75rem;border-style:solid;padding-left:1.5rem;padding-right:1.5rem;padding-top:0.75rem;padding-bottom:0.75rem;font-weight:500;text-decoration:none;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:150ms;transition-duration:200ms;}
|
|
110
111
|
.nova-header{box-sizing:border-box;height:100%;display:flex;align-items:center;gap:0.5rem;}
|
|
112
|
+
div[data-nova-code-container][data-nova-code-title] .nova-code-title{display:block;}
|
|
113
|
+
.nova-code-title{display:none;border-bottom-width:1px;border-bottom-color:var(--sl-color-gray-5);border-bottom-style:solid;background-color:var(--sl-color-bg) /* var(--sl-color-bg) */;padding-left:1rem;padding-right:1rem;padding-top:0.5rem;padding-bottom:0.5rem;font-size:0.875rem;line-height:1.25rem;color:var(--sl-color-gray-3) /* var(--sl-color-gray-3) */;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;}
|
|
111
114
|
.nova-header-actions{display:none;align-items:center;gap:0.5rem;}
|
|
112
115
|
.nova-social-icons-link{width:2rem;height:2rem;display:flex;border-radius:0.375rem;padding:0.5rem;color:var(--sl-color-text) /* var(--sl-color-text) */;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:150ms;}
|
|
113
116
|
.nova-theme-select{width:2rem;height:2rem;border-radius:0.375rem;padding:0.5rem;color:var(--sl-color-text) /* var(--sl-color-text) */;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-duration:150ms;}
|
|
@@ -126,6 +129,7 @@
|
|
|
126
129
|
.nova-pagination-link:active[data-side="left"]{--nova-translate-x:-0.25rem;transform:translateX(var(--nova-translate-x)) translateY(var(--nova-translate-y)) translateZ(var(--nova-translate-z)) rotate(var(--nova-rotate)) rotateX(var(--nova-rotate-x)) rotateY(var(--nova-rotate-y)) rotateZ(var(--nova-rotate-z)) skewX(var(--nova-skew-x)) skewY(var(--nova-skew-y)) scaleX(var(--nova-scale-x)) scaleY(var(--nova-scale-y)) scaleZ(var(--nova-scale-z));}
|
|
127
130
|
.nova-pagination-link:active[data-side="right"]{--nova-translate-x:0.25rem;transform:translateX(var(--nova-translate-x)) translateY(var(--nova-translate-y)) translateZ(var(--nova-translate-z)) rotate(var(--nova-rotate)) rotateX(var(--nova-rotate-x)) rotateY(var(--nova-rotate-y)) rotateZ(var(--nova-rotate-z)) skewX(var(--nova-skew-x)) skewY(var(--nova-skew-y)) scaleX(var(--nova-scale-x)) scaleY(var(--nova-scale-y)) scaleZ(var(--nova-scale-z));}
|
|
128
131
|
.nova-code-copy-button:active{--nova-scale-x:0.9;--nova-scale-y:0.9;transform:translateX(var(--nova-translate-x)) translateY(var(--nova-translate-y)) translateZ(var(--nova-translate-z)) rotate(var(--nova-rotate)) rotateX(var(--nova-rotate-x)) rotateY(var(--nova-rotate-y)) rotateZ(var(--nova-rotate-z)) skewX(var(--nova-skew-x)) skewY(var(--nova-skew-y)) scaleX(var(--nova-scale-x)) scaleY(var(--nova-scale-y)) scaleZ(var(--nova-scale-z));}
|
|
132
|
+
.sl-markdown-content .nova-code-container pre.astro-code{border-width:0px;border-color:transparent;border-radius:0;}
|
|
129
133
|
.nova-page-frame-sidebar-pane{border-width:0px;border-color:var(--sl-color-hairline);border-style:solid;}
|
|
130
134
|
.nova-link-button-secondary{border-color:var(--sl-color-gray-5);--nova-bg-opacity:1;background-color:rgb(255 255 255 / var(--nova-bg-opacity)) /* #fff */;--nova-text-opacity:1;color:rgb(55 65 81 / var(--nova-text-opacity)) /* #374151 */;--nova-shadow:var(--nova-shadow-inset) 0 1px 2px 0 var(--nova-shadow-color, rgb(0 0 0 / 0.05));box-shadow:var(--nova-ring-offset-shadow), var(--nova-ring-shadow), var(--nova-shadow);}
|
|
131
135
|
.nova-mobile-table-of-contents summary{border-bottom-color:var(--sl-color-hairline);}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "starlight-theme-nova",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"description": "",
|
|
6
6
|
"author": "ocavue <ocavue@gmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -29,8 +29,10 @@
|
|
|
29
29
|
"@shikijs/transformers": "^3.2.1",
|
|
30
30
|
"@shikijs/twoslash": "^3.2.1",
|
|
31
31
|
"@shikijs/types": "^3.2.1",
|
|
32
|
+
"@types/hast": "^3.0.4",
|
|
32
33
|
"astro-theme-toggle": "^0.6.0",
|
|
33
34
|
"hast-util-is-element": "^3.0.0",
|
|
35
|
+
"rehype": "^13.0.2",
|
|
34
36
|
"shiki-twoslash-renderer": "0.0.2"
|
|
35
37
|
},
|
|
36
38
|
"devDependencies": {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
import { Tabs } from '@astrojs/starlight/components'
|
|
3
|
+
import { processCodeTabs } from './rehype-code-tabs'
|
|
3
4
|
|
|
4
5
|
interface Props {
|
|
5
6
|
border?: boolean
|
|
@@ -7,11 +8,14 @@ interface Props {
|
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
const { border = true, syncKey } = Astro.props
|
|
11
|
+
|
|
12
|
+
const originalHtml = await Astro.slots.render('default')
|
|
13
|
+
const processedHtml = processCodeTabs(originalHtml)
|
|
10
14
|
---
|
|
11
15
|
|
|
12
16
|
<div class:list={['code-tabs', border ? 'code-tabs-border' : undefined]}>
|
|
13
17
|
<Tabs syncKey={syncKey}>
|
|
14
|
-
<
|
|
18
|
+
<Fragment set:html={processedHtml} />
|
|
15
19
|
</Tabs>
|
|
16
20
|
</div>
|
|
17
21
|
|
|
@@ -59,12 +63,14 @@ const { border = true, syncKey } = Astro.props
|
|
|
59
63
|
margin: 0;
|
|
60
64
|
}
|
|
61
65
|
|
|
62
|
-
|
|
63
|
-
border-
|
|
66
|
+
.astro-code {
|
|
67
|
+
border-radius: 0;
|
|
64
68
|
}
|
|
65
69
|
|
|
66
|
-
.
|
|
70
|
+
.nova-code-container {
|
|
67
71
|
border-radius: 0;
|
|
72
|
+
border-width: 0;
|
|
73
|
+
border-color: transparent;
|
|
68
74
|
}
|
|
69
75
|
}
|
|
70
76
|
</style>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { Element, ElementContent } from 'hast'
|
|
2
|
+
import { rehype } from 'rehype'
|
|
3
|
+
|
|
4
|
+
import { CODE_PROPERTY_CONTAINER, CODE_PROPERTY_TITLE } from '../constants'
|
|
5
|
+
|
|
6
|
+
// https://github.com/withastro/starlight/blob/bdb05e704a6cf06a029367f99b6bf2f575e5a5f3/packages/starlight/user-components/rehype-tabs.ts#L20
|
|
7
|
+
export const TabItemTagname = 'starlight-tab-item'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Rehype processor to extract tab panel data and turn each
|
|
11
|
+
* `<starlight-tab-item>` into a `<div>` with the necessary
|
|
12
|
+
* attributes.
|
|
13
|
+
*/
|
|
14
|
+
const tabsProcessor = rehype()
|
|
15
|
+
.data('settings', { fragment: true })
|
|
16
|
+
.use(() => {
|
|
17
|
+
return (tree: Element) => {
|
|
18
|
+
return {
|
|
19
|
+
...tree,
|
|
20
|
+
children: tree.children.map(replacePre),
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
function replacePre(node: ElementContent): ElementContent {
|
|
26
|
+
if (
|
|
27
|
+
node.type === 'element' &&
|
|
28
|
+
node.tagName === 'div' &&
|
|
29
|
+
node.properties[CODE_PROPERTY_CONTAINER] != null
|
|
30
|
+
) {
|
|
31
|
+
const title = node.properties[CODE_PROPERTY_TITLE]
|
|
32
|
+
|
|
33
|
+
if (title) {
|
|
34
|
+
node.properties[CODE_PROPERTY_TITLE] = undefined
|
|
35
|
+
return {
|
|
36
|
+
type: 'element',
|
|
37
|
+
tagName: TabItemTagname,
|
|
38
|
+
properties: {
|
|
39
|
+
dataLabel: title,
|
|
40
|
+
},
|
|
41
|
+
children: [node],
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return node
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Processes the children of the `<CodeTabs>` component to transform
|
|
51
|
+
* any code blocks with "title" meta information into a <TabItem> component.
|
|
52
|
+
*/
|
|
53
|
+
export function processCodeTabs(html: string): string {
|
|
54
|
+
const file = tabsProcessor.processSync({ value: html })
|
|
55
|
+
return file.toString()
|
|
56
|
+
}
|
package/src/constants.ts
CHANGED
package/src/shiki-config.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
transformerMetaHighlight,
|
|
3
3
|
transformerMetaWordHighlight,
|
|
4
|
-
transformerNotationDiff,
|
|
4
|
+
transformerNotationDiff,transformerRemoveNotationEscape,
|
|
5
5
|
transformerNotationHighlight,
|
|
6
6
|
transformerNotationWordHighlight,
|
|
7
7
|
} from '@shikijs/transformers'
|
|
@@ -10,6 +10,7 @@ import type { ShikiTransformer } from '@shikijs/types'
|
|
|
10
10
|
import type { ShikiConfig } from 'astro'
|
|
11
11
|
import { createRenderer } from 'shiki-twoslash-renderer'
|
|
12
12
|
|
|
13
|
+
import { transformerContainer } from './shiki-transformer-container'
|
|
13
14
|
import { transformerCopyButton } from './shiki-transformer-copy-button'
|
|
14
15
|
|
|
15
16
|
export function createShikiConfig(options: { twoslash: boolean }): ShikiConfig {
|
|
@@ -19,8 +20,10 @@ export function createShikiConfig(options: { twoslash: boolean }): ShikiConfig {
|
|
|
19
20
|
transformerNotationDiff(),
|
|
20
21
|
transformerNotationHighlight(),
|
|
21
22
|
transformerNotationWordHighlight(),
|
|
23
|
+
transformerRemoveNotationEscape(),
|
|
22
24
|
|
|
23
25
|
transformerCopyButton(),
|
|
26
|
+
transformerContainer(),
|
|
24
27
|
options.twoslash
|
|
25
28
|
? transformerTwoslash({
|
|
26
29
|
renderer: createRenderer(),
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { ShikiTransformer } from '@shikijs/types'
|
|
2
|
+
import type { ElementContent, RootContent } from 'hast'
|
|
3
|
+
import { isElement } from 'hast-util-is-element'
|
|
4
|
+
|
|
5
|
+
import { CODE_PROPERTY_CONTAINER, CODE_PROPERTY_TITLE } from './constants'
|
|
6
|
+
import { parseTitleString } from './shiki-meta-title'
|
|
7
|
+
|
|
8
|
+
const name = 'starlight-theme-nova-shiki-transformer-container'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A transformer to wrap code blocks in a container.
|
|
12
|
+
*/
|
|
13
|
+
export function transformerContainer(): ShikiTransformer {
|
|
14
|
+
return {
|
|
15
|
+
name: name,
|
|
16
|
+
root(node) {
|
|
17
|
+
if (node.children.length === 0) {
|
|
18
|
+
throw new Error(`[${name}] Expected at least one child`)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const pre = node.children.find((child) => isElement(child, 'pre'))
|
|
22
|
+
|
|
23
|
+
if (!pre) {
|
|
24
|
+
throw new Error(
|
|
25
|
+
`[${name}] Expected a <pre> element in the root node but got ${JSON.stringify(node)}`,
|
|
26
|
+
)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const title = parseTitleString(this.options.meta?.__raw || '')
|
|
30
|
+
|
|
31
|
+
const children: ElementContent[] = normalizeContent(node.children)
|
|
32
|
+
|
|
33
|
+
if (title) {
|
|
34
|
+
children.unshift({
|
|
35
|
+
type: 'element',
|
|
36
|
+
tagName: 'div',
|
|
37
|
+
properties: {
|
|
38
|
+
class: 'nova-code-title',
|
|
39
|
+
},
|
|
40
|
+
children: [
|
|
41
|
+
{
|
|
42
|
+
type: 'text',
|
|
43
|
+
value: title,
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
node.children = [
|
|
50
|
+
{
|
|
51
|
+
type: 'element',
|
|
52
|
+
tagName: 'div',
|
|
53
|
+
properties: {
|
|
54
|
+
[CODE_PROPERTY_CONTAINER]: '',
|
|
55
|
+
[CODE_PROPERTY_TITLE]: title || undefined,
|
|
56
|
+
class: 'nova-code-container not-content',
|
|
57
|
+
},
|
|
58
|
+
children,
|
|
59
|
+
},
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
return node
|
|
63
|
+
},
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// A simple function to make typescript happy
|
|
68
|
+
function normalizeContent(children: RootContent[]): ElementContent[] {
|
|
69
|
+
return children.filter((child) => child.type !== 'doctype')
|
|
70
|
+
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { ShikiTransformer } from '@shikijs/types'
|
|
2
|
-
import { isElement } from 'hast-util-is-element'
|
|
3
2
|
|
|
4
3
|
const name = 'starlight-theme-nova-shiki-transformer-copy-button'
|
|
5
4
|
|
|
@@ -9,42 +8,25 @@ const name = 'starlight-theme-nova-shiki-transformer-copy-button'
|
|
|
9
8
|
export function transformerCopyButton(): ShikiTransformer {
|
|
10
9
|
return {
|
|
11
10
|
name: name,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
type: 'element',
|
|
27
|
-
tagName: 'div',
|
|
28
|
-
properties: {
|
|
29
|
-
class: 'nova-code-container not-content',
|
|
30
|
-
},
|
|
31
|
-
children: [
|
|
32
|
-
pre,
|
|
33
|
-
{
|
|
34
|
-
type: 'element',
|
|
35
|
-
tagName: 'nova-code-copy-button',
|
|
36
|
-
properties: {
|
|
37
|
-
type: 'button',
|
|
38
|
-
'data-code': this.source,
|
|
39
|
-
title: 'Copy code',
|
|
40
|
-
'aria-label': 'Copy code',
|
|
41
|
-
class: 'nova-code-copy-button',
|
|
42
|
-
},
|
|
43
|
-
children: [],
|
|
11
|
+
pre(node) {
|
|
12
|
+
return {
|
|
13
|
+
...node,
|
|
14
|
+
children: [
|
|
15
|
+
...node.children,
|
|
16
|
+
{
|
|
17
|
+
type: 'element',
|
|
18
|
+
tagName: 'nova-code-copy-button',
|
|
19
|
+
properties: {
|
|
20
|
+
type: 'button',
|
|
21
|
+
'data-code': this.source,
|
|
22
|
+
title: 'Copy code',
|
|
23
|
+
'aria-label': 'Copy code',
|
|
24
|
+
class: 'nova-code-copy-button',
|
|
44
25
|
},
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
26
|
+
children: [],
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
}
|
|
48
30
|
},
|
|
49
31
|
}
|
|
50
32
|
}
|