@codemonster-ru/vue-codeblock 1.0.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/LICENSE +21 -0
- package/README.md +150 -0
- package/dist/components/CodeBlock.vue.d.ts +39 -0
- package/dist/index.css +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +560 -0
- package/dist/index.umd.cjs +11 -0
- package/dist/services/code-highlight.d.ts +3 -0
- package/dist/types.d.ts +25 -0
- package/package.json +74 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026-present Kirill Kolesnikov
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# @codemonster-ru/vue-codeblock
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@codemonster-ru/vue-codeblock)
|
|
4
|
+
[](https://www.npmjs.com/package/@codemonster-ru/vue-codeblock)
|
|
5
|
+
[](https://github.com/codemonster-ru/vue-codeblock/blob/main/LICENSE)
|
|
6
|
+
|
|
7
|
+
Standalone Vue 3 code block component with built-in syntax highlighting, light/dark theme support, copy actions, line numbers, and a small shared highlighting runtime you can also use outside the component.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm i @codemonster-ru/vue-codeblock
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Use Cases
|
|
16
|
+
|
|
17
|
+
- package documentation
|
|
18
|
+
- design system docs
|
|
19
|
+
- internal developer portals
|
|
20
|
+
- settings/admin panels that need to render code examples
|
|
21
|
+
|
|
22
|
+
## Component Usage
|
|
23
|
+
|
|
24
|
+
Register the plugin:
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import { createApp } from "vue";
|
|
28
|
+
import App from "./App.vue";
|
|
29
|
+
import VueCodeBlock from "@codemonster-ru/vue-codeblock";
|
|
30
|
+
|
|
31
|
+
createApp(App).use(VueCodeBlock).mount("#app");
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Or import the component directly:
|
|
35
|
+
|
|
36
|
+
```vue
|
|
37
|
+
<script setup lang="ts">
|
|
38
|
+
import { CodeBlock } from "@codemonster-ru/vue-codeblock";
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<template>
|
|
42
|
+
<CodeBlock
|
|
43
|
+
language="vue"
|
|
44
|
+
filename="ButtonExample.vue"
|
|
45
|
+
:show-line-numbers="true"
|
|
46
|
+
:code="`<Button label="Save" />`"
|
|
47
|
+
/>
|
|
48
|
+
</template>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
If you want the package CSS explicitly:
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
import "@codemonster-ru/vue-codeblock/style.css";
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Runtime Usage
|
|
58
|
+
|
|
59
|
+
The package also exports the shared highlighter:
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import {
|
|
63
|
+
highlightCodeBlock,
|
|
64
|
+
escapeCodeHtml,
|
|
65
|
+
} from "@codemonster-ru/vue-codeblock";
|
|
66
|
+
|
|
67
|
+
const html = highlightCodeBlock("ts", "const answer = 42;");
|
|
68
|
+
const escaped = escapeCodeHtml("<Button />");
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Props
|
|
72
|
+
|
|
73
|
+
| Prop | Type | Default | Purpose |
|
|
74
|
+
| ----------------- | -------------------------------- | -------------- | ------------------------------------ |
|
|
75
|
+
| `code` | `string` | `''` | Raw source code |
|
|
76
|
+
| `language` | `CodeBlockLanguage` | `'plaintext'` | Language hint for highlighting |
|
|
77
|
+
| `filename` | `string` | `''` | Optional filename in header |
|
|
78
|
+
| `showHeader` | `boolean` | `true` | Shows the top meta/action bar |
|
|
79
|
+
| `showLineNumbers` | `boolean` | `false` | Renders line numbers |
|
|
80
|
+
| `copyable` | `boolean` | `true` | Shows copy action |
|
|
81
|
+
| `copyLabel` | `string` | `'Copy'` | Copy button text |
|
|
82
|
+
| `copiedLabel` | `string` | `'Copied'` | Temporary copied state label |
|
|
83
|
+
| `copiedDuration` | `number` | `1200` | Copied state timeout in ms |
|
|
84
|
+
| `languageLabel` | `string` | `'Language'` | Header label before language |
|
|
85
|
+
| `disabled` | `boolean` | `false` | Disables actions |
|
|
86
|
+
| `wrap` | `boolean` | `false` | Enables wrapped lines |
|
|
87
|
+
| `highlight` | `boolean` | `true` | Turns highlighting on/off |
|
|
88
|
+
| `maxHeight` | `string` | `''` | Optional scroll container max height |
|
|
89
|
+
| `ariaLabel` | `string` | `'Code block'` | Accessibility label |
|
|
90
|
+
| `theme` | `'inherit' \| 'light' \| 'dark'` | `'inherit'` | Theme mode override |
|
|
91
|
+
|
|
92
|
+
## Events
|
|
93
|
+
|
|
94
|
+
| Event | Payload |
|
|
95
|
+
| ------ | ------------------ |
|
|
96
|
+
| `copy` | `{ text: string }` |
|
|
97
|
+
|
|
98
|
+
## Slots
|
|
99
|
+
|
|
100
|
+
| Slot | Purpose |
|
|
101
|
+
| --------- | ------------------------------------------ |
|
|
102
|
+
| `actions` | Add custom actions next to the copy button |
|
|
103
|
+
|
|
104
|
+
## Supported Languages
|
|
105
|
+
|
|
106
|
+
Canonical built-in values:
|
|
107
|
+
|
|
108
|
+
`plaintext`, `text`, `txt`, `js`, `javascript`, `ts`, `typescript`, `vue`, `html`, `json`, `bash`, `shell`, `sh`, `css`, `scss`, `sass`
|
|
109
|
+
|
|
110
|
+
You can import them as `SUPPORTED_CODE_BLOCK_LANGUAGES`.
|
|
111
|
+
|
|
112
|
+
## Theming
|
|
113
|
+
|
|
114
|
+
The component ships with light and dark defaults. You can override it with:
|
|
115
|
+
|
|
116
|
+
- `theme="light"`
|
|
117
|
+
- `theme="dark"`
|
|
118
|
+
- `theme="inherit"` and an ancestor `data-theme="dark"`
|
|
119
|
+
|
|
120
|
+
Main CSS custom properties:
|
|
121
|
+
|
|
122
|
+
- `--vcb-background-color`
|
|
123
|
+
- `--vcb-text-color`
|
|
124
|
+
- `--vcb-border-color`
|
|
125
|
+
- `--vcb-padding`
|
|
126
|
+
- `--vcb-font-size`
|
|
127
|
+
- `--vcb-line-height`
|
|
128
|
+
- `--vcb-token-keyword-color`
|
|
129
|
+
- `--vcb-token-string-color`
|
|
130
|
+
- `--vcb-token-number-color`
|
|
131
|
+
- `--vcb-token-variable-color`
|
|
132
|
+
- `--vcb-token-function-color`
|
|
133
|
+
- `--vcb-token-property-color`
|
|
134
|
+
- `--vcb-token-directive-color`
|
|
135
|
+
|
|
136
|
+
Example:
|
|
137
|
+
|
|
138
|
+
```css
|
|
139
|
+
.docs-surface {
|
|
140
|
+
--vcb-background-color: #081224;
|
|
141
|
+
--vcb-border-color: rgba(96, 165, 250, 0.28);
|
|
142
|
+
--vcb-token-keyword-color: #d8b4fe;
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Notes
|
|
147
|
+
|
|
148
|
+
- The built-in highlighter is lightweight and regex-based by design.
|
|
149
|
+
- It is tuned for documentation and UI examples, not for full IDE-grade parsing.
|
|
150
|
+
- If you need more languages later, extend the highlighter runtime rather than patching rendered HTML.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { CodeBlockCopyPayload, CodeBlockProps } from '../types';
|
|
2
|
+
declare function __VLS_template(): {
|
|
3
|
+
attrs: Partial<{}>;
|
|
4
|
+
slots: {
|
|
5
|
+
actions?(_: {}): any;
|
|
6
|
+
};
|
|
7
|
+
refs: {};
|
|
8
|
+
rootEl: HTMLElement;
|
|
9
|
+
};
|
|
10
|
+
type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
|
|
11
|
+
declare const __VLS_component: import('vue').DefineComponent<CodeBlockProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
12
|
+
copy: (payload: CodeBlockCopyPayload) => any;
|
|
13
|
+
}, string, import('vue').PublicProps, Readonly<CodeBlockProps> & Readonly<{
|
|
14
|
+
onCopy?: ((payload: CodeBlockCopyPayload) => any) | undefined;
|
|
15
|
+
}>, {
|
|
16
|
+
code: string;
|
|
17
|
+
language: import('..').CodeBlockLanguage;
|
|
18
|
+
filename: string;
|
|
19
|
+
showHeader: boolean;
|
|
20
|
+
showLineNumbers: boolean;
|
|
21
|
+
copyable: boolean;
|
|
22
|
+
copyLabel: string;
|
|
23
|
+
copiedLabel: string;
|
|
24
|
+
copiedDuration: number;
|
|
25
|
+
languageLabel: string;
|
|
26
|
+
disabled: boolean;
|
|
27
|
+
wrap: boolean;
|
|
28
|
+
highlight: boolean;
|
|
29
|
+
maxHeight: string;
|
|
30
|
+
ariaLabel: string;
|
|
31
|
+
theme: import('..').CodeBlockTheme;
|
|
32
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLElement>;
|
|
33
|
+
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
|
|
34
|
+
export default _default;
|
|
35
|
+
type __VLS_WithTemplateSlots<T, S> = T & {
|
|
36
|
+
new (): {
|
|
37
|
+
$slots: S;
|
|
38
|
+
};
|
|
39
|
+
};
|
package/dist/index.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.vcb{display:grid;gap:var(--vcb-gap, 0);border:1px solid var(--vcb-border-color, #cbd5e1);border-radius:var(--vcb-border-radius, .625rem);background:var(--vcb-background-color, #f8fbff);color:var(--vcb-text-color, #0f172a);font-family:var(--vcb-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-size:var(--vcb-font-size, .8125rem);line-height:var(--vcb-line-height, 1.5)}.vcb__header{display:flex;align-items:center;justify-content:space-between;gap:var(--vcb-header-gap, .75rem);padding:var(--vcb-header-padding, .55rem .75rem);border-bottom:1px solid var(--vcb-header-border-color, rgba(148, 163, 184, .28))}.vcb__meta{display:inline-flex;align-items:center;gap:var(--vcb-meta-gap, .55rem);color:var(--vcb-meta-color, #475569);font-size:var(--vcb-meta-font-size, .75rem)}.vcb__filename{color:var(--vcb-filename-color, #0f172a);font-weight:var(--vcb-filename-font-weight, 600)}.vcb__actions{display:inline-flex;align-items:center;gap:var(--vcb-actions-gap, .45rem)}.vcb__copy{border:1px solid var(--vcb-action-border-color, rgba(148, 163, 184, .38));border-radius:var(--vcb-action-border-radius, .375rem);background:var(--vcb-action-background-color, #ffffff);color:var(--vcb-action-text-color, #0f172a);padding:var(--vcb-action-padding, .2rem .55rem);font-size:var(--vcb-action-font-size, .75rem)}.vcb__pre{margin:0;padding:var(--vcb-padding, .75rem .9rem);overflow:auto;white-space:pre}.vcb__pre_wrap{white-space:pre-wrap;word-break:break-word}.vcb__line{display:flex;align-items:baseline;gap:var(--vcb-line-gap, .7rem)}.vcb__line-number{text-align:right;color:var(--vcb-line-number-color, #64748b);min-width:var(--vcb-line-number-min-width, 2.1rem);-webkit-user-select:none;user-select:none}.vcb__line-content{white-space:inherit}.vcb__token_keyword{color:var(--vcb-token-keyword-color, #8b2fc9)}.vcb__token_string{color:var(--vcb-token-string-color, #0f7b45)}.vcb__token_number{color:var(--vcb-token-number-color, #c2410c)}.vcb__token_comment{color:var(--vcb-token-comment-color, #64748b)}.vcb__token_variable{color:var(--vcb-token-variable-color, #0f4c81)}.vcb__token_identifier{color:var(--vcb-token-identifier-color, #0369a1)}.vcb__token_function{color:var(--vcb-token-function-color, #1d4ed8)}.vcb__token_property{color:var(--vcb-token-property-color, #6d28d9)}.vcb__token_operator{color:var(--vcb-token-operator-color, #be185d)}.vcb__token_tag{color:var(--vcb-token-tag-color, #0f4c81)}.vcb__token_selector{color:var(--vcb-token-selector-color, #0f4c81)}.vcb__token_component{color:var(--vcb-token-component-color, #0369a1)}.vcb__token_attribute{color:var(--vcb-token-attribute-color, #7c3aed)}.vcb__token_directive{color:var(--vcb-token-directive-color, #a21caf)}.vcb[data-theme=dark],:root[data-theme=dark] .vcb:not([data-theme=light]),[data-theme=dark] .vcb:not([data-theme=light]){--vcb-background-color: var( --vcb-dark-background-color, #0a1425 );--vcb-text-color: var(--vcb-dark-text-color, #e2e8f0);--vcb-border-color: var( --vcb-dark-border-color, rgba(148, 163, 184, .35) );--vcb-header-border-color: var( --vcb-dark-header-border-color, rgba(148, 163, 184, .35) );--vcb-meta-color: var(--vcb-dark-meta-color, #93a4bf);--vcb-filename-color: var( --vcb-dark-filename-color, #e2e8f0 );--vcb-action-border-color: var( --vcb-dark-action-border-color, rgba(148, 163, 184, .45) );--vcb-action-background-color: var( --vcb-dark-action-background-color, rgba(15, 23, 42, .7) );--vcb-action-text-color: var( --vcb-dark-action-text-color, #e2e8f0 );--vcb-line-number-color: var( --vcb-dark-line-number-color, #64748b );--vcb-token-keyword-color: var( --vcb-dark-token-keyword-color, #c084fc );--vcb-token-string-color: var( --vcb-dark-token-string-color, #86efac );--vcb-token-number-color: var( --vcb-dark-token-number-color, #fca5a5 );--vcb-token-comment-color: var( --vcb-dark-token-comment-color, #94a3b8 );--vcb-token-variable-color: var( --vcb-dark-token-variable-color, #bfdbfe );--vcb-token-tag-color: var( --vcb-dark-token-tag-color, #93c5fd );--vcb-token-selector-color: var( --vcb-dark-token-selector-color, #93c5fd );--vcb-token-component-color: var( --vcb-dark-token-component-color, #67e8f9 );--vcb-token-attribute-color: var( --vcb-dark-token-attribute-color, #c4b5fd );--vcb-token-directive-color: var( --vcb-dark-token-directive-color, #f0abfc );--vcb-token-identifier-color: var( --vcb-dark-token-identifier-color, #7dd3fc );--vcb-token-function-color: var( --vcb-dark-token-function-color, #93c5fd );--vcb-token-property-color: var( --vcb-dark-token-property-color, #a5b4fc );--vcb-token-operator-color: var( --vcb-dark-token-operator-color, #f0abfc )}.vcb_disabled{opacity:var(--vcb-disabled-opacity, .6)}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Plugin } from 'vue';
|
|
2
|
+
export { default as CodeBlock } from './components/CodeBlock.vue';
|
|
3
|
+
export { escapeCodeHtml, highlightCodeBlock, highlightCodeLine, } from './services/code-highlight';
|
|
4
|
+
export { SUPPORTED_CODE_BLOCK_LANGUAGES, type CodeBlockCopyPayload, type CodeBlockLanguage, type CodeBlockProps, type CodeBlockTheme, type SupportedCodeBlockLanguage, } from './types';
|
|
5
|
+
declare const plugin: Plugin;
|
|
6
|
+
export default plugin;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,560 @@
|
|
|
1
|
+
import { defineComponent as R, ref as F, computed as y, onBeforeUnmount as U, openBlock as m, createElementBlock as b, normalizeClass as q, toDisplayString as w, createCommentVNode as x, createElementVNode as C, renderSlot as G, normalizeStyle as K, Fragment as X, renderList as Y } from "vue";
|
|
2
|
+
const n = (t) => t.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">"), I = (t) => t.replaceAll(""", '"').replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">").replaceAll("&", "&"), B = (t) => n(t), l = (t, o) => `<span class="vcb__token ${t}">${o}</span>`, tt = "\\b\\d(?:[\\d_]*\\d)?(?:\\.\\d(?:[\\d_]*\\d)?)?\\b", et = "\\b-?\\d(?:[\\d_]*\\d)?(?:\\.\\d(?:[\\d_]*\\d)?)?(?:px|rem|em|%|vh|vw|fr|s|ms|deg)?\\b", E = (t) => t.startsWith(":") || t.startsWith("@") || t.startsWith("#") || t.startsWith("v-"), V = (t) => /^[A-Z]/.test(t), nt = (t) => {
|
|
3
|
+
let o = 0, s = l("vcb__token_string", n("`"));
|
|
4
|
+
for (; o < t.length - 1; ) {
|
|
5
|
+
const e = t.indexOf("${", o), i = e === -1 ? t.length - 1 : e, c = t.slice(o, i);
|
|
6
|
+
if (c && (s += l("vcb__token_string", n(c))), e === -1)
|
|
7
|
+
break;
|
|
8
|
+
s += n("${");
|
|
9
|
+
let a = e + 2, r = 1;
|
|
10
|
+
for (; a < t.length && r > 0; ) {
|
|
11
|
+
const u = t[a];
|
|
12
|
+
u === "{" ? r += 1 : u === "}" && (r -= 1), a += 1;
|
|
13
|
+
}
|
|
14
|
+
const _ = t.slice(
|
|
15
|
+
e + 2,
|
|
16
|
+
a - 1
|
|
17
|
+
);
|
|
18
|
+
s += M(_), s += n("}"), o = a;
|
|
19
|
+
}
|
|
20
|
+
return s += l("vcb__token_string", n("`")), s;
|
|
21
|
+
}, M = (t) => H(t), st = (t) => {
|
|
22
|
+
if (t.length < 2)
|
|
23
|
+
return l("vcb__token_string", t);
|
|
24
|
+
const o = t[0], s = I(t.slice(1, -1)), e = M(s), i = o === '"' ? """ : "'";
|
|
25
|
+
return `${i}${e}${i}`;
|
|
26
|
+
}, L = (t, o, s, e, i) => {
|
|
27
|
+
const c = s ? M(I(t)) : l("vcb__token_string", n(t)), a = o === '"' ? """ : "'";
|
|
28
|
+
return `${e ? a : ""}${c}${i ? a : ""}`;
|
|
29
|
+
}, O = (t) => t.replaceAll(/{{\s*([\s\S]*?)\s*}}/g, (o, s) => {
|
|
30
|
+
const e = M(s);
|
|
31
|
+
return `${n("{{ ")}${e}${n(" }}")}`;
|
|
32
|
+
}), T = (t) => t.replaceAll(
|
|
33
|
+
/(\s+)([:@#]?[\w-]+(?::[\w-]+)?)(\s*=\s*)?("[^"]*"|'[^']*')?/g,
|
|
34
|
+
(o, s, e, i = "", c = "") => `${n(s)}${l(
|
|
35
|
+
E(e) ? "vcb__token_directive" : "vcb__token_attribute",
|
|
36
|
+
n(e)
|
|
37
|
+
)}${n(i)}${c ? E(e) ? st(c) : l(
|
|
38
|
+
"vcb__token_string",
|
|
39
|
+
n(c)
|
|
40
|
+
) : ""}`
|
|
41
|
+
), z = (t) => {
|
|
42
|
+
const o = t.match(/^(\s*)<([/\w-]+)([\s\S]*)$/);
|
|
43
|
+
if (!o)
|
|
44
|
+
return n(t);
|
|
45
|
+
const [, s, e, i] = o, c = e.startsWith("/"), a = c ? e.slice(1) : e, r = V(a) ? "vcb__token_component" : "vcb__token_tag";
|
|
46
|
+
return `${n(s)}${n(c ? "</" : "<")}${l(
|
|
47
|
+
r,
|
|
48
|
+
n(a)
|
|
49
|
+
)}${T(String(i))}`;
|
|
50
|
+
}, ct = (t) => {
|
|
51
|
+
if (t.startsWith("<!--") && t.endsWith("-->"))
|
|
52
|
+
return l("vcb__token_comment", n(t));
|
|
53
|
+
const o = t.startsWith("</"), s = t.endsWith("/>"), i = t.slice(
|
|
54
|
+
o ? 2 : 1,
|
|
55
|
+
t.length - (s ? 2 : 1)
|
|
56
|
+
).match(/^([\w-]+)([\s\S]*)$/);
|
|
57
|
+
if (!i)
|
|
58
|
+
return n(t);
|
|
59
|
+
const [, c, a] = i, r = V(c) ? "vcb__token_component" : "vcb__token_tag";
|
|
60
|
+
return `${n(o ? "</" : "<")}${l(
|
|
61
|
+
r,
|
|
62
|
+
n(c)
|
|
63
|
+
)}${T(a)}${n(s ? "/>" : ">")}`;
|
|
64
|
+
}, ot = (t) => n(t).replaceAll(
|
|
65
|
+
/"(?:[^"\\]|\\.)*"(?=\s*:)?/g,
|
|
66
|
+
(s) => l("vcb__token_string", s)
|
|
67
|
+
).replaceAll(
|
|
68
|
+
/\b(true|false|null)\b/g,
|
|
69
|
+
(s) => l("vcb__token_keyword", s)
|
|
70
|
+
).replaceAll(
|
|
71
|
+
/\b-?\d(?:[\d_]*\d)?(?:\.\d(?:[\d_]*\d)?)?(?:[eE][+-]?\d(?:[\d_]*\d)?)?\b/g,
|
|
72
|
+
(s) => l("vcb__token_number", s)
|
|
73
|
+
), it = (t, o) => {
|
|
74
|
+
for (let s = o - 1; s >= 0; s -= 1) {
|
|
75
|
+
const e = t[s];
|
|
76
|
+
if (!/\s/.test(e))
|
|
77
|
+
return e;
|
|
78
|
+
}
|
|
79
|
+
return "";
|
|
80
|
+
}, J = (t, o) => {
|
|
81
|
+
for (let s = o; s < t.length; s += 1) {
|
|
82
|
+
const e = t[s];
|
|
83
|
+
if (!/\s/.test(e))
|
|
84
|
+
return e;
|
|
85
|
+
}
|
|
86
|
+
return "";
|
|
87
|
+
}, rt = (t, o) => {
|
|
88
|
+
let s = o;
|
|
89
|
+
for (; s > 0 && /\s/.test(t[s - 1]); )
|
|
90
|
+
s -= 1;
|
|
91
|
+
return t.slice(0, s).match(/([A-Za-z_$][\w$]*)\s*$/)?.[1] ?? "";
|
|
92
|
+
}, lt = (t, o, s) => {
|
|
93
|
+
const e = it(t, s), i = J(t, s + o.length), c = rt(t, s), a = t.slice(0, s);
|
|
94
|
+
return e === "." || /\?\.\s*$/.test(a) || i === ":" && ["{", ",", ""].includes(e) ? "vcb__token_property" : i === "(" ? "vcb__token_function" : /^[A-Z]/.test(o) || ["import", "from", "new", "class", "extends"].includes(c) ? "vcb__token_identifier" : "vcb__token_variable";
|
|
95
|
+
}, H = (t) => {
|
|
96
|
+
const o = new RegExp(
|
|
97
|
+
`(//.*$)|((["'\`])(?:\\\\.|(?!\\3).)*\\3)|\\b(const|let|var|function|return|if|else|for|while|class|new|import|export|from|await|async|try|catch|throw|true|false|null|undefined)\\b|(=>|\\?\\?|\\?|:|\\.|[{}()[\\],])|${tt}|\\b[A-Za-z_$][\\w$]*\\b`,
|
|
98
|
+
"g"
|
|
99
|
+
);
|
|
100
|
+
let s = 0, e = "";
|
|
101
|
+
for (const i of t.matchAll(o)) {
|
|
102
|
+
const c = i[0] ?? "", a = i.index ?? 0;
|
|
103
|
+
e += n(t.slice(s, a)), i[1] ? e += l(
|
|
104
|
+
"vcb__token_comment",
|
|
105
|
+
n(c)
|
|
106
|
+
) : i[2] ? e += c.startsWith("`") && c.includes("${") ? nt(c) : l("vcb__token_string", n(c)) : i[4] ? e += l(
|
|
107
|
+
"vcb__token_keyword",
|
|
108
|
+
n(c)
|
|
109
|
+
) : i[5] ? e += l(
|
|
110
|
+
"vcb__token_operator",
|
|
111
|
+
n(c)
|
|
112
|
+
) : /^\d/.test(c) ? e += l(
|
|
113
|
+
"vcb__token_number",
|
|
114
|
+
n(c)
|
|
115
|
+
) : e += l(
|
|
116
|
+
lt(t, c, a),
|
|
117
|
+
n(c)
|
|
118
|
+
), s = a + c.length;
|
|
119
|
+
}
|
|
120
|
+
return e += n(t.slice(s)), e;
|
|
121
|
+
}, at = (t, o) => {
|
|
122
|
+
let s = null;
|
|
123
|
+
for (let e = o + 1; e < t.length; e += 1) {
|
|
124
|
+
const i = t[e];
|
|
125
|
+
if (s) {
|
|
126
|
+
i === s && t[e - 1] !== "\\" && (s = null);
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (i === '"' || i === "'") {
|
|
130
|
+
s = i;
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
if (i === ">")
|
|
134
|
+
return e;
|
|
135
|
+
}
|
|
136
|
+
return -1;
|
|
137
|
+
}, k = (t) => {
|
|
138
|
+
if (!t.trim())
|
|
139
|
+
return n(t);
|
|
140
|
+
let o = 0, s = "";
|
|
141
|
+
for (; o < t.length; ) {
|
|
142
|
+
const e = t.indexOf("<", o);
|
|
143
|
+
if (e === -1) {
|
|
144
|
+
s += O(n(t.slice(o)));
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
s += O(
|
|
148
|
+
n(t.slice(o, e))
|
|
149
|
+
);
|
|
150
|
+
const i = at(t, e);
|
|
151
|
+
if (i === -1) {
|
|
152
|
+
s += n(t.slice(e));
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
s += ct(t.slice(e, i + 1)), o = i + 1;
|
|
156
|
+
}
|
|
157
|
+
return s;
|
|
158
|
+
}, ut = (t) => {
|
|
159
|
+
const o = t.match(/^(\s*)(npm)(\s+)(run)(\s+)([^\s].*)$/);
|
|
160
|
+
if (o) {
|
|
161
|
+
const [
|
|
162
|
+
,
|
|
163
|
+
r,
|
|
164
|
+
_,
|
|
165
|
+
u,
|
|
166
|
+
f,
|
|
167
|
+
h,
|
|
168
|
+
d
|
|
169
|
+
] = o;
|
|
170
|
+
return `${n(r)}${l(
|
|
171
|
+
"vcb__token_keyword",
|
|
172
|
+
n(_)
|
|
173
|
+
)}${n(u)}${l(
|
|
174
|
+
"vcb__token_function",
|
|
175
|
+
n(f)
|
|
176
|
+
)}${n(h)}${l(
|
|
177
|
+
"vcb__token_variable",
|
|
178
|
+
n(d)
|
|
179
|
+
)}`;
|
|
180
|
+
}
|
|
181
|
+
const s = (r) => {
|
|
182
|
+
const _ = /(\s+)|((["'])(?:\\.|(?!\3).)*\3)|(\$[A-Za-z_][A-Za-z0-9_]*)|(@[A-Za-z0-9._/-]+|[A-Za-z0-9._-]+\/[A-Za-z0-9._/@-]+)|(-{1,2}[A-Za-z][\w-]*)(?:=(\S+))?|([^\s]+)/g;
|
|
183
|
+
let u = 0, f = "";
|
|
184
|
+
for (const h of r.matchAll(_)) {
|
|
185
|
+
const d = h[0] ?? "", A = h.index ?? 0;
|
|
186
|
+
f += n(r.slice(u, A)), h[1] ? f += n(d) : h[2] ? f += l(
|
|
187
|
+
"vcb__token_string",
|
|
188
|
+
n(d)
|
|
189
|
+
) : h[4] ? f += l(
|
|
190
|
+
"vcb__token_variable",
|
|
191
|
+
n(d)
|
|
192
|
+
) : h[5] ? f += l(
|
|
193
|
+
"vcb__token_string",
|
|
194
|
+
n(d)
|
|
195
|
+
) : h[6] ? (f += l(
|
|
196
|
+
"vcb__token_directive",
|
|
197
|
+
n(h[6])
|
|
198
|
+
), h[7] && (f += `${n("=")}${l(
|
|
199
|
+
h[7].startsWith("@") || h[7].includes("/") ? "vcb__token_string" : "vcb__token_variable",
|
|
200
|
+
n(h[7])
|
|
201
|
+
)}`)) : h[8] ? f += l(
|
|
202
|
+
"vcb__token_variable",
|
|
203
|
+
n(d)
|
|
204
|
+
) : f += n(d), u = A + d.length;
|
|
205
|
+
}
|
|
206
|
+
return f += n(r.slice(u)), f;
|
|
207
|
+
}, e = t.match(
|
|
208
|
+
/^(\s*)(npm|pnpm|yarn|bun)(\s+)(i|install|add|remove|rm|uninstall|create|dlx|exec|x)(\s+)(.+)$/
|
|
209
|
+
);
|
|
210
|
+
if (e) {
|
|
211
|
+
const [
|
|
212
|
+
,
|
|
213
|
+
r,
|
|
214
|
+
_,
|
|
215
|
+
u,
|
|
216
|
+
f,
|
|
217
|
+
h,
|
|
218
|
+
d
|
|
219
|
+
] = e;
|
|
220
|
+
return `${n(r)}${l(
|
|
221
|
+
"vcb__token_keyword",
|
|
222
|
+
n(_)
|
|
223
|
+
)}${n(u)}${l(
|
|
224
|
+
"vcb__token_function",
|
|
225
|
+
n(f)
|
|
226
|
+
)}${n(h)}${s(d)}`;
|
|
227
|
+
}
|
|
228
|
+
const i = /(#[^\n]*$)|((["'])(?:\\.|(?!\3).)*\3)|(\$[A-Za-z_][A-Za-z0-9_]*)|(@[A-Za-z0-9._/-]+)|(^\s*[A-Za-z][\w-]*\b)|(\s-[A-Za-z-]+\b|\s--[A-Za-z-]+\b)/g;
|
|
229
|
+
let c = 0, a = "";
|
|
230
|
+
for (const r of t.matchAll(i)) {
|
|
231
|
+
const _ = r[0] ?? "", u = r.index ?? 0;
|
|
232
|
+
if (a += n(t.slice(c, u)), r[1])
|
|
233
|
+
a += l(
|
|
234
|
+
"vcb__token_comment",
|
|
235
|
+
n(_)
|
|
236
|
+
);
|
|
237
|
+
else if (r[2])
|
|
238
|
+
a += l(
|
|
239
|
+
"vcb__token_string",
|
|
240
|
+
n(_)
|
|
241
|
+
);
|
|
242
|
+
else if (r[4])
|
|
243
|
+
a += l(
|
|
244
|
+
"vcb__token_variable",
|
|
245
|
+
n(_)
|
|
246
|
+
);
|
|
247
|
+
else if (r[5])
|
|
248
|
+
a += l(
|
|
249
|
+
"vcb__token_string",
|
|
250
|
+
n(_)
|
|
251
|
+
);
|
|
252
|
+
else if (r[6])
|
|
253
|
+
a += l(
|
|
254
|
+
"vcb__token_keyword",
|
|
255
|
+
n(_.trimStart())
|
|
256
|
+
);
|
|
257
|
+
else if (r[7]) {
|
|
258
|
+
const f = _.match(/^\s*/)?.[0] ?? "";
|
|
259
|
+
a += `${n(f)}${l(
|
|
260
|
+
"vcb__token_directive",
|
|
261
|
+
n(_.trimStart())
|
|
262
|
+
)}`;
|
|
263
|
+
} else
|
|
264
|
+
a += n(_);
|
|
265
|
+
c = u + _.length;
|
|
266
|
+
}
|
|
267
|
+
return a += n(t.slice(c)), a;
|
|
268
|
+
}, j = (t) => {
|
|
269
|
+
const o = new RegExp(
|
|
270
|
+
`(\\/\\*.*?\\*\\/)|((["'])(?:\\\\.|(?!\\3).)*\\3)|(#[0-9A-Fa-f]{3,8})|(@[A-Za-z-]+)|([A-Za-z_-][\\w-]*)(?=\\s*\\()|${et}|\\b[A-Za-z_-][\\w-]*\\b`,
|
|
271
|
+
"g"
|
|
272
|
+
);
|
|
273
|
+
let s = 0, e = "";
|
|
274
|
+
for (const i of t.matchAll(o)) {
|
|
275
|
+
const c = i[0] ?? "", a = i.index ?? 0;
|
|
276
|
+
e += n(t.slice(s, a)), i[1] ? e += l(
|
|
277
|
+
"vcb__token_comment",
|
|
278
|
+
n(c)
|
|
279
|
+
) : i[2] ? e += l(
|
|
280
|
+
"vcb__token_string",
|
|
281
|
+
n(c)
|
|
282
|
+
) : /^#[0-9A-Fa-f]{3,8}$/.test(c) ? e += l(
|
|
283
|
+
"vcb__token_number",
|
|
284
|
+
n(c)
|
|
285
|
+
) : c.startsWith("@") ? e += l(
|
|
286
|
+
"vcb__token_keyword",
|
|
287
|
+
n(c)
|
|
288
|
+
) : J(t, a + c.length) === "(" ? e += l(
|
|
289
|
+
"vcb__token_function",
|
|
290
|
+
n(c)
|
|
291
|
+
) : /^-?\d/.test(c) ? e += l(
|
|
292
|
+
"vcb__token_number",
|
|
293
|
+
n(c)
|
|
294
|
+
) : e += l(
|
|
295
|
+
"vcb__token_variable",
|
|
296
|
+
n(c)
|
|
297
|
+
), s = a + c.length;
|
|
298
|
+
}
|
|
299
|
+
return e += n(t.slice(s)), e;
|
|
300
|
+
}, _t = (t) => {
|
|
301
|
+
const o = t.match(/^(\s*)(\/\*.*\*\/)(\s*)$/);
|
|
302
|
+
if (o)
|
|
303
|
+
return `${n(o[1])}${l(
|
|
304
|
+
"vcb__token_comment",
|
|
305
|
+
n(o[2])
|
|
306
|
+
)}${n(o[3])}`;
|
|
307
|
+
const s = t.match(/^(\s*)([^{}][^{}]*?)(\s*)(\{|\})\s*$/);
|
|
308
|
+
if (s) {
|
|
309
|
+
const [, i, c, a, r] = s, _ = c.trim(), u = _ === ":root" || _.startsWith(".") || _.startsWith("#") || /^[A-Za-z_-][\w-]*$/.test(_) ? "vcb__token_selector" : "vcb__token_variable";
|
|
310
|
+
return `${n(i)}${l(u, n(_))}${n(
|
|
311
|
+
a
|
|
312
|
+
)}${n(r)}`;
|
|
313
|
+
}
|
|
314
|
+
const e = t.match(
|
|
315
|
+
/^(\s*)(--?[A-Za-z_][\w-]*|[A-Za-z_][\w-]*)(\s*:\s*)(.*)$/
|
|
316
|
+
);
|
|
317
|
+
if (e) {
|
|
318
|
+
const [, i, c, a, r] = e;
|
|
319
|
+
return `${n(i)}${l(
|
|
320
|
+
"vcb__token_property",
|
|
321
|
+
n(c)
|
|
322
|
+
)}${n(a)}${j(r)}`;
|
|
323
|
+
}
|
|
324
|
+
return j(t);
|
|
325
|
+
}, dt = (t, o, s = !0) => {
|
|
326
|
+
if (!s)
|
|
327
|
+
return B(o);
|
|
328
|
+
const e = t.toLowerCase();
|
|
329
|
+
return e.includes("json") ? ot(o) : e.includes("vue") || e.includes("html") ? k(o) : e.includes("js") || e.includes("ts") || e.includes("javascript") || e.includes("typescript") ? H(o) : e.includes("bash") || e.includes("shell") || e === "sh" ? ut(o) : e.includes("css") || e.includes("scss") || e.includes("sass") ? _t(o) : B(o);
|
|
330
|
+
}, ht = (t, o) => {
|
|
331
|
+
const s = (t || "").replace(/\r\n/g, `
|
|
332
|
+
`).split(`
|
|
333
|
+
`);
|
|
334
|
+
let e = !1, i = null, c = null;
|
|
335
|
+
return s.map((a) => {
|
|
336
|
+
const r = a;
|
|
337
|
+
if (!o)
|
|
338
|
+
return B(r);
|
|
339
|
+
const _ = n(r), u = _.trim();
|
|
340
|
+
if (!u)
|
|
341
|
+
return _;
|
|
342
|
+
if (/^<script\b/i.test(u)) {
|
|
343
|
+
i = "script";
|
|
344
|
+
const d = u.includes(">");
|
|
345
|
+
return e = !d, d ? k(r) : z(r);
|
|
346
|
+
}
|
|
347
|
+
if (/^<template\b/i.test(u)) {
|
|
348
|
+
i = "template";
|
|
349
|
+
const d = u.includes(">");
|
|
350
|
+
return e = !d, d ? k(r) : z(r);
|
|
351
|
+
}
|
|
352
|
+
if (/^<style\b/i.test(u)) {
|
|
353
|
+
i = "style";
|
|
354
|
+
const d = u.includes(">");
|
|
355
|
+
return e = !d, d ? k(r) : z(r);
|
|
356
|
+
}
|
|
357
|
+
if (/^<\/script>/i.test(u) || /^<\/template>/i.test(u) || /^<\/style>/i.test(u))
|
|
358
|
+
return i = null, e = !1, k(r);
|
|
359
|
+
const f = u.startsWith("<") && !u.startsWith("</"), h = u.includes(">");
|
|
360
|
+
if (f) {
|
|
361
|
+
const d = h ? k(r) : z(r);
|
|
362
|
+
return e = !h, d;
|
|
363
|
+
}
|
|
364
|
+
if (e) {
|
|
365
|
+
if (u === ">" || u === "/>")
|
|
366
|
+
return e = !1, c = null, _;
|
|
367
|
+
if (c) {
|
|
368
|
+
const p = c, g = r.indexOf(c.quote);
|
|
369
|
+
if (g === -1)
|
|
370
|
+
return L(
|
|
371
|
+
r,
|
|
372
|
+
p.quote,
|
|
373
|
+
p.directive,
|
|
374
|
+
!1,
|
|
375
|
+
!1
|
|
376
|
+
);
|
|
377
|
+
const Z = r.slice(0, g), v = r.slice(g + 1), $ = n(v);
|
|
378
|
+
return c = null, v.includes(">") && (e = !1), `${L(
|
|
379
|
+
Z,
|
|
380
|
+
p.quote,
|
|
381
|
+
p.directive,
|
|
382
|
+
!1,
|
|
383
|
+
!0
|
|
384
|
+
)}${$}`;
|
|
385
|
+
}
|
|
386
|
+
const d = r.match(
|
|
387
|
+
/^(\s+)([:@#]?[\w-]+(?::[\w-]+)?)(\s*=\s*)(["'])([\s\S]*)$/
|
|
388
|
+
);
|
|
389
|
+
if (d) {
|
|
390
|
+
const [, p, g, Z, v, $] = d, S = E(g), W = $.indexOf(v), N = `${p}${l(
|
|
391
|
+
S ? "vcb__token_directive" : "vcb__token_attribute",
|
|
392
|
+
g
|
|
393
|
+
)}${n(Z)}`;
|
|
394
|
+
if (W === -1)
|
|
395
|
+
return c = {
|
|
396
|
+
quote: v,
|
|
397
|
+
directive: S
|
|
398
|
+
}, `${N}${L(
|
|
399
|
+
$,
|
|
400
|
+
v,
|
|
401
|
+
S,
|
|
402
|
+
!0,
|
|
403
|
+
!1
|
|
404
|
+
)}`;
|
|
405
|
+
const Q = $.slice(0, W), P = $.slice(W + 1);
|
|
406
|
+
return P.includes(">") && (e = !1), `${N}${L(
|
|
407
|
+
Q,
|
|
408
|
+
v,
|
|
409
|
+
S,
|
|
410
|
+
!0,
|
|
411
|
+
!0
|
|
412
|
+
)}${n(P)}`;
|
|
413
|
+
}
|
|
414
|
+
const A = T(_);
|
|
415
|
+
return h && (e = !1), A;
|
|
416
|
+
}
|
|
417
|
+
return i === "script" ? H(r) : k(r);
|
|
418
|
+
}).join(`
|
|
419
|
+
`);
|
|
420
|
+
}, ft = (t, o, s = !0) => {
|
|
421
|
+
const e = t.toLowerCase();
|
|
422
|
+
return e.includes("vue") || e.includes("html") ? ht(o, s) : (o || "").replace(/\r\n/g, `
|
|
423
|
+
`).split(`
|
|
424
|
+
`).map((i) => dt(t, i, s)).join(`
|
|
425
|
+
`);
|
|
426
|
+
}, gt = ["data-theme", "aria-label"], mt = {
|
|
427
|
+
key: 0,
|
|
428
|
+
class: "vcb__header"
|
|
429
|
+
}, bt = {
|
|
430
|
+
key: 0,
|
|
431
|
+
class: "vcb__meta"
|
|
432
|
+
}, pt = {
|
|
433
|
+
key: 0,
|
|
434
|
+
class: "vcb__filename"
|
|
435
|
+
}, vt = { class: "vcb__language" }, kt = { class: "vcb__actions" }, $t = ["disabled"], At = {
|
|
436
|
+
key: 0,
|
|
437
|
+
class: "vcb__line-number"
|
|
438
|
+
}, yt = ["innerHTML"], D = /* @__PURE__ */ R({
|
|
439
|
+
name: "VcbCodeBlock",
|
|
440
|
+
__name: "CodeBlock",
|
|
441
|
+
props: {
|
|
442
|
+
code: { default: "" },
|
|
443
|
+
language: { default: "plaintext" },
|
|
444
|
+
filename: { default: "" },
|
|
445
|
+
showHeader: { type: Boolean, default: !0 },
|
|
446
|
+
showLineNumbers: { type: Boolean, default: !1 },
|
|
447
|
+
copyable: { type: Boolean, default: !0 },
|
|
448
|
+
copyLabel: { default: "Copy" },
|
|
449
|
+
copiedLabel: { default: "Copied" },
|
|
450
|
+
copiedDuration: { default: 1200 },
|
|
451
|
+
languageLabel: { default: "Language" },
|
|
452
|
+
disabled: { type: Boolean, default: !1 },
|
|
453
|
+
wrap: { type: Boolean, default: !1 },
|
|
454
|
+
highlight: { type: Boolean, default: !0 },
|
|
455
|
+
maxHeight: { default: "" },
|
|
456
|
+
ariaLabel: { default: "Code block" },
|
|
457
|
+
theme: { default: "inherit" }
|
|
458
|
+
},
|
|
459
|
+
emits: ["copy"],
|
|
460
|
+
setup(t, { emit: o }) {
|
|
461
|
+
const s = t, e = o, i = F(!1);
|
|
462
|
+
let c = null;
|
|
463
|
+
const a = y(() => s.code.replace(/\r\n/g, `
|
|
464
|
+
`)), r = y(() => a.value ? a.value.split(`
|
|
465
|
+
`) : [""]), _ = y(
|
|
466
|
+
() => ft(
|
|
467
|
+
s.language,
|
|
468
|
+
a.value,
|
|
469
|
+
s.highlight
|
|
470
|
+
).split(`
|
|
471
|
+
`)
|
|
472
|
+
), u = y(
|
|
473
|
+
() => s.theme === "inherit" ? void 0 : s.theme
|
|
474
|
+
), f = y(() => {
|
|
475
|
+
if (s.maxHeight)
|
|
476
|
+
return {
|
|
477
|
+
maxHeight: s.maxHeight
|
|
478
|
+
};
|
|
479
|
+
}), h = async () => {
|
|
480
|
+
if (!s.disabled)
|
|
481
|
+
try {
|
|
482
|
+
typeof navigator < "u" && navigator.clipboard?.writeText && await navigator.clipboard.writeText(a.value);
|
|
483
|
+
} finally {
|
|
484
|
+
e("copy", { text: a.value }), i.value = !0, c && clearTimeout(c), c = setTimeout(() => {
|
|
485
|
+
i.value = !1, c = null;
|
|
486
|
+
}, s.copiedDuration);
|
|
487
|
+
}
|
|
488
|
+
};
|
|
489
|
+
return U(() => {
|
|
490
|
+
c && (clearTimeout(c), c = null);
|
|
491
|
+
}), (d, A) => (m(), b("section", {
|
|
492
|
+
class: q(["vcb", { vcb_disabled: t.disabled }]),
|
|
493
|
+
"data-theme": u.value,
|
|
494
|
+
"aria-label": t.ariaLabel
|
|
495
|
+
}, [
|
|
496
|
+
t.showHeader || d.$slots.actions ? (m(), b("header", mt, [
|
|
497
|
+
t.showHeader ? (m(), b("div", bt, [
|
|
498
|
+
t.filename ? (m(), b("span", pt, w(t.filename), 1)) : x("", !0),
|
|
499
|
+
C("span", vt, w(t.languageLabel) + ": " + w(t.language), 1)
|
|
500
|
+
])) : x("", !0),
|
|
501
|
+
C("div", kt, [
|
|
502
|
+
G(d.$slots, "actions"),
|
|
503
|
+
t.copyable ? (m(), b("button", {
|
|
504
|
+
key: 0,
|
|
505
|
+
type: "button",
|
|
506
|
+
class: "vcb__copy",
|
|
507
|
+
disabled: t.disabled,
|
|
508
|
+
onClick: h
|
|
509
|
+
}, w(i.value ? t.copiedLabel : t.copyLabel), 9, $t)) : x("", !0)
|
|
510
|
+
])
|
|
511
|
+
])) : x("", !0),
|
|
512
|
+
C("pre", {
|
|
513
|
+
class: q(["vcb__pre", { vcb__pre_wrap: t.wrap }]),
|
|
514
|
+
style: K(f.value)
|
|
515
|
+
}, [
|
|
516
|
+
C("code", null, [
|
|
517
|
+
(m(!0), b(X, null, Y(r.value, (p, g) => (m(), b("span", {
|
|
518
|
+
key: g,
|
|
519
|
+
class: "vcb__line"
|
|
520
|
+
}, [
|
|
521
|
+
t.showLineNumbers ? (m(), b("span", At, w(g + 1), 1)) : x("", !0),
|
|
522
|
+
C("span", {
|
|
523
|
+
class: "vcb__line-content",
|
|
524
|
+
innerHTML: _.value[g] ?? ""
|
|
525
|
+
}, null, 8, yt)
|
|
526
|
+
]))), 128))
|
|
527
|
+
])
|
|
528
|
+
], 6)
|
|
529
|
+
], 10, gt));
|
|
530
|
+
}
|
|
531
|
+
}), xt = [
|
|
532
|
+
"plaintext",
|
|
533
|
+
"text",
|
|
534
|
+
"txt",
|
|
535
|
+
"js",
|
|
536
|
+
"javascript",
|
|
537
|
+
"ts",
|
|
538
|
+
"typescript",
|
|
539
|
+
"vue",
|
|
540
|
+
"html",
|
|
541
|
+
"json",
|
|
542
|
+
"bash",
|
|
543
|
+
"shell",
|
|
544
|
+
"sh",
|
|
545
|
+
"css",
|
|
546
|
+
"scss",
|
|
547
|
+
"sass"
|
|
548
|
+
], Ct = {
|
|
549
|
+
install(t) {
|
|
550
|
+
t.component("CodeBlock", D), t.component("VueCodeBlock", D);
|
|
551
|
+
}
|
|
552
|
+
};
|
|
553
|
+
export {
|
|
554
|
+
D as CodeBlock,
|
|
555
|
+
xt as SUPPORTED_CODE_BLOCK_LANGUAGES,
|
|
556
|
+
Ct as default,
|
|
557
|
+
n as escapeCodeHtml,
|
|
558
|
+
ft as highlightCodeBlock,
|
|
559
|
+
dt as highlightCodeLine
|
|
560
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
(function(f,s){typeof exports=="object"&&typeof module<"u"?s(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],s):(f=typeof globalThis<"u"?globalThis:f||self,s(f.VueCodeBlock={},f.Vue))})(this,(function(f,s){"use strict";var Z=document.createElement("style");Z.textContent=`.vcb{display:grid;gap:var(--vcb-gap, 0);border:1px solid var(--vcb-border-color, #cbd5e1);border-radius:var(--vcb-border-radius, .625rem);background:var(--vcb-background-color, #f8fbff);color:var(--vcb-text-color, #0f172a);font-family:var(--vcb-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-size:var(--vcb-font-size, .8125rem);line-height:var(--vcb-line-height, 1.5)}.vcb__header{display:flex;align-items:center;justify-content:space-between;gap:var(--vcb-header-gap, .75rem);padding:var(--vcb-header-padding, .55rem .75rem);border-bottom:1px solid var(--vcb-header-border-color, rgba(148, 163, 184, .28))}.vcb__meta{display:inline-flex;align-items:center;gap:var(--vcb-meta-gap, .55rem);color:var(--vcb-meta-color, #475569);font-size:var(--vcb-meta-font-size, .75rem)}.vcb__filename{color:var(--vcb-filename-color, #0f172a);font-weight:var(--vcb-filename-font-weight, 600)}.vcb__actions{display:inline-flex;align-items:center;gap:var(--vcb-actions-gap, .45rem)}.vcb__copy{border:1px solid var(--vcb-action-border-color, rgba(148, 163, 184, .38));border-radius:var(--vcb-action-border-radius, .375rem);background:var(--vcb-action-background-color, #ffffff);color:var(--vcb-action-text-color, #0f172a);padding:var(--vcb-action-padding, .2rem .55rem);font-size:var(--vcb-action-font-size, .75rem)}.vcb__pre{margin:0;padding:var(--vcb-padding, .75rem .9rem);overflow:auto;white-space:pre}.vcb__pre_wrap{white-space:pre-wrap;word-break:break-word}.vcb__line{display:flex;align-items:baseline;gap:var(--vcb-line-gap, .7rem)}.vcb__line-number{text-align:right;color:var(--vcb-line-number-color, #64748b);min-width:var(--vcb-line-number-min-width, 2.1rem);-webkit-user-select:none;user-select:none}.vcb__line-content{white-space:inherit}.vcb__token_keyword{color:var(--vcb-token-keyword-color, #8b2fc9)}.vcb__token_string{color:var(--vcb-token-string-color, #0f7b45)}.vcb__token_number{color:var(--vcb-token-number-color, #c2410c)}.vcb__token_comment{color:var(--vcb-token-comment-color, #64748b)}.vcb__token_variable{color:var(--vcb-token-variable-color, #0f4c81)}.vcb__token_identifier{color:var(--vcb-token-identifier-color, #0369a1)}.vcb__token_function{color:var(--vcb-token-function-color, #1d4ed8)}.vcb__token_property{color:var(--vcb-token-property-color, #6d28d9)}.vcb__token_operator{color:var(--vcb-token-operator-color, #be185d)}.vcb__token_tag{color:var(--vcb-token-tag-color, #0f4c81)}.vcb__token_selector{color:var(--vcb-token-selector-color, #0f4c81)}.vcb__token_component{color:var(--vcb-token-component-color, #0369a1)}.vcb__token_attribute{color:var(--vcb-token-attribute-color, #7c3aed)}.vcb__token_directive{color:var(--vcb-token-directive-color, #a21caf)}.vcb[data-theme=dark],:root[data-theme=dark] .vcb:not([data-theme=light]),[data-theme=dark] .vcb:not([data-theme=light]){--vcb-background-color: var( --vcb-dark-background-color, #0a1425 );--vcb-text-color: var(--vcb-dark-text-color, #e2e8f0);--vcb-border-color: var( --vcb-dark-border-color, rgba(148, 163, 184, .35) );--vcb-header-border-color: var( --vcb-dark-header-border-color, rgba(148, 163, 184, .35) );--vcb-meta-color: var(--vcb-dark-meta-color, #93a4bf);--vcb-filename-color: var( --vcb-dark-filename-color, #e2e8f0 );--vcb-action-border-color: var( --vcb-dark-action-border-color, rgba(148, 163, 184, .45) );--vcb-action-background-color: var( --vcb-dark-action-background-color, rgba(15, 23, 42, .7) );--vcb-action-text-color: var( --vcb-dark-action-text-color, #e2e8f0 );--vcb-line-number-color: var( --vcb-dark-line-number-color, #64748b );--vcb-token-keyword-color: var( --vcb-dark-token-keyword-color, #c084fc );--vcb-token-string-color: var( --vcb-dark-token-string-color, #86efac );--vcb-token-number-color: var( --vcb-dark-token-number-color, #fca5a5 );--vcb-token-comment-color: var( --vcb-dark-token-comment-color, #94a3b8 );--vcb-token-variable-color: var( --vcb-dark-token-variable-color, #bfdbfe );--vcb-token-tag-color: var( --vcb-dark-token-tag-color, #93c5fd );--vcb-token-selector-color: var( --vcb-dark-token-selector-color, #93c5fd );--vcb-token-component-color: var( --vcb-dark-token-component-color, #67e8f9 );--vcb-token-attribute-color: var( --vcb-dark-token-attribute-color, #c4b5fd );--vcb-token-directive-color: var( --vcb-dark-token-directive-color, #f0abfc );--vcb-token-identifier-color: var( --vcb-dark-token-identifier-color, #7dd3fc );--vcb-token-function-color: var( --vcb-dark-token-function-color, #93c5fd );--vcb-token-property-color: var( --vcb-dark-token-property-color, #a5b4fc );--vcb-token-operator-color: var( --vcb-dark-token-operator-color, #f0abfc )}.vcb_disabled{opacity:var(--vcb-disabled-opacity, .6)}
|
|
2
|
+
/*$vite$:1*/`,document.head.appendChild(Z);const o=e=>e.replaceAll("&","&").replaceAll("<","<").replaceAll(">",">"),T=e=>e.replaceAll(""",'"').replaceAll("'","'").replaceAll("<","<").replaceAll(">",">").replaceAll("&","&"),S=e=>o(e),i=(e,r)=>`<span class="vcb__token ${e}">${r}</span>`,I="\\b\\d(?:[\\d_]*\\d)?(?:\\.\\d(?:[\\d_]*\\d)?)?\\b",R="\\b-?\\d(?:[\\d_]*\\d)?(?:\\.\\d(?:[\\d_]*\\d)?)?(?:px|rem|em|%|vh|vw|fr|s|ms|deg)?\\b",B=e=>e.startsWith(":")||e.startsWith("@")||e.startsWith("#")||e.startsWith("v-"),W=e=>/^[A-Z]/.test(e),U=e=>{let r=0,n=i("vcb__token_string",o("`"));for(;r<e.length-1;){const t=e.indexOf("${",r),a=t===-1?e.length-1:t,c=e.slice(r,a);if(c&&(n+=i("vcb__token_string",o(c))),t===-1)break;n+=o("${");let d=t+2,l=1;for(;d<e.length&&l>0;){const b=e[d];b==="{"?l+=1:b==="}"&&(l-=1),d+=1}const _=e.slice(t+2,d-1);n+=w(_),n+=o("}"),r=d}return n+=i("vcb__token_string",o("`")),n},w=e=>z(e),F=e=>{if(e.length<2)return i("vcb__token_string",e);const r=e[0],n=T(e.slice(1,-1)),t=w(n),a=r==='"'?""":"'";return`${a}${t}${a}`},A=(e,r,n,t,a)=>{const c=n?w(T(e)):i("vcb__token_string",o(e)),d=r==='"'?""":"'";return`${t?d:""}${c}${a?d:""}`},V=e=>e.replaceAll(/{{\s*([\s\S]*?)\s*}}/g,(r,n)=>{const t=w(n);return`${o("{{ ")}${t}${o(" }}")}`}),E=e=>e.replaceAll(/(\s+)([:@#]?[\w-]+(?::[\w-]+)?)(\s*=\s*)?("[^"]*"|'[^']*')?/g,(r,n,t,a="",c="")=>`${o(n)}${i(B(t)?"vcb__token_directive":"vcb__token_attribute",o(t))}${o(a)}${c?B(t)?F(c):i("vcb__token_string",o(c)):""}`),x=e=>{const r=e.match(/^(\s*)<([/\w-]+)([\s\S]*)$/);if(!r)return o(e);const[,n,t,a]=r,c=t.startsWith("/"),d=c?t.slice(1):t,l=W(d)?"vcb__token_component":"vcb__token_tag";return`${o(n)}${o(c?"</":"<")}${i(l,o(d))}${E(String(a))}`},G=e=>{if(e.startsWith("<!--")&&e.endsWith("-->"))return i("vcb__token_comment",o(e));const r=e.startsWith("</"),n=e.endsWith("/>"),a=e.slice(r?2:1,e.length-(n?2:1)).match(/^([\w-]+)([\s\S]*)$/);if(!a)return o(e);const[,c,d]=a,l=W(c)?"vcb__token_component":"vcb__token_tag";return`${o(r?"</":"<")}${i(l,o(c))}${E(d)}${o(n?"/>":">")}`},J=e=>o(e).replaceAll(/"(?:[^"\\]|\\.)*"(?=\s*:)?/g,n=>i("vcb__token_string",n)).replaceAll(/\b(true|false|null)\b/g,n=>i("vcb__token_keyword",n)).replaceAll(/\b-?\d(?:[\d_]*\d)?(?:\.\d(?:[\d_]*\d)?)?(?:[eE][+-]?\d(?:[\d_]*\d)?)?\b/g,n=>i("vcb__token_number",n)),Q=(e,r)=>{for(let n=r-1;n>=0;n-=1){const t=e[n];if(!/\s/.test(t))return t}return""},O=(e,r)=>{for(let n=r;n<e.length;n+=1){const t=e[n];if(!/\s/.test(t))return t}return""},K=(e,r)=>{let n=r;for(;n>0&&/\s/.test(e[n-1]);)n-=1;return e.slice(0,n).match(/([A-Za-z_$][\w$]*)\s*$/)?.[1]??""},X=(e,r,n)=>{const t=Q(e,n),a=O(e,n+r.length),c=K(e,n),d=e.slice(0,n);return t==="."||/\?\.\s*$/.test(d)||a===":"&&["{",",",""].includes(t)?"vcb__token_property":a==="("?"vcb__token_function":/^[A-Z]/.test(r)||["import","from","new","class","extends"].includes(c)?"vcb__token_identifier":"vcb__token_variable"},z=e=>{const r=new RegExp(`(//.*$)|((["'\`])(?:\\\\.|(?!\\3).)*\\3)|\\b(const|let|var|function|return|if|else|for|while|class|new|import|export|from|await|async|try|catch|throw|true|false|null|undefined)\\b|(=>|\\?\\?|\\?|:|\\.|[{}()[\\],])|${I}|\\b[A-Za-z_$][\\w$]*\\b`,"g");let n=0,t="";for(const a of e.matchAll(r)){const c=a[0]??"",d=a.index??0;t+=o(e.slice(n,d)),a[1]?t+=i("vcb__token_comment",o(c)):a[2]?t+=c.startsWith("`")&&c.includes("${")?U(c):i("vcb__token_string",o(c)):a[4]?t+=i("vcb__token_keyword",o(c)):a[5]?t+=i("vcb__token_operator",o(c)):/^\d/.test(c)?t+=i("vcb__token_number",o(c)):t+=i(X(e,c,d),o(c)),n=d+c.length}return t+=o(e.slice(n)),t},Y=(e,r)=>{let n=null;for(let t=r+1;t<e.length;t+=1){const a=e[t];if(n){a===n&&e[t-1]!=="\\"&&(n=null);continue}if(a==='"'||a==="'"){n=a;continue}if(a===">")return t}return-1},g=e=>{if(!e.trim())return o(e);let r=0,n="";for(;r<e.length;){const t=e.indexOf("<",r);if(t===-1){n+=V(o(e.slice(r)));break}n+=V(o(e.slice(r,t)));const a=Y(e,t);if(a===-1){n+=o(e.slice(t));break}n+=G(e.slice(t,a+1)),r=a+1}return n},ee=e=>{const r=e.match(/^(\s*)(npm)(\s+)(run)(\s+)([^\s].*)$/);if(r){const[,l,_,b,m,u,v]=r;return`${o(l)}${i("vcb__token_keyword",o(_))}${o(b)}${i("vcb__token_function",o(m))}${o(u)}${i("vcb__token_variable",o(v))}`}const n=l=>{const _=/(\s+)|((["'])(?:\\.|(?!\3).)*\3)|(\$[A-Za-z_][A-Za-z0-9_]*)|(@[A-Za-z0-9._/-]+|[A-Za-z0-9._-]+\/[A-Za-z0-9._/@-]+)|(-{1,2}[A-Za-z][\w-]*)(?:=(\S+))?|([^\s]+)/g;let b=0,m="";for(const u of l.matchAll(_)){const v=u[0]??"",y=u.index??0;m+=o(l.slice(b,y)),u[1]?m+=o(v):u[2]?m+=i("vcb__token_string",o(v)):u[4]?m+=i("vcb__token_variable",o(v)):u[5]?m+=i("vcb__token_string",o(v)):u[6]?(m+=i("vcb__token_directive",o(u[6])),u[7]&&(m+=`${o("=")}${i(u[7].startsWith("@")||u[7].includes("/")?"vcb__token_string":"vcb__token_variable",o(u[7]))}`)):u[8]?m+=i("vcb__token_variable",o(v)):m+=o(v),b=y+v.length}return m+=o(l.slice(b)),m},t=e.match(/^(\s*)(npm|pnpm|yarn|bun)(\s+)(i|install|add|remove|rm|uninstall|create|dlx|exec|x)(\s+)(.+)$/);if(t){const[,l,_,b,m,u,v]=t;return`${o(l)}${i("vcb__token_keyword",o(_))}${o(b)}${i("vcb__token_function",o(m))}${o(u)}${n(v)}`}const a=/(#[^\n]*$)|((["'])(?:\\.|(?!\3).)*\3)|(\$[A-Za-z_][A-Za-z0-9_]*)|(@[A-Za-z0-9._/-]+)|(^\s*[A-Za-z][\w-]*\b)|(\s-[A-Za-z-]+\b|\s--[A-Za-z-]+\b)/g;let c=0,d="";for(const l of e.matchAll(a)){const _=l[0]??"",b=l.index??0;if(d+=o(e.slice(c,b)),l[1])d+=i("vcb__token_comment",o(_));else if(l[2])d+=i("vcb__token_string",o(_));else if(l[4])d+=i("vcb__token_variable",o(_));else if(l[5])d+=i("vcb__token_string",o(_));else if(l[6])d+=i("vcb__token_keyword",o(_.trimStart()));else if(l[7]){const m=_.match(/^\s*/)?.[0]??"";d+=`${o(m)}${i("vcb__token_directive",o(_.trimStart()))}`}else d+=o(_);c=b+_.length}return d+=o(e.slice(c)),d},P=e=>{const r=new RegExp(`(\\/\\*.*?\\*\\/)|((["'])(?:\\\\.|(?!\\3).)*\\3)|(#[0-9A-Fa-f]{3,8})|(@[A-Za-z-]+)|([A-Za-z_-][\\w-]*)(?=\\s*\\()|${R}|\\b[A-Za-z_-][\\w-]*\\b`,"g");let n=0,t="";for(const a of e.matchAll(r)){const c=a[0]??"",d=a.index??0;t+=o(e.slice(n,d)),a[1]?t+=i("vcb__token_comment",o(c)):a[2]?t+=i("vcb__token_string",o(c)):/^#[0-9A-Fa-f]{3,8}$/.test(c)?t+=i("vcb__token_number",o(c)):c.startsWith("@")?t+=i("vcb__token_keyword",o(c)):O(e,d+c.length)==="("?t+=i("vcb__token_function",o(c)):/^-?\d/.test(c)?t+=i("vcb__token_number",o(c)):t+=i("vcb__token_variable",o(c)),n=d+c.length}return t+=o(e.slice(n)),t},te=e=>{const r=e.match(/^(\s*)(\/\*.*\*\/)(\s*)$/);if(r)return`${o(r[1])}${i("vcb__token_comment",o(r[2]))}${o(r[3])}`;const n=e.match(/^(\s*)([^{}][^{}]*?)(\s*)(\{|\})\s*$/);if(n){const[,a,c,d,l]=n,_=c.trim(),b=_===":root"||_.startsWith(".")||_.startsWith("#")||/^[A-Za-z_-][\w-]*$/.test(_)?"vcb__token_selector":"vcb__token_variable";return`${o(a)}${i(b,o(_))}${o(d)}${o(l)}`}const t=e.match(/^(\s*)(--?[A-Za-z_][\w-]*|[A-Za-z_][\w-]*)(\s*:\s*)(.*)$/);if(t){const[,a,c,d,l]=t;return`${o(a)}${i("vcb__token_property",o(c))}${o(d)}${P(l)}`}return P(e)},D=(e,r,n=!0)=>{if(!n)return S(r);const t=e.toLowerCase();return t.includes("json")?J(r):t.includes("vue")||t.includes("html")?g(r):t.includes("js")||t.includes("ts")||t.includes("javascript")||t.includes("typescript")?z(r):t.includes("bash")||t.includes("shell")||t==="sh"?ee(r):t.includes("css")||t.includes("scss")||t.includes("sass")?te(r):S(r)},oe=(e,r)=>{const n=(e||"").replace(/\r\n/g,`
|
|
3
|
+
`).split(`
|
|
4
|
+
`);let t=!1,a=null,c=null;return n.map(d=>{const l=d;if(!r)return S(l);const _=o(l),b=_.trim();if(!b)return _;if(/^<script\b/i.test(b)){a="script";const v=b.includes(">");return t=!v,v?g(l):x(l)}if(/^<template\b/i.test(b)){a="template";const v=b.includes(">");return t=!v,v?g(l):x(l)}if(/^<style\b/i.test(b)){a="style";const v=b.includes(">");return t=!v,v?g(l):x(l)}if(/^<\/script>/i.test(b)||/^<\/template>/i.test(b)||/^<\/style>/i.test(b))return a=null,t=!1,g(l);const m=b.startsWith("<")&&!b.startsWith("</"),u=b.includes(">");if(m){const v=u?g(l):x(l);return t=!u,v}if(t){if(b===">"||b==="/>")return t=!1,c=null,_;if(c){const k=c,h=l.indexOf(c.quote);if(h===-1)return A(l,k.quote,k.directive,!1,!1);const M=l.slice(0,h),p=l.slice(h+1),$=o(p);return c=null,p.includes(">")&&(t=!1),`${A(M,k.quote,k.directive,!1,!0)}${$}`}const v=l.match(/^(\s+)([:@#]?[\w-]+(?::[\w-]+)?)(\s*=\s*)(["'])([\s\S]*)$/);if(v){const[,k,h,M,p,$]=v,C=B(h),N=$.indexOf(p),j=`${k}${i(C?"vcb__token_directive":"vcb__token_attribute",h)}${o(M)}`;if(N===-1)return c={quote:p,directive:C},`${j}${A($,p,C,!0,!1)}`;const ue=$.slice(0,N),q=$.slice(N+1);return q.includes(">")&&(t=!1),`${j}${A(ue,p,C,!0,!0)}${o(q)}`}const y=E(_);return u&&(t=!1),y}return a==="script"?z(l):g(l)}).join(`
|
|
5
|
+
`)},H=(e,r,n=!0)=>{const t=e.toLowerCase();return t.includes("vue")||t.includes("html")?oe(r,n):(r||"").replace(/\r\n/g,`
|
|
6
|
+
`).split(`
|
|
7
|
+
`).map(a=>D(e,a,n)).join(`
|
|
8
|
+
`)},ne=["data-theme","aria-label"],ce={key:0,class:"vcb__header"},re={key:0,class:"vcb__meta"},ae={key:0,class:"vcb__filename"},se={class:"vcb__language"},le={class:"vcb__actions"},ie=["disabled"],de={key:0,class:"vcb__line-number"},be=["innerHTML"],L=s.defineComponent({name:"VcbCodeBlock",__name:"CodeBlock",props:{code:{default:""},language:{default:"plaintext"},filename:{default:""},showHeader:{type:Boolean,default:!0},showLineNumbers:{type:Boolean,default:!1},copyable:{type:Boolean,default:!0},copyLabel:{default:"Copy"},copiedLabel:{default:"Copied"},copiedDuration:{default:1200},languageLabel:{default:"Language"},disabled:{type:Boolean,default:!1},wrap:{type:Boolean,default:!1},highlight:{type:Boolean,default:!0},maxHeight:{default:""},ariaLabel:{default:"Code block"},theme:{default:"inherit"}},emits:["copy"],setup(e,{emit:r}){const n=e,t=r,a=s.ref(!1);let c=null;const d=s.computed(()=>n.code.replace(/\r\n/g,`
|
|
9
|
+
`)),l=s.computed(()=>d.value?d.value.split(`
|
|
10
|
+
`):[""]),_=s.computed(()=>H(n.language,d.value,n.highlight).split(`
|
|
11
|
+
`)),b=s.computed(()=>n.theme==="inherit"?void 0:n.theme),m=s.computed(()=>{if(n.maxHeight)return{maxHeight:n.maxHeight}}),u=async()=>{if(!n.disabled)try{typeof navigator<"u"&&navigator.clipboard?.writeText&&await navigator.clipboard.writeText(d.value)}finally{t("copy",{text:d.value}),a.value=!0,c&&clearTimeout(c),c=setTimeout(()=>{a.value=!1,c=null},n.copiedDuration)}};return s.onBeforeUnmount(()=>{c&&(clearTimeout(c),c=null)}),(v,y)=>(s.openBlock(),s.createElementBlock("section",{class:s.normalizeClass(["vcb",{vcb_disabled:e.disabled}]),"data-theme":b.value,"aria-label":e.ariaLabel},[e.showHeader||v.$slots.actions?(s.openBlock(),s.createElementBlock("header",ce,[e.showHeader?(s.openBlock(),s.createElementBlock("div",re,[e.filename?(s.openBlock(),s.createElementBlock("span",ae,s.toDisplayString(e.filename),1)):s.createCommentVNode("",!0),s.createElementVNode("span",se,s.toDisplayString(e.languageLabel)+": "+s.toDisplayString(e.language),1)])):s.createCommentVNode("",!0),s.createElementVNode("div",le,[s.renderSlot(v.$slots,"actions"),e.copyable?(s.openBlock(),s.createElementBlock("button",{key:0,type:"button",class:"vcb__copy",disabled:e.disabled,onClick:u},s.toDisplayString(a.value?e.copiedLabel:e.copyLabel),9,ie)):s.createCommentVNode("",!0)])])):s.createCommentVNode("",!0),s.createElementVNode("pre",{class:s.normalizeClass(["vcb__pre",{vcb__pre_wrap:e.wrap}]),style:s.normalizeStyle(m.value)},[s.createElementVNode("code",null,[(s.openBlock(!0),s.createElementBlock(s.Fragment,null,s.renderList(l.value,(k,h)=>(s.openBlock(),s.createElementBlock("span",{key:h,class:"vcb__line"},[e.showLineNumbers?(s.openBlock(),s.createElementBlock("span",de,s.toDisplayString(h+1),1)):s.createCommentVNode("",!0),s.createElementVNode("span",{class:"vcb__line-content",innerHTML:_.value[h]??""},null,8,be)]))),128))])],6)],10,ne))}}),_e=["plaintext","text","txt","js","javascript","ts","typescript","vue","html","json","bash","shell","sh","css","scss","sass"],ve={install(e){e.component("CodeBlock",L),e.component("VueCodeBlock",L)}};f.CodeBlock=L,f.SUPPORTED_CODE_BLOCK_LANGUAGES=_e,f.default=ve,f.escapeCodeHtml=o,f.highlightCodeBlock=H,f.highlightCodeLine=D,Object.defineProperties(f,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const escapeCodeHtml: (value: string) => string;
|
|
2
|
+
export declare const highlightCodeLine: (language: string, line: string, highlight?: boolean) => string;
|
|
3
|
+
export declare const highlightCodeBlock: (language: string, code: string, highlight?: boolean) => string;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export declare const SUPPORTED_CODE_BLOCK_LANGUAGES: readonly ["plaintext", "text", "txt", "js", "javascript", "ts", "typescript", "vue", "html", "json", "bash", "shell", "sh", "css", "scss", "sass"];
|
|
2
|
+
export type CodeBlockTheme = "inherit" | "light" | "dark";
|
|
3
|
+
export type SupportedCodeBlockLanguage = (typeof SUPPORTED_CODE_BLOCK_LANGUAGES)[number];
|
|
4
|
+
export type CodeBlockLanguage = SupportedCodeBlockLanguage | (string & {});
|
|
5
|
+
export interface CodeBlockCopyPayload {
|
|
6
|
+
text: string;
|
|
7
|
+
}
|
|
8
|
+
export interface CodeBlockProps {
|
|
9
|
+
code?: string;
|
|
10
|
+
language?: CodeBlockLanguage;
|
|
11
|
+
filename?: string;
|
|
12
|
+
showHeader?: boolean;
|
|
13
|
+
showLineNumbers?: boolean;
|
|
14
|
+
copyable?: boolean;
|
|
15
|
+
copyLabel?: string;
|
|
16
|
+
copiedLabel?: string;
|
|
17
|
+
copiedDuration?: number;
|
|
18
|
+
languageLabel?: string;
|
|
19
|
+
disabled?: boolean;
|
|
20
|
+
wrap?: boolean;
|
|
21
|
+
highlight?: boolean;
|
|
22
|
+
maxHeight?: string;
|
|
23
|
+
ariaLabel?: string;
|
|
24
|
+
theme?: CodeBlockTheme;
|
|
25
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@codemonster-ru/vue-codeblock",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Standalone Vue code block component with syntax highlighting and light/dark theming.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Kirill Kolesnikov",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"vue",
|
|
9
|
+
"vue3",
|
|
10
|
+
"code-block",
|
|
11
|
+
"syntax-highlighting",
|
|
12
|
+
"code",
|
|
13
|
+
"documentation"
|
|
14
|
+
],
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/codemonster-ru/vue-codeblock.git"
|
|
18
|
+
},
|
|
19
|
+
"homepage": "https://github.com/codemonster-ru/vue-codeblock#readme",
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/codemonster-ru/vue-codeblock/issues"
|
|
22
|
+
},
|
|
23
|
+
"type": "module",
|
|
24
|
+
"main": "./dist/index.umd.cjs",
|
|
25
|
+
"module": "./dist/index.js",
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"style": "./dist/index.css",
|
|
28
|
+
"sideEffects": [
|
|
29
|
+
"**/*.css"
|
|
30
|
+
],
|
|
31
|
+
"exports": {
|
|
32
|
+
".": {
|
|
33
|
+
"import": {
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"default": "./dist/index.js"
|
|
36
|
+
},
|
|
37
|
+
"require": {
|
|
38
|
+
"types": "./dist/index.d.ts",
|
|
39
|
+
"default": "./dist/index.umd.cjs"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"./style.css": "./dist/index.css"
|
|
43
|
+
},
|
|
44
|
+
"files": [
|
|
45
|
+
"dist"
|
|
46
|
+
],
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"access": "public"
|
|
49
|
+
},
|
|
50
|
+
"scripts": {
|
|
51
|
+
"dev": "vite",
|
|
52
|
+
"build": "vite build",
|
|
53
|
+
"format": "prettier --write .",
|
|
54
|
+
"typecheck": "vue-tsc --noEmit",
|
|
55
|
+
"test": "vitest run"
|
|
56
|
+
},
|
|
57
|
+
"peerDependencies": {
|
|
58
|
+
"vue": "^3.4.0"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"@types/node": "^24.3.1",
|
|
62
|
+
"@vitejs/plugin-vue": "^6.0.1",
|
|
63
|
+
"@vue/test-utils": "^2.4.6",
|
|
64
|
+
"jsdom": "^26.1.0",
|
|
65
|
+
"prettier": "^3.6.2",
|
|
66
|
+
"sass": "^1.77.8",
|
|
67
|
+
"typescript": "^5.5.3",
|
|
68
|
+
"vite": "^7.1.3",
|
|
69
|
+
"vite-plugin-dts": "^4.5.4",
|
|
70
|
+
"vitest": "^3.2.4",
|
|
71
|
+
"vue": "^3.5.21",
|
|
72
|
+
"vue-tsc": "^3.0.7"
|
|
73
|
+
}
|
|
74
|
+
}
|