@feugene/granularity 0.20.0 → 0.21.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/dist/chunks/{config-BJ7Bv_G2.js → config-BC8d_smz.js} +10 -2
- package/dist/chunks/config-BC8d_smz.js.map +1 -0
- package/dist/chunks/config-BDfTXHo1.js.map +1 -0
- package/dist/chunks/config-BEVBsvni2.js.map +1 -0
- package/dist/chunks/config-B_qi4Fma2.js +92 -0
- package/dist/chunks/config-B_qi4Fma2.js.map +1 -0
- package/dist/chunks/config-Baj7Wvx-2.js.map +1 -0
- package/dist/chunks/{config-gwro_7yn.js → config-Bm_Sovla.js} +6 -2
- package/dist/chunks/config-Bm_Sovla.js.map +1 -0
- package/dist/chunks/config-COpuWGr_.js.map +1 -0
- package/dist/chunks/config-DBQQT-WP.js +66 -0
- package/dist/chunks/config-DBQQT-WP.js.map +1 -0
- package/dist/chunks/config-DU2DNSRx.js.map +1 -0
- package/dist/chunks/config-QJ54_fcM.js +61 -0
- package/dist/chunks/config-QJ54_fcM.js.map +1 -0
- package/dist/chunks/config-QaIc_gRa2.js.map +1 -0
- package/dist/chunks/config-ScuvHw6k.js.map +1 -0
- package/dist/chunks/config-jyZq8XKL.js +58 -0
- package/dist/chunks/config-jyZq8XKL.js.map +1 -0
- package/dist/chunks/{en-COdzxgAX.js → en-CwAr3C_x.js} +8 -2
- package/dist/chunks/{en-COdzxgAX.js.map → en-CwAr3C_x.js.map} +1 -1
- package/dist/chunks/{es-DGMHwknJ.js → es-Do1q9_SF.js} +3 -3
- package/dist/chunks/{es-DGMHwknJ.js.map → es-Do1q9_SF.js.map} +1 -1
- package/dist/chunks/{es-ClqJ-4hr.js → es-TR4g2I4A.js} +8 -2
- package/dist/chunks/{es-ClqJ-4hr.js.map → es-TR4g2I4A.js.map} +1 -1
- package/dist/chunks/{generated-BRkbhyxk.js → generated-Do60Aq2I.js} +98 -0
- package/dist/chunks/{generated-BRkbhyxk.js.map → generated-Do60Aq2I.js.map} +1 -1
- package/dist/chunks/{granular-provider-CZYm70Pm.js → granular-provider-BW2uopTG.js} +17 -9
- package/dist/chunks/granular-provider-BW2uopTG.js.map +1 -0
- package/dist/chunks/{ru-9z8ix45c.js → ru-Bm-zWJ3F.js} +8 -2
- package/dist/chunks/{ru-9z8ix45c.js.map → ru-Bm-zWJ3F.js.map} +1 -1
- package/dist/chunks/trending-up-Bf9AQmoq.js +42 -0
- package/dist/chunks/trending-up-Bf9AQmoq.js.map +1 -0
- package/dist/components/GrCard/chunks/GrCard-Bc7nRfbe.js +144 -0
- package/dist/components/GrCard/chunks/GrCard-Bc7nRfbe.js.map +1 -0
- package/dist/components/GrCard/index.js +2 -2
- package/dist/components/GrCodeBlock/chunks/GrCodeBlock-CW3zY1ee.js +341 -0
- package/dist/components/GrCodeBlock/chunks/GrCodeBlock-CW3zY1ee.js.map +1 -0
- package/dist/components/GrCodeBlock/index.js +3 -0
- package/dist/components/GrCodeBlock/styles.css +1 -0
- package/dist/components/GrCollapse/chunks/{GrCollapse-KFcrji1L.js → GrCollapse-C1rCfbc0.js} +2 -2
- package/dist/components/GrCollapse/chunks/{GrCollapse-KFcrji1L.js.map → GrCollapse-C1rCfbc0.js.map} +1 -1
- package/dist/components/GrCollapse/index.js +2 -2
- package/dist/components/GrDataTable/chunks/{GrDataTable-CNvZg2HZ.js → GrDataTable-B5MmZFUg.js} +67 -5
- package/dist/components/GrDataTable/chunks/GrDataTable-B5MmZFUg.js.map +1 -0
- package/dist/components/GrDataTable/index.js +2 -2
- package/dist/components/GrDelta/chunks/GrDelta-BMmpYz8K.js +0 -0
- package/dist/components/GrDelta/chunks/GrDelta-BMmpYz8K.js.map +1 -0
- package/dist/components/GrDelta/index.js +3 -0
- package/dist/components/GrDescriptionList/chunks/GrDescriptionList-pXh1LZEe.js +103 -0
- package/dist/components/GrDescriptionList/chunks/GrDescriptionList-pXh1LZEe.js.map +1 -0
- package/dist/components/GrDescriptionList/index.js +3 -0
- package/dist/components/GrFilePreview/chunks/GrFilePreview-rbE3zL9w.js +315 -0
- package/dist/components/GrFilePreview/chunks/GrFilePreview-rbE3zL9w.js.map +1 -0
- package/dist/components/GrFilePreview/index.js +3 -0
- package/dist/components/GrForm/chunks/{GrForm-DdJw23Pz.js → GrForm-B_Qq_13k.js} +14 -7
- package/dist/components/GrForm/chunks/GrForm-B_Qq_13k.js.map +1 -0
- package/dist/components/GrForm/index.js +1 -1
- package/dist/components/GrImageViewer/chunks/{GrImageViewer-CMO10TS7.js.map → GrImageViewer-ng7el4wn.js.map} +1 -1
- package/dist/components/GrImageViewer/index.js +1 -1
- package/dist/components/GrInputTag/chunks/{GrInputTag-Dghhg03-.js.map → GrInputTag-C7QVPijj.js.map} +1 -1
- package/dist/components/GrInputTag/index.js +1 -1
- package/dist/components/GrList/chunks/{GrList-CHibO0xA.js → GrList-BUzFRa8-.js} +1 -1
- package/dist/components/GrList/chunks/{GrList-CHibO0xA.js.map → GrList-BUzFRa8-.js.map} +1 -1
- package/dist/components/GrList/index.js +1 -1
- package/dist/components/GrRadioGroup/index.js +1 -1
- package/dist/components/GrRating/chunks/{GrRating-BSEtaibx.js → GrRating-BiAVT9H7.js} +1 -1
- package/dist/components/GrRating/chunks/{GrRating-BSEtaibx.js.map → GrRating-BiAVT9H7.js.map} +1 -1
- package/dist/components/GrRating/index.js +2 -2
- package/dist/components/GrSegmented/chunks/{GrSegmented-DP9WMAbm.js → GrSegmented-D1mjxF_O.js} +1 -1
- package/dist/components/GrSegmented/chunks/GrSegmented-D1mjxF_O.js.map +1 -0
- package/dist/components/GrSegmented/index.js +2 -2
- package/dist/components/GrSidebar/chunks/{GrSidebar-DG_t4aPE.js → GrSidebar-D7WxRtIu.js} +7 -1
- package/dist/components/GrSidebar/chunks/{GrSidebar-DG_t4aPE.js.map → GrSidebar-D7WxRtIu.js.map} +1 -1
- package/dist/components/GrSidebar/index.js +1 -1
- package/dist/components/GrSortableList/chunks/{GrSortableList-DJFPdUVv.js → GrSortableList-DPjxilmN.js} +1 -1
- package/dist/components/GrSortableList/chunks/{GrSortableList-DJFPdUVv.js.map → GrSortableList-DPjxilmN.js.map} +1 -1
- package/dist/components/GrSortableList/index.js +1 -1
- package/dist/components/GrStatistic/chunks/{GrStatistic-C3VpykHo.js → GrStatistic-DkzWUAw1.js} +8 -41
- package/dist/components/GrStatistic/chunks/GrStatistic-DkzWUAw1.js.map +1 -0
- package/dist/components/GrStatistic/index.js +1 -1
- package/dist/components/GrTextarea/index.js +1 -1
- package/dist/components/GrTimeline/chunks/{GrTimeline-DlTraRn5.js → GrTimeline-Ch9sHzwL.js} +1 -1
- package/dist/components/GrTimeline/chunks/GrTimeline-Ch9sHzwL.js.map +1 -0
- package/dist/components/GrTimeline/index.js +2 -2
- package/dist/components/GrTimeline/styles.css +1 -1
- package/dist/components/GrToaster/chunks/{GrToaster-Db2NgrXu.js → GrToaster-DJUzx3sR.js} +1 -1
- package/dist/components/GrToaster/chunks/{GrToaster-Db2NgrXu.js.map → GrToaster-DJUzx3sR.js.map} +1 -1
- package/dist/components/GrToaster/index.js +2 -2
- package/dist/composables/useToast.js +14 -2
- package/dist/composables/useToast.js.map +1 -1
- package/dist/granular-provider-node.js +1 -1
- package/dist/granular-provider.js +1 -1
- package/dist/i18n/all.js +1 -1
- package/dist/i18n/index.js +1 -1
- package/dist/index.js +33 -25
- package/dist/theme.js +1 -1
- package/dist/tokens.js +1 -1
- package/dist/types/components/GrButton/GrButton.vue.d.ts +1 -1
- package/dist/types/components/GrCard/GrCard.vue.d.ts +25 -6
- package/dist/types/components/GrCard/defaults.d.ts +2 -1
- package/dist/types/components/GrCard/grCardStyles.d.ts +8 -0
- package/dist/types/components/GrCard/index.d.ts +1 -1
- package/dist/types/components/GrCodeBlock/GrCodeBlock.vue.d.ts +79 -0
- package/dist/types/components/GrCodeBlock/config.d.ts +1 -0
- package/dist/types/components/GrCodeBlock/defaults.d.ts +21 -0
- package/dist/types/components/GrCodeBlock/grCodeBlockStyles.d.ts +53 -0
- package/dist/types/components/GrCodeBlock/index.d.ts +6 -0
- package/dist/types/components/GrCodeBlock/safelist.d.ts +1 -0
- package/dist/types/components/GrCodeBlock/serializeCode.d.ts +19 -0
- package/dist/types/components/GrCodeBlock/tokenizeJson.d.ts +24 -0
- package/dist/types/components/GrCollapse/GrCollapse.vue.d.ts +2 -2
- package/dist/types/components/GrCommandPalette/GrCommandPalette.vue.d.ts +2 -2
- package/dist/types/components/GrDataTable/GrDataTable.vue.d.ts +38 -1
- package/dist/types/components/GrDataTable/grDataTableStyles.d.ts +7 -0
- package/dist/types/components/GrDataTable/index.d.ts +1 -1
- package/dist/types/components/GrDelta/GrDelta.vue.d.ts +84 -0
- package/dist/types/components/GrDelta/config.d.ts +1 -0
- package/dist/types/components/GrDelta/defaults.d.ts +22 -0
- package/dist/types/components/GrDelta/deltaTone.d.ts +24 -0
- package/dist/types/components/GrDelta/grDeltaStyles.d.ts +38 -0
- package/dist/types/components/GrDelta/index.d.ts +6 -0
- package/dist/types/components/GrDelta/safelist.d.ts +1 -0
- package/dist/types/components/GrDescriptionList/GrDescriptionList.vue.d.ts +107 -0
- package/dist/types/components/GrDescriptionList/config.d.ts +1 -0
- package/dist/types/components/GrDescriptionList/defaults.d.ts +21 -0
- package/dist/types/components/GrDescriptionList/grDescriptionListStyles.d.ts +25 -0
- package/dist/types/components/GrDescriptionList/index.d.ts +6 -0
- package/dist/types/components/GrDescriptionList/safelist.d.ts +1 -0
- package/dist/types/components/GrFilePreview/GrFilePreview.vue.d.ts +100 -0
- package/dist/types/components/GrFilePreview/config.d.ts +1 -0
- package/dist/types/components/GrFilePreview/defaults.d.ts +20 -0
- package/dist/types/components/GrFilePreview/fileKindOf.d.ts +14 -0
- package/dist/types/components/GrFilePreview/grFilePreviewStyles.d.ts +37 -0
- package/dist/types/components/GrFilePreview/index.d.ts +6 -0
- package/dist/types/components/GrFilePreview/safelist.d.ts +1 -0
- package/dist/types/components/GrForm/GrForm.vue.d.ts +47 -86
- package/dist/types/components/GrFormField/GrFormField.vue.d.ts +2 -2
- package/dist/types/components/GrImageViewer/GrImageViewer.vue.d.ts +1 -1
- package/dist/types/components/GrInput/GrInput.vue.d.ts +1 -1
- package/dist/types/components/GrInputTag/GrInputTag.vue.d.ts +1 -1
- package/dist/types/components/GrNumberInput/GrNumberInput.vue.d.ts +1 -1
- package/dist/types/components/GrRating/GrRating.vue.d.ts +1 -1
- package/dist/types/components/GrSegmented/GrSegmented.vue.d.ts +1 -1
- package/dist/types/components/GrStatistic/GrStatistic.vue.d.ts +2 -2
- package/dist/types/components/GrSwitch/GrSwitch.vue.d.ts +1 -1
- package/dist/types/components/GrTable/GrTable.vue.d.ts +2 -2
- package/dist/types/components/GrTabs/GrTabs.vue.d.ts +1 -1
- package/dist/types/components/GrTimeline/GrTimelineItem.vue.d.ts +3 -3
- package/dist/types/components/shared/sizes.d.ts +5 -1
- package/dist/types/composables/useToast.d.ts +11 -0
- package/dist/types/granular-provider/shared.d.ts +4 -0
- package/dist/types/i18n/messages/en.d.ts +10 -0
- package/dist/types/i18n/messages/es.d.ts +10 -0
- package/dist/types/i18n/messages/ru.d.ts +10 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/web-types.json +556 -139
- package/package.json +18 -1
- package/dist/chunks/config-BDfTXHo12.js.map +0 -1
- package/dist/chunks/config-BEVBsvni.js.map +0 -1
- package/dist/chunks/config-BJ7Bv_G2.js.map +0 -1
- package/dist/chunks/config-Baj7Wvx-.js.map +0 -1
- package/dist/chunks/config-COpuWGr_2.js.map +0 -1
- package/dist/chunks/config-DU2DNSRx2.js.map +0 -1
- package/dist/chunks/config-QaIc_gRa.js.map +0 -1
- package/dist/chunks/config-ScuvHw6k2.js.map +0 -1
- package/dist/chunks/config-gwro_7yn.js.map +0 -1
- package/dist/chunks/granular-provider-CZYm70Pm.js.map +0 -1
- package/dist/components/GrCard/chunks/GrCard-DfIZOP5N.js +0 -89
- package/dist/components/GrCard/chunks/GrCard-DfIZOP5N.js.map +0 -1
- package/dist/components/GrDataTable/chunks/GrDataTable-CNvZg2HZ.js.map +0 -1
- package/dist/components/GrForm/chunks/GrForm-DdJw23Pz.js.map +0 -1
- package/dist/components/GrSegmented/chunks/GrSegmented-DP9WMAbm.js.map +0 -1
- package/dist/components/GrStatistic/chunks/GrStatistic-C3VpykHo.js.map +0 -1
- package/dist/components/GrTimeline/chunks/GrTimeline-DlTraRn5.js.map +0 -1
- package/dist/chunks/{config-BDfTXHo12.js → config-BDfTXHo1.js} +0 -0
- package/dist/chunks/{config-BEVBsvni.js → config-BEVBsvni2.js} +0 -0
- package/dist/chunks/{config-Baj7Wvx-.js → config-Baj7Wvx-2.js} +0 -0
- package/dist/chunks/{config-COpuWGr_2.js → config-COpuWGr_.js} +0 -0
- package/dist/chunks/{config-DU2DNSRx2.js → config-DU2DNSRx.js} +0 -0
- package/dist/chunks/{config-QaIc_gRa.js → config-QaIc_gRa2.js} +0 -0
- package/dist/chunks/{config-ScuvHw6k2.js → config-ScuvHw6k.js} +0 -0
- package/dist/components/GrImageViewer/chunks/{GrImageViewer-CMO10TS7.js → GrImageViewer-ng7el4wn.js} +1 -1
- package/dist/components/GrInputTag/chunks/{GrInputTag-Dghhg03-.js → GrInputTag-C7QVPijj.js} +1 -1
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import { a as useGrComponentSize, i as useGrComponentProp } from "../../../chunks/context-CTbuwcYs.js";
|
|
2
|
+
import { n as useGranularityTranslations } from "../../../chunks/granularityI18n-BC5zsj_d.js";
|
|
3
|
+
import { t as check_default } from "../../../chunks/check-BZI24Qs4.js";
|
|
4
|
+
import { t as GrButton_default } from "../../GrButton/chunks/GrButton-Bw2AH4uX.js";
|
|
5
|
+
import { useAnnouncer } from "../../../composables/useAnnouncer.js";
|
|
6
|
+
import { a as codeBlockHookClass, c as codeBlockPaddings, d as codeBlockTextSizes, f as codeBlockWrapClass, i as codeBlockGutterClass, l as codeBlockRootClass, o as codeBlockNowrapClass, p as codeTokenClass, r as codeBlockCopyClass, s as codeBlockNumberedClass, u as codeBlockScrollClass } from "../../../chunks/config-B_qi4Fma2.js";
|
|
7
|
+
import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, defineComponent, markRaw, normalizeClass, normalizeStyle, onBeforeUnmount, onMounted, openBlock, ref, renderList, resolveDynamicComponent, toDisplayString, unref, withCtx } from "vue";
|
|
8
|
+
import '../styles.css';//#region ~icons/lucide/copy
|
|
9
|
+
var _hoisted_1$1 = {
|
|
10
|
+
viewBox: "0 0 24 24",
|
|
11
|
+
width: "1.2em",
|
|
12
|
+
height: "1.2em"
|
|
13
|
+
};
|
|
14
|
+
function render$1(_ctx, _cache) {
|
|
15
|
+
return openBlock(), createElementBlock("svg", _hoisted_1$1, [..._cache[0] || (_cache[0] = [createElementVNode("g", {
|
|
16
|
+
fill: "none",
|
|
17
|
+
stroke: "currentColor",
|
|
18
|
+
"stroke-linecap": "round",
|
|
19
|
+
"stroke-linejoin": "round",
|
|
20
|
+
"stroke-width": "2"
|
|
21
|
+
}, [createElementVNode("rect", {
|
|
22
|
+
width: "14",
|
|
23
|
+
height: "14",
|
|
24
|
+
x: "8",
|
|
25
|
+
y: "8",
|
|
26
|
+
rx: "2",
|
|
27
|
+
ry: "2"
|
|
28
|
+
}), createElementVNode("path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" })], -1)])]);
|
|
29
|
+
}
|
|
30
|
+
var copy_default = markRaw({
|
|
31
|
+
name: "lucide-copy",
|
|
32
|
+
render: render$1
|
|
33
|
+
});
|
|
34
|
+
//#endregion
|
|
35
|
+
//#region src/components/GrCodeBlock/serializeCode.ts
|
|
36
|
+
/**
|
|
37
|
+
* Приведение произвольного значения к тексту для показа.
|
|
38
|
+
*
|
|
39
|
+
* Компонент показывает данные из БД, и они бывают любыми: `unknown`-поле ответа
|
|
40
|
+
* модели, `meta` запуска, тело ошибки. Поэтому сериализация обязана пережить всё
|
|
41
|
+
* — уронить страницу она права не имеет.
|
|
42
|
+
*/
|
|
43
|
+
/** Маркер повторной ссылки. Показывается вместо ветки, которая уже встречалась выше. */
|
|
44
|
+
var CIRCULAR_MARKER = "[Circular]";
|
|
45
|
+
/** Что печатается, когда сериализовать не удалось вовсе. */
|
|
46
|
+
var UNSERIALIZABLE_MARKER = "[Unserializable]";
|
|
47
|
+
/**
|
|
48
|
+
* Замена значений, на которых штатный `JSON.stringify` спотыкается.
|
|
49
|
+
*
|
|
50
|
+
* Маркером помечается **повторная ссылка**, а не только настоящий цикл: объект,
|
|
51
|
+
* положенный в дерево дважды, тоже её получит. Отличить одно от другого можно
|
|
52
|
+
* лишь стеком предков, а `replacer` его не отдаёт — узнать, что обход вышел из
|
|
53
|
+
* ветки, изнутри нечем. Размен осознанный: показать `[Circular]` там, где данные
|
|
54
|
+
* просто переиспользуют объект, — неточность; зациклиться на настоящем цикле —
|
|
55
|
+
* зависшая вкладка.
|
|
56
|
+
*/
|
|
57
|
+
function createSafeReplacer() {
|
|
58
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
59
|
+
return function safeReplacer(_key, value) {
|
|
60
|
+
if (typeof value === "bigint") return `${value}n`;
|
|
61
|
+
if (typeof value !== "object" || value === null) return value;
|
|
62
|
+
if (seen.has(value)) return CIRCULAR_MARKER;
|
|
63
|
+
seen.add(value);
|
|
64
|
+
return value;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Значение → текст.
|
|
69
|
+
*
|
|
70
|
+
* Строка проходит как есть: это уже готовый текст, и оборачивать его в кавычки
|
|
71
|
+
* значило бы показать не то, что пришло. `undefined` даёт пустую строку —
|
|
72
|
+
* показывать нечего. Всё остальное сериализуется с отступом.
|
|
73
|
+
*/
|
|
74
|
+
function serializeCode(value, indent = 2) {
|
|
75
|
+
if (typeof value === "string") return value;
|
|
76
|
+
if (value === void 0) return "";
|
|
77
|
+
try {
|
|
78
|
+
return JSON.stringify(value, createSafeReplacer(), indent) ?? "";
|
|
79
|
+
} catch {
|
|
80
|
+
return UNSERIALIZABLE_MARKER;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//#endregion
|
|
84
|
+
//#region src/components/GrCodeBlock/tokenizeJson.ts
|
|
85
|
+
var PUNCTUATION = /* @__PURE__ */ new Set([
|
|
86
|
+
"{",
|
|
87
|
+
"}",
|
|
88
|
+
"[",
|
|
89
|
+
"]",
|
|
90
|
+
",",
|
|
91
|
+
":"
|
|
92
|
+
]);
|
|
93
|
+
var LITERALS = [
|
|
94
|
+
"true",
|
|
95
|
+
"false",
|
|
96
|
+
"null"
|
|
97
|
+
];
|
|
98
|
+
/** Строка от открывающей кавычки до закрывающей, с учётом экранирования. */
|
|
99
|
+
function readString(source, start) {
|
|
100
|
+
let index = start + 1;
|
|
101
|
+
while (index < source.length) {
|
|
102
|
+
const char = source[index];
|
|
103
|
+
if (char === "\\") {
|
|
104
|
+
index += 2;
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
index += 1;
|
|
108
|
+
if (char === "\"") break;
|
|
109
|
+
}
|
|
110
|
+
return index;
|
|
111
|
+
}
|
|
112
|
+
/** Число целиком: знак, дробная часть, экспонента. */
|
|
113
|
+
function readNumber(source, start) {
|
|
114
|
+
let index = start;
|
|
115
|
+
if (source[index] === "-") index += 1;
|
|
116
|
+
while (index < source.length && /[\d.eE+-]/.test(source[index])) index += 1;
|
|
117
|
+
return index;
|
|
118
|
+
}
|
|
119
|
+
/** Первый непробельный символ после позиции — по нему строка отличается от ключа. */
|
|
120
|
+
function nextMeaningful(source, from) {
|
|
121
|
+
for (let index = from; index < source.length; index += 1) if (!/\s/.test(source[index])) return source[index];
|
|
122
|
+
}
|
|
123
|
+
function tokenizeJson(source) {
|
|
124
|
+
const tokens = [];
|
|
125
|
+
let index = 0;
|
|
126
|
+
let plainStart = 0;
|
|
127
|
+
const flushPlain = (until) => {
|
|
128
|
+
if (until > plainStart) tokens.push({
|
|
129
|
+
text: source.slice(plainStart, until),
|
|
130
|
+
kind: "plain"
|
|
131
|
+
});
|
|
132
|
+
};
|
|
133
|
+
while (index < source.length) {
|
|
134
|
+
const char = source[index];
|
|
135
|
+
if (char === "\"") {
|
|
136
|
+
flushPlain(index);
|
|
137
|
+
const end = readString(source, index);
|
|
138
|
+
const kind = nextMeaningful(source, end) === ":" ? "key" : "string";
|
|
139
|
+
tokens.push({
|
|
140
|
+
text: source.slice(index, end),
|
|
141
|
+
kind
|
|
142
|
+
});
|
|
143
|
+
index = end;
|
|
144
|
+
plainStart = index;
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (PUNCTUATION.has(char)) {
|
|
148
|
+
flushPlain(index);
|
|
149
|
+
tokens.push({
|
|
150
|
+
text: char,
|
|
151
|
+
kind: "punctuation"
|
|
152
|
+
});
|
|
153
|
+
index += 1;
|
|
154
|
+
plainStart = index;
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
if (char === "-" || char >= "0" && char <= "9") {
|
|
158
|
+
flushPlain(index);
|
|
159
|
+
const end = readNumber(source, index);
|
|
160
|
+
tokens.push({
|
|
161
|
+
text: source.slice(index, end),
|
|
162
|
+
kind: "number"
|
|
163
|
+
});
|
|
164
|
+
index = end;
|
|
165
|
+
plainStart = index;
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
const literal = LITERALS.find((candidate) => source.startsWith(candidate, index));
|
|
169
|
+
if (literal) {
|
|
170
|
+
flushPlain(index);
|
|
171
|
+
tokens.push({
|
|
172
|
+
text: literal,
|
|
173
|
+
kind: "literal"
|
|
174
|
+
});
|
|
175
|
+
index += literal.length;
|
|
176
|
+
plainStart = index;
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
index += 1;
|
|
180
|
+
}
|
|
181
|
+
flushPlain(source.length);
|
|
182
|
+
return tokens;
|
|
183
|
+
}
|
|
184
|
+
//#endregion
|
|
185
|
+
//#region src/components/GrCodeBlock/GrCodeBlock.vue?vue&type=script&setup=true&lang.ts
|
|
186
|
+
var _hoisted_1 = [
|
|
187
|
+
"tabindex",
|
|
188
|
+
"role",
|
|
189
|
+
"aria-label"
|
|
190
|
+
];
|
|
191
|
+
var _hoisted_2 = { "data-gr-code-block-code": "" };
|
|
192
|
+
//#endregion
|
|
193
|
+
//#region src/components/GrCodeBlock/GrCodeBlock.vue
|
|
194
|
+
var GrCodeBlock_default = /* @__PURE__ */ defineComponent({
|
|
195
|
+
__name: "GrCodeBlock",
|
|
196
|
+
props: {
|
|
197
|
+
code: {},
|
|
198
|
+
language: { default: "json" },
|
|
199
|
+
maxHeight: { default: void 0 },
|
|
200
|
+
copyable: {
|
|
201
|
+
type: Boolean,
|
|
202
|
+
default: void 0
|
|
203
|
+
},
|
|
204
|
+
wrap: {
|
|
205
|
+
type: Boolean,
|
|
206
|
+
default: void 0
|
|
207
|
+
},
|
|
208
|
+
lineNumbers: {
|
|
209
|
+
type: Boolean,
|
|
210
|
+
default: void 0
|
|
211
|
+
},
|
|
212
|
+
ariaLabel: { default: void 0 },
|
|
213
|
+
size: { default: void 0 }
|
|
214
|
+
},
|
|
215
|
+
emits: ["copy"],
|
|
216
|
+
setup(__props, { emit: __emit }) {
|
|
217
|
+
const props = __props;
|
|
218
|
+
const emit = __emit;
|
|
219
|
+
const { t } = useGranularityTranslations();
|
|
220
|
+
const { announce } = useAnnouncer();
|
|
221
|
+
const resolvedSize = useGrComponentSize(() => props.size, { component: "GrCodeBlock" });
|
|
222
|
+
const resolvedCopyable = useGrComponentProp("GrCodeBlock", "copyable", () => props.copyable, true);
|
|
223
|
+
const resolvedWrap = useGrComponentProp("GrCodeBlock", "wrap", () => props.wrap, false);
|
|
224
|
+
const resolvedLineNumbers = useGrComponentProp("GrCodeBlock", "lineNumbers", () => props.lineNumbers, false);
|
|
225
|
+
/** Единственный источник текста: он же рендерится, он же уходит в буфер. */
|
|
226
|
+
const source = computed(() => serializeCode(props.code));
|
|
227
|
+
/**
|
|
228
|
+
* Разбор идёт по строкам, а не по всему тексту: номер строки — CSS-счётчик, а
|
|
229
|
+
* счётчику нужен элемент на строку. JSON-строка перенос не содержит (он в ней
|
|
230
|
+
* экранирован), поэтому построчная токенизация ничего не рвёт.
|
|
231
|
+
*/
|
|
232
|
+
const lines = computed(() => {
|
|
233
|
+
const rows = source.value.split("\n");
|
|
234
|
+
if (props.language !== "json") return rows.map((row) => [{
|
|
235
|
+
text: row,
|
|
236
|
+
kind: "plain"
|
|
237
|
+
}]);
|
|
238
|
+
return rows.map((row) => tokenizeJson(row));
|
|
239
|
+
});
|
|
240
|
+
/**
|
|
241
|
+
* Блок — скроллер по конструкции, а не по замеру. Замер здесь означал бы
|
|
242
|
+
* мигающую остановку `Tab` на каждой смене данных и загрузке шрифта; ни один
|
|
243
|
+
* компонент пакета так не делает.
|
|
244
|
+
*/
|
|
245
|
+
const isScroller = computed(() => props.maxHeight !== void 0 || !resolvedWrap.value);
|
|
246
|
+
const scrollStyle = computed(() => {
|
|
247
|
+
if (props.maxHeight === void 0) return void 0;
|
|
248
|
+
return { maxHeight: typeof props.maxHeight === "number" ? `${props.maxHeight}px` : props.maxHeight };
|
|
249
|
+
});
|
|
250
|
+
const preClass = computed(() => [
|
|
251
|
+
codeBlockHookClass,
|
|
252
|
+
"m-0",
|
|
253
|
+
codeBlockPaddings[resolvedSize.value],
|
|
254
|
+
codeBlockTextSizes[resolvedSize.value],
|
|
255
|
+
resolvedWrap.value ? codeBlockWrapClass : codeBlockNowrapClass,
|
|
256
|
+
isScroller.value ? codeBlockScrollClass : ""
|
|
257
|
+
].filter(Boolean).join(" "));
|
|
258
|
+
/**
|
|
259
|
+
* Наличие буфера уточняется после монтирования: `navigator` в теле `setup` либо
|
|
260
|
+
* роняет серверный рендер, либо расходится с ним. До этого момента кнопки нет —
|
|
261
|
+
* ровно то же, что отдаёт сервер, поэтому гидрация совпадает.
|
|
262
|
+
*/
|
|
263
|
+
const canCopy = ref(false);
|
|
264
|
+
onMounted(() => {
|
|
265
|
+
canCopy.value = typeof navigator !== "undefined" && typeof navigator.clipboard?.writeText === "function";
|
|
266
|
+
});
|
|
267
|
+
const showCopy = computed(() => resolvedCopyable.value && canCopy.value);
|
|
268
|
+
const copied = ref(false);
|
|
269
|
+
let copiedTimer = null;
|
|
270
|
+
function resetCopiedTimer() {
|
|
271
|
+
if (copiedTimer !== null) {
|
|
272
|
+
clearTimeout(copiedTimer);
|
|
273
|
+
copiedTimer = null;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
onBeforeUnmount(resetCopiedTimer);
|
|
277
|
+
async function copy() {
|
|
278
|
+
try {
|
|
279
|
+
await navigator.clipboard.writeText(source.value);
|
|
280
|
+
} catch {
|
|
281
|
+
announce(t("gr.codeBlock.copyFailed", "Could not copy code"));
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
copied.value = true;
|
|
285
|
+
resetCopiedTimer();
|
|
286
|
+
copiedTimer = window.setTimeout(() => {
|
|
287
|
+
copied.value = false;
|
|
288
|
+
copiedTimer = null;
|
|
289
|
+
}, 1200);
|
|
290
|
+
announce(t("gr.codeBlock.copied", "Code copied"));
|
|
291
|
+
emit("copy", source.value);
|
|
292
|
+
}
|
|
293
|
+
const copyLabel = computed(() => copied.value ? t("gr.codeBlock.copied", "Code copied") : t("gr.codeBlock.copy", "Copy code"));
|
|
294
|
+
return (_ctx, _cache) => {
|
|
295
|
+
return openBlock(), createElementBlock("div", {
|
|
296
|
+
"data-gr-code-block": "",
|
|
297
|
+
class: normalizeClass([unref(codeBlockRootClass), showCopy.value ? unref(codeBlockGutterClass) : ""])
|
|
298
|
+
}, [showCopy.value ? (openBlock(), createBlock(GrButton_default, {
|
|
299
|
+
key: 0,
|
|
300
|
+
"data-gr-code-block-copy": "",
|
|
301
|
+
variant: "ghost",
|
|
302
|
+
size: "xs",
|
|
303
|
+
square: "",
|
|
304
|
+
class: normalizeClass(unref(codeBlockCopyClass)),
|
|
305
|
+
"aria-label": copyLabel.value,
|
|
306
|
+
title: copyLabel.value,
|
|
307
|
+
onClick: copy
|
|
308
|
+
}, {
|
|
309
|
+
default: withCtx(() => [(openBlock(), createBlock(resolveDynamicComponent(copied.value ? unref(check_default) : unref(copy_default)), {
|
|
310
|
+
class: "h-3.5 w-3.5",
|
|
311
|
+
"aria-hidden": "true"
|
|
312
|
+
}))]),
|
|
313
|
+
_: 1
|
|
314
|
+
}, 8, [
|
|
315
|
+
"class",
|
|
316
|
+
"aria-label",
|
|
317
|
+
"title"
|
|
318
|
+
])) : createCommentVNode("", true), createElementVNode("pre", {
|
|
319
|
+
"data-gr-code-block-scroll": "",
|
|
320
|
+
class: normalizeClass([preClass.value, unref(resolvedLineNumbers) ? unref(codeBlockNumberedClass) : ""]),
|
|
321
|
+
style: normalizeStyle(scrollStyle.value),
|
|
322
|
+
tabindex: isScroller.value ? 0 : void 0,
|
|
323
|
+
role: __props.ariaLabel ? "region" : void 0,
|
|
324
|
+
"aria-label": __props.ariaLabel
|
|
325
|
+
}, [createElementVNode("code", _hoisted_2, [(openBlock(true), createElementBlock(Fragment, null, renderList(lines.value, (tokens, index) => {
|
|
326
|
+
return openBlock(), createElementBlock("span", {
|
|
327
|
+
key: index,
|
|
328
|
+
"data-gr-code-block-line": "",
|
|
329
|
+
class: "gr-code-block__line"
|
|
330
|
+
}, [(openBlock(true), createElementBlock(Fragment, null, renderList(tokens, (token, tokenIndex) => {
|
|
331
|
+
return openBlock(), createElementBlock("span", {
|
|
332
|
+
key: tokenIndex,
|
|
333
|
+
class: normalizeClass(unref(codeTokenClass)[token.kind])
|
|
334
|
+
}, toDisplayString(token.text), 3);
|
|
335
|
+
}), 128))]);
|
|
336
|
+
}), 128))])], 14, _hoisted_1)], 2);
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
//#endregion
|
|
341
|
+
export { GrCodeBlock_default as t };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GrCodeBlock-CW3zY1ee.js","names":[],"sources":["../../../../src/components/GrCodeBlock/serializeCode.ts","../../../../src/components/GrCodeBlock/tokenizeJson.ts","../../../../src/components/GrCodeBlock/GrCodeBlock.vue","../../../../src/components/GrCodeBlock/GrCodeBlock.vue"],"sourcesContent":["/**\n * Приведение произвольного значения к тексту для показа.\n *\n * Компонент показывает данные из БД, и они бывают любыми: `unknown`-поле ответа\n * модели, `meta` запуска, тело ошибки. Поэтому сериализация обязана пережить всё\n * — уронить страницу она права не имеет.\n */\n\n/** Маркер повторной ссылки. Показывается вместо ветки, которая уже встречалась выше. */\nexport const CIRCULAR_MARKER = '[Circular]'\n\n/** Что печатается, когда сериализовать не удалось вовсе. */\nexport const UNSERIALIZABLE_MARKER = '[Unserializable]'\n\n/**\n * Замена значений, на которых штатный `JSON.stringify` спотыкается.\n *\n * Маркером помечается **повторная ссылка**, а не только настоящий цикл: объект,\n * положенный в дерево дважды, тоже её получит. Отличить одно от другого можно\n * лишь стеком предков, а `replacer` его не отдаёт — узнать, что обход вышел из\n * ветки, изнутри нечем. Размен осознанный: показать `[Circular]` там, где данные\n * просто переиспользуют объект, — неточность; зациклиться на настоящем цикле —\n * зависшая вкладка.\n */\nfunction createSafeReplacer(): (key: string, value: unknown) => unknown {\n const seen = new WeakSet<object>()\n\n return function safeReplacer(_key: string, value: unknown): unknown {\n // `BigInt` не имеет представления в JSON, и `stringify` на нём бросает.\n if (typeof value === 'bigint') return `${value}n`\n\n if (typeof value !== 'object' || value === null) return value\n\n if (seen.has(value)) return CIRCULAR_MARKER\n\n seen.add(value)\n return value\n }\n}\n\n/**\n * Значение → текст.\n *\n * Строка проходит как есть: это уже готовый текст, и оборачивать его в кавычки\n * значило бы показать не то, что пришло. `undefined` даёт пустую строку —\n * показывать нечего. Всё остальное сериализуется с отступом.\n */\nexport function serializeCode(value: unknown, indent = 2): string {\n if (typeof value === 'string') return value\n if (value === undefined) return ''\n\n try {\n const serialized = JSON.stringify(value, createSafeReplacer(), indent)\n // `stringify` отдаёт `undefined` на функции и символе — печатать «undefined»\n // строкой было бы враньём про содержимое.\n return serialized ?? ''\n }\n catch {\n return UNSERIALIZABLE_MARKER\n }\n}\n","/**\n * Токенизация JSON для подсветки.\n *\n * Своя, а не библиотечная: тянуть highlight.js ради четырёх ролей несоразмерно\n * — компонент показывает JSON и обычный текст, а не произвольные языки.\n *\n * Разбор посимвольный и **ничего не теряет**: пробелы, переносы и запятые тоже\n * становятся токенами. Отсюда инвариант, который держит тест: склейка `text`\n * всех токенов равна исходной строке. Любая потеря символа — сдвиг разметки.\n */\n\nexport type GrCodeTokenKind =\n /** Имя поля объекта: строка, за которой идёт двоеточие. */\n | 'key'\n | 'string'\n | 'number'\n /** `true`, `false`, `null`. */\n | 'literal'\n /** Скобки, запятые, двоеточия. */\n | 'punctuation'\n /** Пробелы, переносы и всё, что не опознано. */\n | 'plain'\n\nexport interface GrCodeToken {\n text: string\n kind: GrCodeTokenKind\n}\n\nconst PUNCTUATION = new Set(['{', '}', '[', ']', ',', ':'])\nconst LITERALS = ['true', 'false', 'null'] as const\n\n/** Строка от открывающей кавычки до закрывающей, с учётом экранирования. */\nfunction readString(source: string, start: number): number {\n let index = start + 1\n\n while (index < source.length) {\n const char = source[index]\n\n // Экранированная кавычка не закрывает строку: `\"a\\\":b\"` — одно значение,\n // а не строка плюс мусор.\n if (char === '\\\\') {\n index += 2\n continue\n }\n\n index += 1\n if (char === '\"') break\n }\n\n return index\n}\n\n/** Число целиком: знак, дробная часть, экспонента. */\nfunction readNumber(source: string, start: number): number {\n let index = start\n\n if (source[index] === '-') index += 1\n while (index < source.length && /[\\d.eE+-]/.test(source[index])) index += 1\n\n return index\n}\n\n/** Первый непробельный символ после позиции — по нему строка отличается от ключа. */\nfunction nextMeaningful(source: string, from: number): string | undefined {\n for (let index = from; index < source.length; index += 1) {\n if (!/\\s/.test(source[index])) return source[index]\n }\n\n return undefined\n}\n\nexport function tokenizeJson(source: string): GrCodeToken[] {\n const tokens: GrCodeToken[] = []\n let index = 0\n let plainStart = 0\n\n const flushPlain = (until: number): void => {\n if (until > plainStart) tokens.push({ text: source.slice(plainStart, until), kind: 'plain' })\n }\n\n while (index < source.length) {\n const char = source[index]\n\n if (char === '\"') {\n flushPlain(index)\n const end = readString(source, index)\n // Ключ от строки отличает только идущее следом двоеточие.\n const kind: GrCodeTokenKind = nextMeaningful(source, end) === ':' ? 'key' : 'string'\n tokens.push({ text: source.slice(index, end), kind })\n index = end\n plainStart = index\n continue\n }\n\n if (PUNCTUATION.has(char)) {\n flushPlain(index)\n tokens.push({ text: char, kind: 'punctuation' })\n index += 1\n plainStart = index\n continue\n }\n\n if (char === '-' || (char >= '0' && char <= '9')) {\n flushPlain(index)\n const end = readNumber(source, index)\n tokens.push({ text: source.slice(index, end), kind: 'number' })\n index = end\n plainStart = index\n continue\n }\n\n const literal = LITERALS.find(candidate => source.startsWith(candidate, index))\n if (literal) {\n flushPlain(index)\n tokens.push({ text: literal, kind: 'literal' })\n index += literal.length\n plainStart = index\n continue\n }\n\n index += 1\n }\n\n flushPlain(source.length)\n\n return tokens\n}\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, ref } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport { useAnnouncer } from '../../composables/useAnnouncer'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\n\nimport IconCheck from '~icons/lucide/check'\nimport IconCopy from '~icons/lucide/copy'\n\nimport { serializeCode } from './serializeCode'\nimport { tokenizeJson, type GrCodeToken } from './tokenizeJson'\nimport {\n codeBlockCopyClass,\n codeBlockGutterClass,\n codeBlockHookClass,\n codeBlockNowrapClass,\n codeBlockNumberedClass as numberedClass,\n codeBlockPaddings,\n codeBlockRootClass,\n codeBlockScrollClass,\n codeBlockSurfaceClass,\n codeBlockTextSizes,\n codeBlockWrapClass,\n codeTokenClass,\n} from './grCodeBlockStyles'\n\nimport type { GrComponentSize } from '../shared/sizes'\n\nexport type { GrCodeToken, GrCodeTokenKind } from './tokenizeJson'\n\n/** Язык подсветки. Кроме JSON компонент ничего не разбирает — и не должен. */\nexport type GrCodeBlockLanguage = 'json' | 'text'\n\n/**\n * Блок сырого текста или JSON: моноширинный, с подсветкой, номерами строк и\n * копированием в буфер.\n *\n * Показывает, а не редактирует и не сворачивает узлы. Свёртка по узлам — задача\n * `GrJsonViewer`, дерево выбора — `GrTree`.\n */\nexport interface GrCodeBlockProps {\n /** Строка или значение: объект сериализуется с отступом. */\n code: unknown\n language?: GrCodeBlockLanguage\n /** Высота, после которой включается вертикальный скролл. */\n maxHeight?: string | number\n /** Кнопка копирования. Без защищённого контекста не рисуется вовсе. */\n copyable?: boolean\n /** Переносить длинные строки вместо горизонтальной прокрутки. */\n wrap?: boolean\n lineNumbers?: boolean\n /** Имя области прокрутки. Безымянную скринридер объявляет просто «регион». */\n ariaLabel?: string\n size?: GrComponentSize\n}\n\nexport interface GrCodeBlockEmits {\n /** Текст скопирован. Тост показывает потребитель: у блока своего места для него нет. */\n (e: 'copy', code: string): void\n}\n\nconst props = withDefaults(defineProps<GrCodeBlockProps>(), {\n // Дефолты живут в резолверах ниже: Vue подставил бы свой раньше, чем компонент\n // заглянет в `GrConfigProvider`.\n language: 'json',\n maxHeight: undefined,\n copyable: undefined,\n wrap: undefined,\n lineNumbers: undefined,\n ariaLabel: undefined,\n size: undefined,\n})\n\nconst emit = defineEmits<GrCodeBlockEmits>()\n\nconst { t } = useGranularityTranslations()\nconst { announce } = useAnnouncer()\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrCodeBlock' })\nconst resolvedCopyable = useGrComponentProp('GrCodeBlock', 'copyable', () => props.copyable, true)\nconst resolvedWrap = useGrComponentProp('GrCodeBlock', 'wrap', () => props.wrap, false)\nconst resolvedLineNumbers = useGrComponentProp('GrCodeBlock', 'lineNumbers', () => props.lineNumbers, false)\n\n/** Единственный источник текста: он же рендерится, он же уходит в буфер. */\nconst source = computed(() => serializeCode(props.code))\n\n/**\n * Разбор идёт по строкам, а не по всему тексту: номер строки — CSS-счётчик, а\n * счётчику нужен элемент на строку. JSON-строка перенос не содержит (он в ней\n * экранирован), поэтому построчная токенизация ничего не рвёт.\n */\nconst lines = computed<GrCodeToken[][]>(() => {\n const rows = source.value.split('\\n')\n\n if (props.language !== 'json') return rows.map(row => [{ text: row, kind: 'plain' as const }])\n\n return rows.map(row => tokenizeJson(row))\n})\n\n/**\n * Блок — скроллер по конструкции, а не по замеру. Замер здесь означал бы\n * мигающую остановку `Tab` на каждой смене данных и загрузке шрифта; ни один\n * компонент пакета так не делает.\n */\nconst isScroller = computed(() => props.maxHeight !== undefined || !resolvedWrap.value)\n\nconst scrollStyle = computed(() => {\n if (props.maxHeight === undefined) return undefined\n\n return { maxHeight: typeof props.maxHeight === 'number' ? `${props.maxHeight}px` : props.maxHeight }\n})\n\nconst preClass = computed(() => [\n codeBlockHookClass,\n codeBlockSurfaceClass,\n codeBlockPaddings[resolvedSize.value],\n codeBlockTextSizes[resolvedSize.value],\n resolvedWrap.value ? codeBlockWrapClass : codeBlockNowrapClass,\n isScroller.value ? codeBlockScrollClass : '',\n].filter(Boolean).join(' '))\n\n/**\n * Наличие буфера уточняется после монтирования: `navigator` в теле `setup` либо\n * роняет серверный рендер, либо расходится с ним. До этого момента кнопки нет —\n * ровно то же, что отдаёт сервер, поэтому гидрация совпадает.\n */\nconst canCopy = ref(false)\n\nonMounted(() => {\n canCopy.value = typeof navigator !== 'undefined' && typeof navigator.clipboard?.writeText === 'function'\n})\n\nconst showCopy = computed(() => resolvedCopyable.value && canCopy.value)\n\nconst copied = ref(false)\nlet copiedTimer: number | null = null\n\nfunction resetCopiedTimer(): void {\n if (copiedTimer !== null) {\n clearTimeout(copiedTimer)\n copiedTimer = null\n }\n}\n\nonBeforeUnmount(resetCopiedTimer)\n\nasync function copy(): Promise<void> {\n try {\n // Копируется исходный текст, а не разметка: номера строк — CSS-счётчик,\n // а мягкие переносы принадлежат показу, и вставить их обратно нельзя.\n await navigator.clipboard.writeText(source.value)\n }\n catch {\n announce(t('gr.codeBlock.copyFailed', 'Could not copy code'))\n return\n }\n\n copied.value = true\n resetCopiedTimer()\n copiedTimer = window.setTimeout(() => {\n copied.value = false\n copiedTimer = null\n }, 1200)\n\n announce(t('gr.codeBlock.copied', 'Code copied'))\n emit('copy', source.value)\n}\n\nconst copyLabel = computed(() => (\n copied.value ? t('gr.codeBlock.copied', 'Code copied') : t('gr.codeBlock.copy', 'Copy code')\n))\n</script>\n\n<template>\n <div data-gr-code-block :class=\"[codeBlockRootClass, showCopy ? codeBlockGutterClass : '']\">\n <GrButton\n v-if=\"showCopy\"\n data-gr-code-block-copy\n variant=\"ghost\"\n size=\"xs\"\n square\n :class=\"codeBlockCopyClass\"\n :aria-label=\"copyLabel\"\n :title=\"copyLabel\"\n @click=\"copy\"\n >\n <component :is=\"copied ? IconCheck : IconCopy\" class=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n </GrButton>\n\n <!--\n Внутри `<pre>` пробелы значимы, и компилятор Vue их здесь не схлопывает:\n любой перенос между тегами стал бы пустой строкой в коде. Поэтому\n содержимое блока записано без переносов — строки разделяет `display: block`\n у `.gr-code-block__line`, а не текстовый `\\n`.\n -->\n <pre\n data-gr-code-block-scroll\n :class=\"[preClass, resolvedLineNumbers ? numberedClass : '']\"\n :style=\"scrollStyle\"\n :tabindex=\"isScroller ? 0 : undefined\"\n :role=\"ariaLabel ? 'region' : undefined\"\n :aria-label=\"ariaLabel\"\n ><code data-gr-code-block-code><span v-for=\"(tokens, index) in lines\" :key=\"index\" data-gr-code-block-line class=\"gr-code-block__line\"><span v-for=\"(token, tokenIndex) in tokens\" :key=\"tokenIndex\" :class=\"codeTokenClass[token.kind]\">{{ token.text }}</span></span></code></pre>\n </div>\n</template>\n\n<style>\n/*\n * Номер строки — CSS-счётчик, а не текст в разметке. Разница не косметическая:\n * узел со `<span>2</span>` попадает в выделение мышью, и в буфер уезжает то,\n * что нельзя вставить обратно как код. У `::before` содержимого в DOM нет.\n *\n * Стиль глобальный, а не scoped: правило адресует псевдоэлемент строки, и\n * scoped-атрибут пришлось бы вешать на каждый из них.\n */\n:where(.gr-code-block__line) {\n display: block;\n}\n\n:where(.gr-code-block--numbered) {\n counter-reset: gr-code-line;\n}\n\n/*\n * Висячий отступ: строка сдвинута на ширину колонки номеров, а первая строка\n * возвращена назад отрицательным `text-indent` — туда и встаёт номер. Без этого\n * перенесённая при `wrap` строка начиналась бы под номером, а не под кодом.\n */\n:where(.gr-code-block--numbered .gr-code-block__line) {\n padding-left: calc(var(--gr-code-block-line-number-width, 2.5em) + 1em);\n text-indent: calc(-1 * (var(--gr-code-block-line-number-width, 2.5em) + 1em));\n}\n\n:where(.gr-code-block--numbered .gr-code-block__line)::before {\n counter-increment: gr-code-line;\n content: counter(gr-code-line);\n display: inline-block;\n width: var(--gr-code-block-line-number-width, 2.5em);\n margin-right: 1em;\n text-align: right;\n text-indent: 0;\n color: var(--gr-code-block-line-number, var(--gr-muted-fg));\n user-select: none;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, ref } from 'vue'\n\nimport GrButton from '../GrButton/GrButton.vue'\nimport { useAnnouncer } from '../../composables/useAnnouncer'\nimport { useGranularityTranslations } from '../../internal/granularityI18n'\nimport { useGrComponentProp, useGrComponentSize } from '../GrConfigProvider/context'\n\nimport IconCheck from '~icons/lucide/check'\nimport IconCopy from '~icons/lucide/copy'\n\nimport { serializeCode } from './serializeCode'\nimport { tokenizeJson, type GrCodeToken } from './tokenizeJson'\nimport {\n codeBlockCopyClass,\n codeBlockGutterClass,\n codeBlockHookClass,\n codeBlockNowrapClass,\n codeBlockNumberedClass as numberedClass,\n codeBlockPaddings,\n codeBlockRootClass,\n codeBlockScrollClass,\n codeBlockSurfaceClass,\n codeBlockTextSizes,\n codeBlockWrapClass,\n codeTokenClass,\n} from './grCodeBlockStyles'\n\nimport type { GrComponentSize } from '../shared/sizes'\n\nexport type { GrCodeToken, GrCodeTokenKind } from './tokenizeJson'\n\n/** Язык подсветки. Кроме JSON компонент ничего не разбирает — и не должен. */\nexport type GrCodeBlockLanguage = 'json' | 'text'\n\n/**\n * Блок сырого текста или JSON: моноширинный, с подсветкой, номерами строк и\n * копированием в буфер.\n *\n * Показывает, а не редактирует и не сворачивает узлы. Свёртка по узлам — задача\n * `GrJsonViewer`, дерево выбора — `GrTree`.\n */\nexport interface GrCodeBlockProps {\n /** Строка или значение: объект сериализуется с отступом. */\n code: unknown\n language?: GrCodeBlockLanguage\n /** Высота, после которой включается вертикальный скролл. */\n maxHeight?: string | number\n /** Кнопка копирования. Без защищённого контекста не рисуется вовсе. */\n copyable?: boolean\n /** Переносить длинные строки вместо горизонтальной прокрутки. */\n wrap?: boolean\n lineNumbers?: boolean\n /** Имя области прокрутки. Безымянную скринридер объявляет просто «регион». */\n ariaLabel?: string\n size?: GrComponentSize\n}\n\nexport interface GrCodeBlockEmits {\n /** Текст скопирован. Тост показывает потребитель: у блока своего места для него нет. */\n (e: 'copy', code: string): void\n}\n\nconst props = withDefaults(defineProps<GrCodeBlockProps>(), {\n // Дефолты живут в резолверах ниже: Vue подставил бы свой раньше, чем компонент\n // заглянет в `GrConfigProvider`.\n language: 'json',\n maxHeight: undefined,\n copyable: undefined,\n wrap: undefined,\n lineNumbers: undefined,\n ariaLabel: undefined,\n size: undefined,\n})\n\nconst emit = defineEmits<GrCodeBlockEmits>()\n\nconst { t } = useGranularityTranslations()\nconst { announce } = useAnnouncer()\n\nconst resolvedSize = useGrComponentSize(() => props.size, { component: 'GrCodeBlock' })\nconst resolvedCopyable = useGrComponentProp('GrCodeBlock', 'copyable', () => props.copyable, true)\nconst resolvedWrap = useGrComponentProp('GrCodeBlock', 'wrap', () => props.wrap, false)\nconst resolvedLineNumbers = useGrComponentProp('GrCodeBlock', 'lineNumbers', () => props.lineNumbers, false)\n\n/** Единственный источник текста: он же рендерится, он же уходит в буфер. */\nconst source = computed(() => serializeCode(props.code))\n\n/**\n * Разбор идёт по строкам, а не по всему тексту: номер строки — CSS-счётчик, а\n * счётчику нужен элемент на строку. JSON-строка перенос не содержит (он в ней\n * экранирован), поэтому построчная токенизация ничего не рвёт.\n */\nconst lines = computed<GrCodeToken[][]>(() => {\n const rows = source.value.split('\\n')\n\n if (props.language !== 'json') return rows.map(row => [{ text: row, kind: 'plain' as const }])\n\n return rows.map(row => tokenizeJson(row))\n})\n\n/**\n * Блок — скроллер по конструкции, а не по замеру. Замер здесь означал бы\n * мигающую остановку `Tab` на каждой смене данных и загрузке шрифта; ни один\n * компонент пакета так не делает.\n */\nconst isScroller = computed(() => props.maxHeight !== undefined || !resolvedWrap.value)\n\nconst scrollStyle = computed(() => {\n if (props.maxHeight === undefined) return undefined\n\n return { maxHeight: typeof props.maxHeight === 'number' ? `${props.maxHeight}px` : props.maxHeight }\n})\n\nconst preClass = computed(() => [\n codeBlockHookClass,\n codeBlockSurfaceClass,\n codeBlockPaddings[resolvedSize.value],\n codeBlockTextSizes[resolvedSize.value],\n resolvedWrap.value ? codeBlockWrapClass : codeBlockNowrapClass,\n isScroller.value ? codeBlockScrollClass : '',\n].filter(Boolean).join(' '))\n\n/**\n * Наличие буфера уточняется после монтирования: `navigator` в теле `setup` либо\n * роняет серверный рендер, либо расходится с ним. До этого момента кнопки нет —\n * ровно то же, что отдаёт сервер, поэтому гидрация совпадает.\n */\nconst canCopy = ref(false)\n\nonMounted(() => {\n canCopy.value = typeof navigator !== 'undefined' && typeof navigator.clipboard?.writeText === 'function'\n})\n\nconst showCopy = computed(() => resolvedCopyable.value && canCopy.value)\n\nconst copied = ref(false)\nlet copiedTimer: number | null = null\n\nfunction resetCopiedTimer(): void {\n if (copiedTimer !== null) {\n clearTimeout(copiedTimer)\n copiedTimer = null\n }\n}\n\nonBeforeUnmount(resetCopiedTimer)\n\nasync function copy(): Promise<void> {\n try {\n // Копируется исходный текст, а не разметка: номера строк — CSS-счётчик,\n // а мягкие переносы принадлежат показу, и вставить их обратно нельзя.\n await navigator.clipboard.writeText(source.value)\n }\n catch {\n announce(t('gr.codeBlock.copyFailed', 'Could not copy code'))\n return\n }\n\n copied.value = true\n resetCopiedTimer()\n copiedTimer = window.setTimeout(() => {\n copied.value = false\n copiedTimer = null\n }, 1200)\n\n announce(t('gr.codeBlock.copied', 'Code copied'))\n emit('copy', source.value)\n}\n\nconst copyLabel = computed(() => (\n copied.value ? t('gr.codeBlock.copied', 'Code copied') : t('gr.codeBlock.copy', 'Copy code')\n))\n</script>\n\n<template>\n <div data-gr-code-block :class=\"[codeBlockRootClass, showCopy ? codeBlockGutterClass : '']\">\n <GrButton\n v-if=\"showCopy\"\n data-gr-code-block-copy\n variant=\"ghost\"\n size=\"xs\"\n square\n :class=\"codeBlockCopyClass\"\n :aria-label=\"copyLabel\"\n :title=\"copyLabel\"\n @click=\"copy\"\n >\n <component :is=\"copied ? IconCheck : IconCopy\" class=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n </GrButton>\n\n <!--\n Внутри `<pre>` пробелы значимы, и компилятор Vue их здесь не схлопывает:\n любой перенос между тегами стал бы пустой строкой в коде. Поэтому\n содержимое блока записано без переносов — строки разделяет `display: block`\n у `.gr-code-block__line`, а не текстовый `\\n`.\n -->\n <pre\n data-gr-code-block-scroll\n :class=\"[preClass, resolvedLineNumbers ? numberedClass : '']\"\n :style=\"scrollStyle\"\n :tabindex=\"isScroller ? 0 : undefined\"\n :role=\"ariaLabel ? 'region' : undefined\"\n :aria-label=\"ariaLabel\"\n ><code data-gr-code-block-code><span v-for=\"(tokens, index) in lines\" :key=\"index\" data-gr-code-block-line class=\"gr-code-block__line\"><span v-for=\"(token, tokenIndex) in tokens\" :key=\"tokenIndex\" :class=\"codeTokenClass[token.kind]\">{{ token.text }}</span></span></code></pre>\n </div>\n</template>\n\n<style>\n/*\n * Номер строки — CSS-счётчик, а не текст в разметке. Разница не косметическая:\n * узел со `<span>2</span>` попадает в выделение мышью, и в буфер уезжает то,\n * что нельзя вставить обратно как код. У `::before` содержимого в DOM нет.\n *\n * Стиль глобальный, а не scoped: правило адресует псевдоэлемент строки, и\n * scoped-атрибут пришлось бы вешать на каждый из них.\n */\n:where(.gr-code-block__line) {\n display: block;\n}\n\n:where(.gr-code-block--numbered) {\n counter-reset: gr-code-line;\n}\n\n/*\n * Висячий отступ: строка сдвинута на ширину колонки номеров, а первая строка\n * возвращена назад отрицательным `text-indent` — туда и встаёт номер. Без этого\n * перенесённая при `wrap` строка начиналась бы под номером, а не под кодом.\n */\n:where(.gr-code-block--numbered .gr-code-block__line) {\n padding-left: calc(var(--gr-code-block-line-number-width, 2.5em) + 1em);\n text-indent: calc(-1 * (var(--gr-code-block-line-number-width, 2.5em) + 1em));\n}\n\n:where(.gr-code-block--numbered .gr-code-block__line)::before {\n counter-increment: gr-code-line;\n content: counter(gr-code-line);\n display: inline-block;\n width: var(--gr-code-block-line-number-width, 2.5em);\n margin-right: 1em;\n text-align: right;\n text-indent: 0;\n color: var(--gr-code-block-line-number, var(--gr-muted-fg));\n user-select: none;\n}\n</style>\n"],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { t as GrCodeBlock_default } from "./chunks/GrCodeBlock-CW3zY1ee.js";
|
|
2
|
+
import { n as grCodeBlockSafelist, t as grCodeBlockConfig } from "../../chunks/config-B_qi4Fma2.js";
|
|
3
|
+
export { GrCodeBlock_default as GrCodeBlock, GrCodeBlock_default as default, grCodeBlockConfig, grCodeBlockSafelist };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:where(.gr-code-block__line){display:block}:where(.gr-code-block--numbered){counter-reset:gr-code-line}:where(.gr-code-block--numbered .gr-code-block__line){padding-left:calc(var(--gr-code-block-line-number-width,2.5em) + 1em);text-indent:calc(-1 * (var(--gr-code-block-line-number-width,2.5em) + 1em))}:where(.gr-code-block--numbered .gr-code-block__line):before{counter-increment:gr-code-line;content:counter(gr-code-line);width:var(--gr-code-block-line-number-width,2.5em);text-align:right;text-indent:0;color:var(--gr-code-block-line-number,var(--gr-muted-fg));user-select:none;margin-right:1em;display:inline-block}
|
|
@@ -2,9 +2,9 @@ import { a as useGrComponentSize, i as useGrComponentProp } from "../../../chunk
|
|
|
2
2
|
import { n as useGranularityTranslations } from "../../../chunks/granularityI18n-BC5zsj_d.js";
|
|
3
3
|
import { t as GrIcon_default } from "../../GrIcon/chunks/GrIcon-bQwtZtYT.js";
|
|
4
4
|
import { t as chevron_down_default } from "../../../chunks/chevron-down-CQS2OG_s.js";
|
|
5
|
-
import { t as GrCard_default } from "../../GrCard/chunks/GrCard-
|
|
5
|
+
import { t as GrCard_default } from "../../GrCard/chunks/GrCard-Bc7nRfbe.js";
|
|
6
6
|
import { n as hasMeaningfulSlotContent } from "../../../chunks/slotNodes-DxNXpC7v.js";
|
|
7
|
-
import { a as grCollapseBodyClass, c as grCollapseHeaderClass, i as collapseExtraPaddings, l as grCollapseRowClass, o as grCollapseChevronClass, r as collapseChevronSizes, s as grCollapseEmptyClass, u as grCollapseTitleClass } from "../../../chunks/config-
|
|
7
|
+
import { a as grCollapseBodyClass, c as grCollapseHeaderClass, i as collapseExtraPaddings, l as grCollapseRowClass, o as grCollapseChevronClass, r as collapseChevronSizes, s as grCollapseEmptyClass, u as grCollapseTitleClass } from "../../../chunks/config-DU2DNSRx.js";
|
|
8
8
|
import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, inject, normalizeClass, openBlock, provide, ref, renderSlot, resolveDynamicComponent, toDisplayString, unref, useId, useSlots, withCtx } from "vue";
|
|
9
9
|
//#region src/components/GrCollapse/grCollapseContext.ts
|
|
10
10
|
var GR_COLLAPSE_CONTEXT = Symbol("GR_COLLAPSE_CONTEXT");
|