@markup-carve/carve-grammars 0.1.2
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/LICENSE +21 -0
- package/README.md +240 -0
- package/highlightjs/carve.js +537 -0
- package/highlightjs/carve.mjs +25 -0
- package/package.json +119 -0
- package/prism/carve.js +471 -0
- package/shiki/carve.css +46 -0
- package/shiki/index.js +188 -0
- package/textmate/carve.tmLanguage.json +1023 -0
- package/tiptap/carve-kit.js +507 -0
- package/tiptap/extensions/carve-abbreviation.js +79 -0
- package/tiptap/extensions/carve-definition-list.js +270 -0
- package/tiptap/extensions/carve-delete.js +54 -0
- package/tiptap/extensions/carve-div.js +188 -0
- package/tiptap/extensions/carve-embed.js +248 -0
- package/tiptap/extensions/carve-footnote-definition.js +81 -0
- package/tiptap/extensions/carve-footnote.js +76 -0
- package/tiptap/extensions/carve-insert.js +54 -0
- package/tiptap/extensions/carve-keymap.js +71 -0
- package/tiptap/extensions/carve-math.js +82 -0
- package/tiptap/extensions/carve-mention.js +44 -0
- package/tiptap/extensions/carve-span.js +101 -0
- package/tiptap/extensions/carve-tabs.js +158 -0
- package/tiptap/extensions/index.js +14 -0
- package/tiptap/index.js +53 -0
- package/tiptap/serializer.js +686 -0
package/shiki/index.js
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Shiki setup for Carve documentation sites.
|
|
3
|
+
*
|
|
4
|
+
* One import gives a docs site the same Carve highlighting everywhere:
|
|
5
|
+
* the TextMate grammar, GitHub-theme scope extras for Carve-specific
|
|
6
|
+
* scopes, and the transformer + CSS that bridge what Shiki's HTML
|
|
7
|
+
* emitter cannot express (strikethrough, sub/superscript positioning,
|
|
8
|
+
* highlight background).
|
|
9
|
+
*
|
|
10
|
+
* VitePress usage:
|
|
11
|
+
*
|
|
12
|
+
* // .vitepress/config.ts
|
|
13
|
+
* import { carveMarkdown } from 'carve-grammars/shiki'
|
|
14
|
+
* export default defineConfig({
|
|
15
|
+
* markdown: { ...carveMarkdown() },
|
|
16
|
+
* })
|
|
17
|
+
*
|
|
18
|
+
* // .vitepress/theme/index.ts
|
|
19
|
+
* import 'carve-grammars/shiki/carve.css'
|
|
20
|
+
*/
|
|
21
|
+
import { createRequire } from 'node:module'
|
|
22
|
+
import githubLight from '@shikijs/themes/github-light'
|
|
23
|
+
import githubDark from '@shikijs/themes/github-dark'
|
|
24
|
+
|
|
25
|
+
const require = createRequire(import.meta.url)
|
|
26
|
+
|
|
27
|
+
/** The Carve TextMate grammar, ready for Shiki's `languages` array. */
|
|
28
|
+
export const carveGrammar = {
|
|
29
|
+
...require('../textmate/carve.tmLanguage.json'),
|
|
30
|
+
name: 'carve',
|
|
31
|
+
aliases: ['crv', 'Carve'],
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Token-color rules for Carve scopes the stock GitHub themes do not
|
|
36
|
+
* style: highlight, sub/superscript, code fences, lists and checkboxes,
|
|
37
|
+
* tables, admonitions, captions, attributes, mentions/tags,
|
|
38
|
+
* abbreviations, links and math.
|
|
39
|
+
*/
|
|
40
|
+
export const carveLightExtras = [
|
|
41
|
+
{ scope: 'markup.bold.italic', settings: { foreground: '#24292e', fontStyle: 'italic bold' } },
|
|
42
|
+
{ scope: 'markup.highlight', settings: { foreground: '#b08800', fontStyle: 'bold' } },
|
|
43
|
+
{ scope: 'markup.superscript', settings: { foreground: '#6f42c1' } },
|
|
44
|
+
{ scope: 'markup.subscript', settings: { foreground: '#6f42c1' } },
|
|
45
|
+
{ scope: 'markup.raw.inline', settings: { foreground: '#005cc5' } },
|
|
46
|
+
{ scope: 'markup.raw.code', settings: { foreground: '#6a737d' } },
|
|
47
|
+
{ scope: 'fenced_code.block.language', settings: { foreground: '#22863a', fontStyle: 'bold' } },
|
|
48
|
+
{ scope: 'punctuation.definition.fenced', settings: { foreground: '#959da5' } },
|
|
49
|
+
{ scope: 'punctuation.definition.raw', settings: { foreground: '#959da5' } },
|
|
50
|
+
{ scope: ['punctuation.definition.list.unnumbered', 'punctuation.definition.list.numbered', 'punctuation.definition.list'], settings: { foreground: '#d73a49', fontStyle: 'bold' } },
|
|
51
|
+
{ scope: 'punctuation.definition.checkbox', settings: { foreground: '#959da5' } },
|
|
52
|
+
{ scope: 'constant.language.checkbox', settings: { foreground: '#22863a', fontStyle: 'bold' } },
|
|
53
|
+
{ scope: 'keyword.operator.table.header', settings: { foreground: '#d73a49', fontStyle: 'bold' } },
|
|
54
|
+
{ scope: ['keyword.operator.table.rowspan', 'keyword.operator.table.colspan', 'keyword.operator.table.continuation'], settings: { foreground: '#e36209', fontStyle: 'bold' } },
|
|
55
|
+
{ scope: 'keyword.operator.table.alignment', settings: { foreground: '#e36209' } },
|
|
56
|
+
{ scope: 'punctuation.separator.table', settings: { foreground: '#959da5' } },
|
|
57
|
+
{ scope: 'punctuation.definition.admonition', settings: { foreground: '#d73a49', fontStyle: 'bold' } },
|
|
58
|
+
{ scope: 'entity.name.tag.admonition', settings: { foreground: '#22863a', fontStyle: 'bold' } },
|
|
59
|
+
{ scope: 'string.unquoted.admonition.title', settings: { foreground: '#032f62' } },
|
|
60
|
+
{ scope: 'punctuation.definition.caption', settings: { foreground: '#e36209', fontStyle: 'bold' } },
|
|
61
|
+
{ scope: 'markup.caption', settings: { foreground: '#6a737d', fontStyle: 'italic' } },
|
|
62
|
+
{ scope: 'meta.attributes', settings: { foreground: '#e36209' } },
|
|
63
|
+
{ scope: 'punctuation.definition.attributes', settings: { foreground: '#959da5' } },
|
|
64
|
+
{ scope: 'punctuation.definition.mention', settings: { foreground: '#d73a49' } },
|
|
65
|
+
{ scope: 'variable.other.mention', settings: { foreground: '#d73a49', fontStyle: 'bold' } },
|
|
66
|
+
{ scope: 'punctuation.definition.tag', settings: { foreground: '#22863a' } },
|
|
67
|
+
{ scope: 'variable.other.tag', settings: { foreground: '#22863a', fontStyle: 'bold' } },
|
|
68
|
+
{ scope: 'punctuation.definition.symbol', settings: { foreground: '#959da5' } },
|
|
69
|
+
{ scope: 'constant.language.symbol', settings: { foreground: '#e36209', fontStyle: 'bold' } },
|
|
70
|
+
{ scope: 'entity.name.abbreviation', settings: { foreground: '#005cc5', fontStyle: 'bold' } },
|
|
71
|
+
{ scope: 'string.unquoted.abbreviation', settings: { foreground: '#6a737d', fontStyle: 'italic' } },
|
|
72
|
+
{ scope: ['punctuation.definition.link', 'punctuation.definition.image'], settings: { foreground: '#d73a49' } },
|
|
73
|
+
{ scope: ['string.other.link.title', 'string.other.link.description', 'string.other.image.alt'], settings: { foreground: '#005cc5' } },
|
|
74
|
+
{ scope: 'markup.underline.link', settings: { foreground: '#032f62', fontStyle: 'underline' } },
|
|
75
|
+
{ scope: 'constant.other.reference.link', settings: { foreground: '#005cc5', fontStyle: 'bold' } },
|
|
76
|
+
{ scope: 'markup.math', settings: { foreground: '#6f42c1' } },
|
|
77
|
+
{ scope: 'punctuation.definition.math', settings: { foreground: '#959da5' } },
|
|
78
|
+
// Inline emphasis delimiters recede like code backticks: the content
|
|
79
|
+
// already carries the styling (bold, italic, raised, lowered, marked).
|
|
80
|
+
{ scope: ['punctuation.definition.bold', 'punctuation.definition.italic', 'punctuation.definition.bold-italic', 'punctuation.definition.underline', 'punctuation.definition.strike', 'punctuation.definition.superscript', 'punctuation.definition.subscript', 'punctuation.definition.highlight'], settings: { foreground: '#959da5' } },
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
export const carveDarkExtras = [
|
|
84
|
+
{ scope: 'markup.bold.italic', settings: { foreground: '#e1e4e8', fontStyle: 'italic bold' } },
|
|
85
|
+
{ scope: 'markup.highlight', settings: { foreground: '#ffd33d', fontStyle: 'bold' } },
|
|
86
|
+
{ scope: 'markup.superscript', settings: { foreground: '#b392f0' } },
|
|
87
|
+
{ scope: 'markup.subscript', settings: { foreground: '#b392f0' } },
|
|
88
|
+
{ scope: 'markup.raw.inline', settings: { foreground: '#79b8ff' } },
|
|
89
|
+
{ scope: 'markup.raw.code', settings: { foreground: '#959da5' } },
|
|
90
|
+
{ scope: 'fenced_code.block.language', settings: { foreground: '#85e89d', fontStyle: 'bold' } },
|
|
91
|
+
{ scope: 'punctuation.definition.fenced', settings: { foreground: '#6a737d' } },
|
|
92
|
+
{ scope: 'punctuation.definition.raw', settings: { foreground: '#6a737d' } },
|
|
93
|
+
{ scope: ['punctuation.definition.list.unnumbered', 'punctuation.definition.list.numbered', 'punctuation.definition.list'], settings: { foreground: '#f97583', fontStyle: 'bold' } },
|
|
94
|
+
{ scope: 'punctuation.definition.checkbox', settings: { foreground: '#6a737d' } },
|
|
95
|
+
{ scope: 'constant.language.checkbox', settings: { foreground: '#85e89d', fontStyle: 'bold' } },
|
|
96
|
+
{ scope: 'keyword.operator.table.header', settings: { foreground: '#f97583', fontStyle: 'bold' } },
|
|
97
|
+
{ scope: ['keyword.operator.table.rowspan', 'keyword.operator.table.colspan', 'keyword.operator.table.continuation'], settings: { foreground: '#ffab70', fontStyle: 'bold' } },
|
|
98
|
+
{ scope: 'keyword.operator.table.alignment', settings: { foreground: '#ffab70' } },
|
|
99
|
+
{ scope: 'punctuation.separator.table', settings: { foreground: '#6a737d' } },
|
|
100
|
+
{ scope: 'punctuation.definition.admonition', settings: { foreground: '#f97583', fontStyle: 'bold' } },
|
|
101
|
+
{ scope: 'entity.name.tag.admonition', settings: { foreground: '#85e89d', fontStyle: 'bold' } },
|
|
102
|
+
{ scope: 'string.unquoted.admonition.title', settings: { foreground: '#79b8ff' } },
|
|
103
|
+
{ scope: 'punctuation.definition.caption', settings: { foreground: '#ffab70', fontStyle: 'bold' } },
|
|
104
|
+
{ scope: 'markup.caption', settings: { foreground: '#959da5', fontStyle: 'italic' } },
|
|
105
|
+
{ scope: 'meta.attributes', settings: { foreground: '#ffab70' } },
|
|
106
|
+
{ scope: 'punctuation.definition.attributes', settings: { foreground: '#6a737d' } },
|
|
107
|
+
{ scope: 'punctuation.definition.mention', settings: { foreground: '#f97583' } },
|
|
108
|
+
{ scope: 'variable.other.mention', settings: { foreground: '#f97583', fontStyle: 'bold' } },
|
|
109
|
+
{ scope: 'punctuation.definition.tag', settings: { foreground: '#85e89d' } },
|
|
110
|
+
{ scope: 'variable.other.tag', settings: { foreground: '#85e89d', fontStyle: 'bold' } },
|
|
111
|
+
{ scope: 'punctuation.definition.symbol', settings: { foreground: '#6a737d' } },
|
|
112
|
+
{ scope: 'constant.language.symbol', settings: { foreground: '#ffab70', fontStyle: 'bold' } },
|
|
113
|
+
{ scope: 'entity.name.abbreviation', settings: { foreground: '#79b8ff', fontStyle: 'bold' } },
|
|
114
|
+
{ scope: 'string.unquoted.abbreviation', settings: { foreground: '#959da5', fontStyle: 'italic' } },
|
|
115
|
+
{ scope: ['punctuation.definition.link', 'punctuation.definition.image'], settings: { foreground: '#f97583' } },
|
|
116
|
+
{ scope: ['string.other.link.title', 'string.other.link.description', 'string.other.image.alt'], settings: { foreground: '#79b8ff' } },
|
|
117
|
+
{ scope: 'markup.underline.link', settings: { foreground: '#9ecbff', fontStyle: 'underline' } },
|
|
118
|
+
{ scope: 'constant.other.reference.link', settings: { foreground: '#79b8ff', fontStyle: 'bold' } },
|
|
119
|
+
{ scope: 'markup.math', settings: { foreground: '#b392f0' } },
|
|
120
|
+
{ scope: 'punctuation.definition.math', settings: { foreground: '#6a737d' } },
|
|
121
|
+
{ scope: ['punctuation.definition.bold', 'punctuation.definition.italic', 'punctuation.definition.bold-italic', 'punctuation.definition.underline', 'punctuation.definition.strike', 'punctuation.definition.superscript', 'punctuation.definition.subscript', 'punctuation.definition.highlight'], settings: { foreground: '#6a737d' } },
|
|
122
|
+
]
|
|
123
|
+
|
|
124
|
+
/** Extend any Shiki theme object with extra token-color rules. */
|
|
125
|
+
export function extendTheme(theme, extras) {
|
|
126
|
+
return { ...theme, tokenColors: [...(theme.tokenColors ?? []), ...extras] }
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** GitHub themes pre-extended with the Carve scope rules. */
|
|
130
|
+
export const carveLightTheme = extendTheme(githubLight, carveLightExtras)
|
|
131
|
+
export const carveDarkTheme = extendTheme(githubDark, carveDarkExtras)
|
|
132
|
+
|
|
133
|
+
const FontStyle = { Italic: 1, Bold: 2, Underline: 4, Strikethrough: 8 }
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Shiki code transformer that tags tokens the HTML emitter cannot style
|
|
137
|
+
* directly. Pair with `carve-grammars/shiki/carve.css`, which styles the
|
|
138
|
+
* emitted `data-carve-*` attributes.
|
|
139
|
+
*/
|
|
140
|
+
export const carveStylingTransformer = {
|
|
141
|
+
name: 'carve-extras',
|
|
142
|
+
preprocess(_code, options) {
|
|
143
|
+
options.includeExplanation = 'scopeName'
|
|
144
|
+
},
|
|
145
|
+
tokens(tokens) {
|
|
146
|
+
for (const line of tokens) {
|
|
147
|
+
for (const tk of line) {
|
|
148
|
+
const scopes = tk.explanation?.flatMap((e) =>
|
|
149
|
+
e.scopes.map((s) => s.scopeName),
|
|
150
|
+
) ?? []
|
|
151
|
+
const hasScope = (prefix) => scopes.some((s) => s.startsWith(prefix))
|
|
152
|
+
|
|
153
|
+
const mark = (attr) => {
|
|
154
|
+
if (!tk.htmlAttrs) tk.htmlAttrs = {}
|
|
155
|
+
tk.htmlAttrs[attr] = ''
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if ((tk.fontStyle ?? 0) & FontStyle.Strikethrough || hasScope('markup.strikethrough')) {
|
|
159
|
+
mark('data-carve-strike')
|
|
160
|
+
}
|
|
161
|
+
if (hasScope('markup.superscript')) mark('data-carve-super')
|
|
162
|
+
if (hasScope('markup.subscript')) mark('data-carve-sub')
|
|
163
|
+
if (hasScope('markup.highlight')) mark('data-carve-highlight')
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Everything a VitePress `markdown` config needs, in one spreadable
|
|
171
|
+
* object: the Carve grammar, the extended dual themes and the styling
|
|
172
|
+
* transformer.
|
|
173
|
+
*
|
|
174
|
+
* @param {object} [options]
|
|
175
|
+
* @param {object} [options.light] Base light theme (default: github-light)
|
|
176
|
+
* @param {object} [options.dark] Base dark theme (default: github-dark)
|
|
177
|
+
* @param {Array} [options.languages] Additional grammars to register
|
|
178
|
+
*/
|
|
179
|
+
export function carveMarkdown(options = {}) {
|
|
180
|
+
const light = extendTheme(options.light ?? githubLight, carveLightExtras)
|
|
181
|
+
const dark = extendTheme(options.dark ?? githubDark, carveDarkExtras)
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
languages: [carveGrammar, ...(options.languages ?? [])],
|
|
185
|
+
theme: { light, dark },
|
|
186
|
+
codeTransformers: [carveStylingTransformer],
|
|
187
|
+
}
|
|
188
|
+
}
|