@mk-kit/ui 0.47.0 → 0.49.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/README.md +16 -7
- package/fesm2022/mk-kit-ui-core.mjs +9 -380
- package/fesm2022/mk-kit-ui-core.mjs.map +1 -1
- package/fesm2022/mk-kit-ui-data.mjs +6 -842
- package/fesm2022/mk-kit-ui-data.mjs.map +1 -1
- package/fesm2022/mk-kit-ui-datetime.mjs +4 -247
- package/fesm2022/mk-kit-ui-datetime.mjs.map +1 -1
- package/fesm2022/mk-kit-ui-locales-de.mjs +494 -0
- package/fesm2022/mk-kit-ui-locales-de.mjs.map +1 -0
- package/fesm2022/mk-kit-ui-locales-es.mjs +494 -0
- package/fesm2022/mk-kit-ui-locales-es.mjs.map +1 -0
- package/fesm2022/mk-kit-ui-locales-fr.mjs +495 -0
- package/fesm2022/mk-kit-ui-locales-fr.mjs.map +1 -0
- package/fesm2022/mk-kit-ui-locales-uk.mjs +503 -0
- package/fesm2022/mk-kit-ui-locales-uk.mjs.map +1 -0
- package/package.json +18 -1
- package/types/mk-kit-ui-core.d.ts +7 -162
- package/types/mk-kit-ui-data.d.ts +6 -173
- package/types/mk-kit-ui-datetime.d.ts +5 -77
- package/types/mk-kit-ui-locales-de.d.ts +40 -0
- package/types/mk-kit-ui-locales-es.d.ts +40 -0
- package/types/mk-kit-ui-locales-fr.d.ts +41 -0
- package/types/mk-kit-ui-locales-uk.d.ts +42 -0
|
@@ -5,6 +5,8 @@ import { mkUniqueId, MK_I18N, MkFieldContext, mkInjectFieldTouched, mkHighlight
|
|
|
5
5
|
import { MkIcon } from '@mk-kit/ui/icon';
|
|
6
6
|
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
7
7
|
import { MkCopyToClipboard } from '@mk-kit/ui/directives';
|
|
8
|
+
import { mkComputeDiff, mkDiffStats, mkStripAnsi, mkParseAnsi, mkRenderMarkdown, mkParseMarkdown } from '@mk-kit/core';
|
|
9
|
+
export { mkComputeDiff, mkDiffStats, mkParseAnsi, mkParseMarkdown, mkRenderMarkdown, mkStripAnsi } from '@mk-kit/core';
|
|
8
10
|
import { mkMoveItemInArray, MkDropList, MkDrag } from '@mk-kit/ui/dnd';
|
|
9
11
|
|
|
10
12
|
/**
|
|
@@ -4781,187 +4783,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
|
|
|
4781
4783
|
args: [{ selector: 'mk-carousel', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'mk-carousel' }, template: "<div\n class=\"mk-carousel__viewport\"\n role=\"region\"\n aria-roledescription=\"carousel\"\n [attr.aria-label]=\"ariaLabel()\"\n tabindex=\"0\"\n (keydown)=\"onKeydown($event)\"\n (mouseenter)=\"pause()\"\n (mouseleave)=\"resume()\"\n (focusin)=\"pause()\"\n (focusout)=\"resume()\"\n (pointerdown)=\"onPointerDown($event)\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerup)=\"onPointerUp($event)\"\n (pointercancel)=\"onPointerUp($event)\"\n>\n @if (autoplay()) {\n <button\n type=\"button\"\n class=\"mk-carousel__playpause\"\n [attr.aria-label]=\"userPaused() ? i18n.playSlideshow : i18n.pauseSlideshow\"\n [attr.aria-pressed]=\"userPaused()\"\n (click)=\"toggleUserPause()\"\n >\n <span aria-hidden=\"true\">{{ userPaused() ? '\u25B6' : '\u23F8' }}</span>\n </button>\n }\n <div\n class=\"mk-carousel__track\"\n [class.mk-carousel__track--dragging]=\"dragging()\"\n [style.transform]=\"trackTransform()\"\n >\n <ng-content />\n </div>\n\n @if (showArrows() && count() > 1) {\n <button\n type=\"button\"\n class=\"mk-carousel__arrow mk-carousel__arrow--prev\"\n [attr.aria-label]=\"i18n.previousSlide\"\n (click)=\"prev()\"\n >\n <span aria-hidden=\"true\">\u2039</span>\n </button>\n <button\n type=\"button\"\n class=\"mk-carousel__arrow mk-carousel__arrow--next\"\n [attr.aria-label]=\"i18n.nextSlide\"\n (click)=\"next()\"\n >\n <span aria-hidden=\"true\">\u203A</span>\n </button>\n }\n</div>\n\n@if (showDots() && count() > 1) {\n <div class=\"mk-carousel__dots\">\n @for (dot of dots(); track dot) {\n <button\n type=\"button\"\n class=\"mk-carousel__dot\"\n [class.mk-carousel__dot--active]=\"dot === index()\"\n [attr.aria-current]=\"dot === index() || null\"\n [attr.aria-label]=\"i18n.goToSlide(dot + 1)\"\n (click)=\"goTo(dot)\"\n ></button>\n }\n </div>\n}\n\n<div class=\"mk-visually-hidden\" [attr.aria-live]=\"liveMode()\">{{ liveText() }}</div>\n", styles: ["@charset \"UTF-8\";:host{display:block;font-family:var(--mk-font-sans)}.mk-carousel__viewport{position:relative;overflow:hidden;border-radius:var(--mk-radius-md);touch-action:pan-y}.mk-carousel__viewport:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:var(--mk-focus-ring-offset)}.mk-carousel__track{display:flex;transition:transform var(--mk-duration-normal, .24s) var(--mk-ease-standard)}.mk-carousel__track--dragging{transition:none}:host ::ng-deep .mk-carousel__slide{flex:0 0 100%;min-width:0;box-sizing:border-box}.mk-carousel__playpause{position:absolute;top:var(--mk-space-2);inset-inline-start:var(--mk-space-2);z-index:1;display:grid;place-items:center;width:2rem;height:2rem;padding:0;font-size:var(--mk-font-size-sm);line-height:1;color:var(--mk-text);background-color:var(--mk-surface);border:var(--mk-border-width) solid var(--mk-border);border-radius:var(--mk-radius-circle);box-shadow:var(--mk-shadow-sm);cursor:pointer;transition:background-color var(--mk-duration-fast) var(--mk-ease-standard)}.mk-carousel__playpause:hover{background-color:var(--mk-surface-2)}.mk-carousel__playpause:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:var(--mk-focus-ring-offset)}.mk-carousel__arrow{position:absolute;top:50%;transform:translateY(-50%);display:grid;place-items:center;width:2rem;height:2rem;font-size:var(--mk-font-size-lg);line-height:1;color:var(--mk-text);background-color:var(--mk-surface);border:var(--mk-border-width) solid var(--mk-border);border-radius:var(--mk-radius-circle);box-shadow:var(--mk-shadow-sm);cursor:pointer;transition:background-color var(--mk-duration-fast) var(--mk-ease-standard)}.mk-carousel__arrow:hover{background-color:var(--mk-surface-2)}.mk-carousel__arrow:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:var(--mk-focus-ring-offset)}.mk-carousel__arrow--prev{inset-inline-start:var(--mk-space-2)}.mk-carousel__arrow--next{inset-inline-end:var(--mk-space-2)}.mk-carousel__arrow:dir(rtl) span{display:inline-block;transform:scaleX(-1)}.mk-carousel__dots{display:flex;justify-content:center;gap:var(--mk-space-2);margin-top:var(--mk-space-2)}.mk-carousel__dot{width:.5rem;height:.5rem;padding:0;background-color:var(--mk-border-strong);border:none;border-radius:var(--mk-radius-circle);cursor:pointer;transition:background-color var(--mk-duration-fast) var(--mk-ease-standard),transform var(--mk-duration-fast) var(--mk-ease-standard)}.mk-carousel__dot:hover{background-color:var(--mk-text-muted)}.mk-carousel__dot:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:var(--mk-focus-ring-offset)}.mk-carousel__dot--active{background-color:var(--mk-primary);transform:scale(1.25)}@media(prefers-reduced-motion:reduce){.mk-carousel__track,.mk-carousel__arrow,.mk-carousel__dot{transition:none}}\n"] }]
|
|
4782
4784
|
}], ctorParameters: () => [], propDecorators: { slides: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => MkCarouselSlide), { isSignal: true }] }], index: [{ type: i0.Input, args: [{ isSignal: true, alias: "index", required: false }] }, { type: i0.Output, args: ["indexChange"] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], loop: [{ type: i0.Input, args: [{ isSignal: true, alias: "loop", required: false }] }], showDots: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDots", required: false }] }], showArrows: [{ type: i0.Input, args: [{ isSignal: true, alias: "showArrows", required: false }] }], autoplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoplay", required: false }] }], interval: [{ type: i0.Input, args: [{ isSignal: true, alias: "interval", required: false }] }], userPaused: [{ type: i0.Input, args: [{ isSignal: true, alias: "userPaused", required: false }] }, { type: i0.Output, args: ["userPausedChange"] }] } });
|
|
4783
4785
|
|
|
4784
|
-
/**
|
|
4785
|
-
* Dependency-free text diff for {@link MkDiff} — an LCS line diff with optional
|
|
4786
|
-
* intra-line word highlighting. Pure and SSR-safe (no DOM). Suited to revision
|
|
4787
|
-
* comparison ("what changed between save N and N+1").
|
|
4788
|
-
*/
|
|
4789
|
-
/**
|
|
4790
|
-
* The largest DP matrix lcsOps will allocate (cells). Above this the diff
|
|
4791
|
-
* falls back to a plain delete-all/insert-all block instead of freezing the
|
|
4792
|
-
* tab on huge inputs (an n×m matrix of two 10k-line files is 100M cells).
|
|
4793
|
-
*/
|
|
4794
|
-
const MAX_LCS_CELLS = 4_000_000;
|
|
4795
|
-
/** LCS diff of two sequences (dynamic programming + backtrack). */
|
|
4796
|
-
function lcsOps(a, b, eq) {
|
|
4797
|
-
// Trim the common prefix/suffix first — the usual case for revisions is a
|
|
4798
|
-
// small edit inside a large document, which shrinks the matrix massively.
|
|
4799
|
-
let lead = 0;
|
|
4800
|
-
const maxLead = Math.min(a.length, b.length);
|
|
4801
|
-
while (lead < maxLead && eq(a[lead], b[lead]))
|
|
4802
|
-
lead++;
|
|
4803
|
-
let trail = 0;
|
|
4804
|
-
while (trail < maxLead - lead &&
|
|
4805
|
-
eq(a[a.length - 1 - trail], b[b.length - 1 - trail])) {
|
|
4806
|
-
trail++;
|
|
4807
|
-
}
|
|
4808
|
-
if (lead > 0 || trail > 0) {
|
|
4809
|
-
const head = a.slice(0, lead).map((x, k) => ({
|
|
4810
|
-
op: 'equal',
|
|
4811
|
-
a: x,
|
|
4812
|
-
b: b[k],
|
|
4813
|
-
}));
|
|
4814
|
-
const tail = a.slice(a.length - trail).map((x, k) => ({
|
|
4815
|
-
op: 'equal',
|
|
4816
|
-
a: x,
|
|
4817
|
-
b: b[b.length - trail + k],
|
|
4818
|
-
}));
|
|
4819
|
-
return [
|
|
4820
|
-
...head,
|
|
4821
|
-
...lcsCore(a.slice(lead, a.length - trail), b.slice(lead, b.length - trail), eq),
|
|
4822
|
-
...tail,
|
|
4823
|
-
];
|
|
4824
|
-
}
|
|
4825
|
-
return lcsCore(a, b, eq);
|
|
4826
|
-
}
|
|
4827
|
-
function lcsCore(a, b, eq) {
|
|
4828
|
-
const n = a.length;
|
|
4829
|
-
const m = b.length;
|
|
4830
|
-
if (n === 0 && m === 0)
|
|
4831
|
-
return [];
|
|
4832
|
-
// Guard against quadratic blow-up on huge, mostly-different inputs.
|
|
4833
|
-
if ((n + 1) * (m + 1) > MAX_LCS_CELLS) {
|
|
4834
|
-
return [
|
|
4835
|
-
...a.map((x) => ({ op: 'delete', a: x })),
|
|
4836
|
-
...b.map((x) => ({ op: 'insert', b: x })),
|
|
4837
|
-
];
|
|
4838
|
-
}
|
|
4839
|
-
// dp[i][j] = LCS length of a[i:] and b[j:].
|
|
4840
|
-
const dp = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));
|
|
4841
|
-
for (let i = n - 1; i >= 0; i--) {
|
|
4842
|
-
for (let j = m - 1; j >= 0; j--) {
|
|
4843
|
-
dp[i][j] = eq(a[i], b[j])
|
|
4844
|
-
? dp[i + 1][j + 1] + 1
|
|
4845
|
-
: Math.max(dp[i + 1][j], dp[i][j + 1]);
|
|
4846
|
-
}
|
|
4847
|
-
}
|
|
4848
|
-
const ops = [];
|
|
4849
|
-
let i = 0;
|
|
4850
|
-
let j = 0;
|
|
4851
|
-
while (i < n && j < m) {
|
|
4852
|
-
if (eq(a[i], b[j])) {
|
|
4853
|
-
ops.push({ op: 'equal', a: a[i], b: b[j] });
|
|
4854
|
-
i++;
|
|
4855
|
-
j++;
|
|
4856
|
-
}
|
|
4857
|
-
else if (dp[i + 1][j] >= dp[i][j + 1]) {
|
|
4858
|
-
ops.push({ op: 'delete', a: a[i] });
|
|
4859
|
-
i++;
|
|
4860
|
-
}
|
|
4861
|
-
else {
|
|
4862
|
-
ops.push({ op: 'insert', b: b[j] });
|
|
4863
|
-
j++;
|
|
4864
|
-
}
|
|
4865
|
-
}
|
|
4866
|
-
while (i < n)
|
|
4867
|
-
ops.push({ op: 'delete', a: a[i++] });
|
|
4868
|
-
while (j < m)
|
|
4869
|
-
ops.push({ op: 'insert', b: b[j++] });
|
|
4870
|
-
return ops;
|
|
4871
|
-
}
|
|
4872
|
-
/** Split a line into word/whitespace tokens (separators preserved). */
|
|
4873
|
-
function tokenize(line) {
|
|
4874
|
-
return line.split(/(\s+)/).filter((t) => t.length > 0);
|
|
4875
|
-
}
|
|
4876
|
-
/** Word-level segments for a paired (deleted, inserted) line. */
|
|
4877
|
-
function wordSegments(before, after) {
|
|
4878
|
-
const ops = lcsOps(tokenize(before), tokenize(after), (x, y) => x === y);
|
|
4879
|
-
const bSeg = [];
|
|
4880
|
-
const aSeg = [];
|
|
4881
|
-
for (const o of ops) {
|
|
4882
|
-
if (o.op === 'equal') {
|
|
4883
|
-
bSeg.push({ text: o.a, changed: false });
|
|
4884
|
-
aSeg.push({ text: o.b, changed: false });
|
|
4885
|
-
}
|
|
4886
|
-
else if (o.op === 'delete') {
|
|
4887
|
-
bSeg.push({ text: o.a, changed: true });
|
|
4888
|
-
}
|
|
4889
|
-
else {
|
|
4890
|
-
aSeg.push({ text: o.b, changed: true });
|
|
4891
|
-
}
|
|
4892
|
-
}
|
|
4893
|
-
return { before: bSeg, after: aSeg };
|
|
4894
|
-
}
|
|
4895
|
-
/** Pair adjacent delete/insert runs and attach word segments to each row. */
|
|
4896
|
-
function addWordHighlights(rows) {
|
|
4897
|
-
let i = 0;
|
|
4898
|
-
while (i < rows.length) {
|
|
4899
|
-
if (rows[i].op !== 'delete') {
|
|
4900
|
-
i++;
|
|
4901
|
-
continue;
|
|
4902
|
-
}
|
|
4903
|
-
let d = i;
|
|
4904
|
-
while (d < rows.length && rows[d].op === 'delete')
|
|
4905
|
-
d++;
|
|
4906
|
-
let s = d;
|
|
4907
|
-
while (s < rows.length && rows[s].op === 'insert')
|
|
4908
|
-
s++;
|
|
4909
|
-
const deletes = rows.slice(i, d);
|
|
4910
|
-
const inserts = rows.slice(d, s);
|
|
4911
|
-
const pairs = Math.min(deletes.length, inserts.length);
|
|
4912
|
-
for (let k = 0; k < pairs; k++) {
|
|
4913
|
-
const seg = wordSegments(deletes[k].text, inserts[k].text);
|
|
4914
|
-
deletes[k].segments = seg.before;
|
|
4915
|
-
inserts[k].segments = seg.after;
|
|
4916
|
-
}
|
|
4917
|
-
i = s;
|
|
4918
|
-
}
|
|
4919
|
-
}
|
|
4920
|
-
/**
|
|
4921
|
-
* Compute a line diff between `before` and `after`. Returns one {@link MkDiffRow}
|
|
4922
|
-
* per line in document order, with `equal` / `insert` / `delete` ops and 1-based
|
|
4923
|
-
* before/after line numbers. With `wordHighlight` (default true) changed lines
|
|
4924
|
-
* also carry word-level `segments`.
|
|
4925
|
-
*/
|
|
4926
|
-
function mkComputeDiff(before, after, options = {}) {
|
|
4927
|
-
const { wordHighlight = true, ignoreTrailingWhitespace = false } = options;
|
|
4928
|
-
const norm = (s) => ignoreTrailingWhitespace ? s.replace(/[ \t]+$/, '') : s;
|
|
4929
|
-
const beforeLines = String(before ?? '').split('\n');
|
|
4930
|
-
const afterLines = String(after ?? '').split('\n');
|
|
4931
|
-
const ops = lcsOps(beforeLines, afterLines, (x, y) => norm(x) === norm(y));
|
|
4932
|
-
const rows = [];
|
|
4933
|
-
let beforeNo = 0;
|
|
4934
|
-
let afterNo = 0;
|
|
4935
|
-
for (const o of ops) {
|
|
4936
|
-
if (o.op === 'equal') {
|
|
4937
|
-
rows.push({ op: 'equal', text: o.a, beforeNo: ++beforeNo, afterNo: ++afterNo });
|
|
4938
|
-
}
|
|
4939
|
-
else if (o.op === 'delete') {
|
|
4940
|
-
rows.push({ op: 'delete', text: o.a, beforeNo: ++beforeNo, afterNo: null });
|
|
4941
|
-
}
|
|
4942
|
-
else {
|
|
4943
|
-
rows.push({ op: 'insert', text: o.b, beforeNo: null, afterNo: ++afterNo });
|
|
4944
|
-
}
|
|
4945
|
-
}
|
|
4946
|
-
if (wordHighlight)
|
|
4947
|
-
addWordHighlights(rows);
|
|
4948
|
-
return rows;
|
|
4949
|
-
}
|
|
4950
|
-
/** Summary counts (added / removed / unchanged lines) for a diff. */
|
|
4951
|
-
function mkDiffStats(rows) {
|
|
4952
|
-
let added = 0;
|
|
4953
|
-
let removed = 0;
|
|
4954
|
-
let unchanged = 0;
|
|
4955
|
-
for (const r of rows) {
|
|
4956
|
-
if (r.op === 'insert')
|
|
4957
|
-
added++;
|
|
4958
|
-
else if (r.op === 'delete')
|
|
4959
|
-
removed++;
|
|
4960
|
-
else
|
|
4961
|
-
unchanged++;
|
|
4962
|
-
}
|
|
4963
|
-
return { added, removed, unchanged };
|
|
4964
|
-
}
|
|
4786
|
+
/** Delegates to `@mk-kit/core` — the exported names are unchanged. */
|
|
4965
4787
|
|
|
4966
4788
|
/**
|
|
4967
4789
|
* Diff — a text comparison view for revisions (before ⇄ after). Computes an LCS
|
|
@@ -5939,153 +5761,7 @@ function collectToDepth(root, maxDepth) {
|
|
|
5939
5761
|
return paths;
|
|
5940
5762
|
}
|
|
5941
5763
|
|
|
5942
|
-
/**
|
|
5943
|
-
* Minimal ANSI SGR parser for {@link MkLogViewer}.
|
|
5944
|
-
*
|
|
5945
|
-
* Understands the SGR (`ESC[…m`) subset that matters for log output — reset
|
|
5946
|
-
* (0), bold (1), italic (3), underline (4), the 22/23/24 "off" codes, the 8
|
|
5947
|
-
* standard + 8 bright foreground colours (30–37 / 90–97, 39 reset) and the
|
|
5948
|
-
* matching backgrounds (40–47 / 100–107, 49 reset). Extended-colour
|
|
5949
|
-
* introducers (38/48;5;… and 38/48;2;r;g;b) are consumed so their arguments
|
|
5950
|
-
* are never misread as other codes, but map to "no colour" (the theme has no
|
|
5951
|
-
* 256-colour palette). Every other escape sequence — cursor movement, erase,
|
|
5952
|
-
* OSC titles, single-character escapes — is stripped rather than rendered as
|
|
5953
|
-
* garbage.
|
|
5954
|
-
*
|
|
5955
|
-
* Colours are emitted as CSS class names (`mk-ansi--fg-red`,
|
|
5956
|
-
* `mk-ansi--bg-bright-blue`, `mk-ansi--bold`, …) themed in
|
|
5957
|
-
* `log-viewer.scss`, not as raw terminal colours.
|
|
5958
|
-
*/
|
|
5959
|
-
/** SGR colour slots 0–7, shared by fg/bg and their bright variants. */
|
|
5960
|
-
const COLOR_NAMES = [
|
|
5961
|
-
'black',
|
|
5962
|
-
'red',
|
|
5963
|
-
'green',
|
|
5964
|
-
'yellow',
|
|
5965
|
-
'blue',
|
|
5966
|
-
'magenta',
|
|
5967
|
-
'cyan',
|
|
5968
|
-
'white',
|
|
5969
|
-
];
|
|
5970
|
-
/**
|
|
5971
|
-
* Any ANSI escape sequence. Alternatives, in order: SGR (params captured),
|
|
5972
|
-
* any other CSI sequence, OSC (terminated by BEL or ST), and two-character
|
|
5973
|
-
* `ESC <letter>` escapes.
|
|
5974
|
-
*/
|
|
5975
|
-
const ANSI_SOURCE = '\\x1b(?:\\[([0-9;]*)m|\\[[0-9;?]*[ -/]*[@-~]|\\][^\\x07\\x1b]*(?:\\x07|\\x1b\\\\)?|[@-Z\\\\-_])';
|
|
5976
|
-
const EMPTY_CLASSES = [];
|
|
5977
|
-
function applySgr(params, s) {
|
|
5978
|
-
const codes = params.split(';').map((p) => (p === '' ? 0 : Number(p)));
|
|
5979
|
-
for (let i = 0; i < codes.length; i++) {
|
|
5980
|
-
const c = codes[i];
|
|
5981
|
-
if (c === 0) {
|
|
5982
|
-
s.bold = s.italic = s.underline = false;
|
|
5983
|
-
s.fg = s.bg = null;
|
|
5984
|
-
}
|
|
5985
|
-
else if (c === 1)
|
|
5986
|
-
s.bold = true;
|
|
5987
|
-
else if (c === 3)
|
|
5988
|
-
s.italic = true;
|
|
5989
|
-
else if (c === 4)
|
|
5990
|
-
s.underline = true;
|
|
5991
|
-
else if (c === 22)
|
|
5992
|
-
s.bold = false;
|
|
5993
|
-
else if (c === 23)
|
|
5994
|
-
s.italic = false;
|
|
5995
|
-
else if (c === 24)
|
|
5996
|
-
s.underline = false;
|
|
5997
|
-
else if (c >= 30 && c <= 37)
|
|
5998
|
-
s.fg = COLOR_NAMES[c - 30];
|
|
5999
|
-
else if (c >= 90 && c <= 97)
|
|
6000
|
-
s.fg = `bright-${COLOR_NAMES[c - 90]}`;
|
|
6001
|
-
else if (c === 39)
|
|
6002
|
-
s.fg = null;
|
|
6003
|
-
else if (c >= 40 && c <= 47)
|
|
6004
|
-
s.bg = COLOR_NAMES[c - 40];
|
|
6005
|
-
else if (c >= 100 && c <= 107)
|
|
6006
|
-
s.bg = `bright-${COLOR_NAMES[c - 100]}`;
|
|
6007
|
-
else if (c === 49)
|
|
6008
|
-
s.bg = null;
|
|
6009
|
-
else if (c === 38 || c === 48) {
|
|
6010
|
-
// Extended colour: consume the arguments, render as "no colour".
|
|
6011
|
-
const mode = codes[i + 1];
|
|
6012
|
-
if (mode === 5)
|
|
6013
|
-
i += 2;
|
|
6014
|
-
else if (mode === 2)
|
|
6015
|
-
i += 4;
|
|
6016
|
-
else
|
|
6017
|
-
i = codes.length;
|
|
6018
|
-
if (c === 38)
|
|
6019
|
-
s.fg = null;
|
|
6020
|
-
else
|
|
6021
|
-
s.bg = null;
|
|
6022
|
-
}
|
|
6023
|
-
// Any other SGR parameter is ignored.
|
|
6024
|
-
}
|
|
6025
|
-
}
|
|
6026
|
-
function classesFor(s) {
|
|
6027
|
-
if (!s.bold && !s.italic && !s.underline && !s.fg && !s.bg) {
|
|
6028
|
-
return EMPTY_CLASSES;
|
|
6029
|
-
}
|
|
6030
|
-
const classes = [];
|
|
6031
|
-
if (s.bold)
|
|
6032
|
-
classes.push('mk-ansi--bold');
|
|
6033
|
-
if (s.italic)
|
|
6034
|
-
classes.push('mk-ansi--italic');
|
|
6035
|
-
if (s.underline)
|
|
6036
|
-
classes.push('mk-ansi--underline');
|
|
6037
|
-
if (s.fg)
|
|
6038
|
-
classes.push(`mk-ansi--fg-${s.fg}`);
|
|
6039
|
-
if (s.bg)
|
|
6040
|
-
classes.push(`mk-ansi--bg-${s.bg}`);
|
|
6041
|
-
return classes;
|
|
6042
|
-
}
|
|
6043
|
-
function sameClasses(a, b) {
|
|
6044
|
-
return a.length === b.length && a.every((cls, i) => cls === b[i]);
|
|
6045
|
-
}
|
|
6046
|
-
/**
|
|
6047
|
-
* Parse one log line into styled spans. Pure — same input, same output.
|
|
6048
|
-
* Adjacent runs with identical styling are merged, so a plain line yields a
|
|
6049
|
-
* single span (or none when empty).
|
|
6050
|
-
*/
|
|
6051
|
-
function mkParseAnsi(line) {
|
|
6052
|
-
const spans = [];
|
|
6053
|
-
const state = {
|
|
6054
|
-
bold: false,
|
|
6055
|
-
italic: false,
|
|
6056
|
-
underline: false,
|
|
6057
|
-
fg: null,
|
|
6058
|
-
bg: null,
|
|
6059
|
-
};
|
|
6060
|
-
const re = new RegExp(ANSI_SOURCE, 'g');
|
|
6061
|
-
let last = 0;
|
|
6062
|
-
const flush = (end) => {
|
|
6063
|
-
if (end <= last)
|
|
6064
|
-
return;
|
|
6065
|
-
const text = line.slice(last, end);
|
|
6066
|
-
const classes = classesFor(state);
|
|
6067
|
-
const prev = spans[spans.length - 1];
|
|
6068
|
-
if (prev && sameClasses(prev.classes, classes)) {
|
|
6069
|
-
spans[spans.length - 1] = { text: prev.text + text, classes: prev.classes };
|
|
6070
|
-
}
|
|
6071
|
-
else {
|
|
6072
|
-
spans.push({ text, classes });
|
|
6073
|
-
}
|
|
6074
|
-
};
|
|
6075
|
-
let m;
|
|
6076
|
-
while ((m = re.exec(line))) {
|
|
6077
|
-
flush(m.index);
|
|
6078
|
-
last = m.index + m[0].length;
|
|
6079
|
-
if (m[1] !== undefined)
|
|
6080
|
-
applySgr(m[1], state);
|
|
6081
|
-
}
|
|
6082
|
-
flush(line.length);
|
|
6083
|
-
return spans;
|
|
6084
|
-
}
|
|
6085
|
-
/** Remove every ANSI escape sequence from a line (for copy / search). */
|
|
6086
|
-
function mkStripAnsi(line) {
|
|
6087
|
-
return line.replace(new RegExp(ANSI_SOURCE, 'g'), '');
|
|
6088
|
-
}
|
|
5764
|
+
/** Delegates to `@mk-kit/core` — the exported names are unchanged. */
|
|
6089
5765
|
|
|
6090
5766
|
/** Rows rendered above/below the viewport to smooth fast scrolls. */
|
|
6091
5767
|
const OVERSCAN = 6;
|
|
@@ -6359,519 +6035,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
|
|
|
6359
6035
|
args: [{ selector: 'mk-log-viewer', exportAs: 'mkLogViewer', changeDetection: ChangeDetectionStrategy.OnPush, imports: [MkCopyToClipboard], host: { class: 'mk-log-viewer' }, template: "@if (!hideToolbar()) {\n <div class=\"mk-log-viewer__toolbar\">\n <ng-content />\n <span class=\"mk-log-viewer__toolbar-spacer\"></span>\n <button\n type=\"button\"\n class=\"mk-log-viewer__tool\"\n [class.mk-log-viewer__tool--active]=\"wrap()\"\n [attr.aria-pressed]=\"wrap()\"\n (click)=\"wrap.set(!wrap())\"\n >\n {{ i18n.logWrapLines }}\n </button>\n <button\n type=\"button\"\n class=\"mk-log-viewer__tool\"\n [mkCopyToClipboard]=\"allText()\"\n #copier=\"mkCopyToClipboard\"\n >\n {{ copier.justCopied() ? '\u2713 ' + i18n.logCopyAll : i18n.logCopyAll }}\n </button>\n </div>\n}\n\n<div class=\"mk-log-viewer__body\">\n <!--\n role=\"log\" makes additions politely announced without re-reading the whole\n buffer; tabindex=\"0\" keeps the overflowing region keyboard-scrollable.\n Tokens are emitted on one line: the rows render `white-space: pre`, so any\n inter-element template whitespace would corrupt log alignment.\n -->\n <div\n #viewport\n class=\"mk-log-viewer__viewport\"\n role=\"log\"\n tabindex=\"0\"\n [attr.aria-label]=\"ariaLabel()\"\n (scroll)=\"onScroll($event)\"\n >\n @if (wrap()) {\n <div class=\"mk-log-viewer__lines mk-log-viewer__lines--wrap\">\n @for (line of wrappedLines(); track line.index) {\n <div class=\"mk-log-viewer__line\">@for (t of line.tokens; track $index) {@if (t.mark) {<mark class=\"mk-log-viewer__match {{ t.cls }}\">{{ t.text }}</mark>} @else {<span class=\"{{ t.cls }}\">{{ t.text }}</span>}}</div>\n }\n </div>\n } @else {\n <div class=\"mk-log-viewer__spacer\" [style.height.px]=\"totalHeight()\">\n <div\n class=\"mk-log-viewer__window\"\n [style.transform]=\"'translateY(' + offset() + 'px)'\"\n >\n @for (line of visibleLines(); track line.index) {\n <div\n class=\"mk-log-viewer__line\"\n [style.height.px]=\"itemHeight()\"\n [style.line-height.px]=\"itemHeight()\"\n >@for (t of line.tokens; track $index) {@if (t.mark) {<mark class=\"mk-log-viewer__match {{ t.cls }}\">{{ t.text }}</mark>} @else {<span class=\"{{ t.cls }}\">{{ t.text }}</span>}}</div>\n }\n </div>\n </div>\n }\n </div>\n\n @if (!follow()) {\n <button\n type=\"button\"\n class=\"mk-log-viewer__follow\"\n (click)=\"resumeFollow()\"\n >\n {{ i18n.logFollow }} <span aria-hidden=\"true\">\u2193</span>\n </button>\n }\n</div>\n\n@if (query()) {\n <span class=\"mk-visually-hidden\" aria-live=\"polite\">\n {{ i18n.resultsCount(matchCount()) }}\n </span>\n}\n", styles: ["@charset \"UTF-8\";:host{--_fs: var(--mk-font-size-sm);display:flex;flex-direction:column;height:var(--mk-log-viewer-height, 20rem);overflow:hidden;background-color:var(--mk-log-viewer-bg, var(--mk-code-bg, var(--mk-surface-2)));border:var(--mk-border-width) solid var(--mk-border);border-radius:var(--mk-radius-md);font-family:var(--mk-font-mono)}.mk-log-viewer__toolbar{display:flex;align-items:center;gap:var(--mk-space-2);flex:none;padding:var(--mk-space-1) var(--mk-space-2);background-color:var(--mk-surface-2);border-bottom:var(--mk-border-width) solid var(--mk-border-subtle);font-family:var(--mk-font-sans)}.mk-log-viewer__toolbar-spacer{flex:1 1 auto}.mk-log-viewer__tool{flex:none;padding:var(--mk-space-1) var(--mk-space-2);font-family:var(--mk-font-sans);font-size:var(--mk-font-size-xs);color:var(--mk-text-muted);background:transparent;border:var(--mk-border-width) solid var(--mk-border);border-radius:var(--mk-radius-sm);cursor:pointer;transition:background-color var(--mk-duration-fast) var(--mk-ease-standard),color var(--mk-duration-fast) var(--mk-ease-standard)}.mk-log-viewer__tool:hover{background-color:var(--mk-hover-overlay);color:var(--mk-text)}.mk-log-viewer__tool:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:var(--mk-focus-ring-offset)}.mk-log-viewer__tool--active{color:var(--mk-primary);border-color:var(--mk-primary)}.mk-log-viewer__body{position:relative;flex:1 1 auto;min-height:0}.mk-log-viewer__viewport{height:100%;overflow:auto;direction:ltr;padding:var(--mk-space-2) var(--mk-space-3);font-size:var(--_fs);color:var(--mk-text)}.mk-log-viewer__viewport:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(-1 * var(--mk-focus-ring-width))}.mk-log-viewer__spacer{position:relative}.mk-log-viewer__window{position:absolute;top:0;left:0;min-width:100%;width:max-content;will-change:transform}.mk-log-viewer__line{white-space:pre}.mk-log-viewer__lines--wrap .mk-log-viewer__line{white-space:pre-wrap;overflow-wrap:break-word;word-break:break-word;line-height:1.5}.mk-log-viewer__match{background-color:var(--mk-warning);color:var(--mk-warning-contrast);border-radius:2px}.mk-log-viewer__follow{position:absolute;bottom:var(--mk-space-3);left:50%;transform:translate(-50%);padding:var(--mk-space-1) var(--mk-space-3);font-family:var(--mk-font-sans);font-size:var(--mk-font-size-xs);font-weight:var(--mk-font-weight-medium);color:var(--mk-primary-contrast);background-color:var(--mk-primary);border:none;border-radius:var(--mk-radius-pill);box-shadow:var(--mk-shadow-md);cursor:pointer}.mk-log-viewer__follow:hover{background-color:var(--mk-primary-hover)}.mk-log-viewer__follow:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:var(--mk-focus-ring-offset)}.mk-ansi--bold{font-weight:var(--mk-font-weight-bold)}.mk-ansi--italic{font-style:italic}.mk-ansi--underline{text-decoration:underline}.mk-ansi--fg-black,.mk-ansi--fg-bright-black{color:var(--mk-text-muted)}.mk-ansi--fg-red,.mk-ansi--fg-bright-red{color:var(--mk-danger-text)}.mk-ansi--fg-green,.mk-ansi--fg-bright-green{color:var(--mk-success)}.mk-ansi--fg-yellow,.mk-ansi--fg-bright-yellow{color:var(--mk-warning)}.mk-ansi--fg-blue,.mk-ansi--fg-bright-blue{color:var(--mk-info)}.mk-ansi--fg-magenta,.mk-ansi--fg-bright-magenta{color:var(--mk-chart-4)}.mk-ansi--fg-cyan,.mk-ansi--fg-bright-cyan{color:var(--mk-chart-6)}.mk-ansi--fg-white,.mk-ansi--fg-bright-white{color:var(--mk-text)}.mk-ansi--bg-black,.mk-ansi--bg-bright-black{background-color:var(--mk-surface-3)}.mk-ansi--bg-red,.mk-ansi--bg-bright-red{background-color:var(--mk-danger-subtle)}.mk-ansi--bg-green,.mk-ansi--bg-bright-green{background-color:var(--mk-success-subtle)}.mk-ansi--bg-yellow,.mk-ansi--bg-bright-yellow{background-color:var(--mk-warning-subtle)}.mk-ansi--bg-blue,.mk-ansi--bg-bright-blue{background-color:var(--mk-info-subtle)}.mk-ansi--bg-magenta,.mk-ansi--bg-bright-magenta{background-color:color-mix(in srgb,var(--mk-chart-4) 18%,transparent)}.mk-ansi--bg-cyan,.mk-ansi--bg-bright-cyan{background-color:color-mix(in srgb,var(--mk-chart-6) 18%,transparent)}.mk-ansi--bg-white,.mk-ansi--bg-bright-white{background-color:var(--mk-surface)}@media(prefers-reduced-motion:reduce){.mk-log-viewer__tool{transition:none}}\n"] }]
|
|
6360
6036
|
}], ctorParameters: () => [], propDecorators: { viewportRef: [{ type: i0.ViewChild, args: ['viewport', { isSignal: true }] }], lines: [{ type: i0.Input, args: [{ isSignal: true, alias: "lines", required: false }] }], follow: [{ type: i0.Input, args: [{ isSignal: true, alias: "follow", required: false }] }, { type: i0.Output, args: ["followChange"] }], wrap: [{ type: i0.Input, args: [{ isSignal: true, alias: "wrap", required: false }] }, { type: i0.Output, args: ["wrapChange"] }], ansi: [{ type: i0.Input, args: [{ isSignal: true, alias: "ansi", required: false }] }], query: [{ type: i0.Input, args: [{ isSignal: true, alias: "query", required: false }] }], maxLines: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLines", required: false }] }], itemHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemHeight", required: false }] }], hideToolbar: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideToolbar", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], matches: [{ type: i0.Output, args: ["matches"] }] } });
|
|
6361
6037
|
|
|
6362
|
-
/**
|
|
6363
|
-
* Dependency-free markdown parsing and rendering for `<mk-markdown>` — a small
|
|
6364
|
-
* hand-written CommonMark subset aimed at admin-app content (changelogs, AI
|
|
6365
|
-
* output, user notes). {@link mkParseMarkdown} produces a typed AST and
|
|
6366
|
-
* {@link mkRenderMarkdown} serialises it to an HTML string that is safe by
|
|
6367
|
-
* construction: every character of source text is HTML-escaped and the only
|
|
6368
|
-
* tags in the output are the ones the renderer itself generates.
|
|
6369
|
-
*
|
|
6370
|
-
* SUPPORTED SYNTAX
|
|
6371
|
-
* - ATX headings `#` … `######` (optional closing hashes are stripped)
|
|
6372
|
-
* - Paragraphs; hard line breaks via two trailing spaces
|
|
6373
|
-
* - Emphasis: bold `**x**`, italic `*x*` / `_x_` (word-bounded for `_`),
|
|
6374
|
-
* strikethrough `~~x~~`, and `***x***` for bold-italic
|
|
6375
|
-
* - Inline code `` `x` `` (multi-backtick fences for literal backticks)
|
|
6376
|
-
* - Links `[text](url)` — http/https/mailto/relative URLs only; anything else
|
|
6377
|
-
* (`javascript:` etc.) has its href dropped and renders as plain text
|
|
6378
|
-
* - Images `` — same URL policy; unsafe sources render as alt text
|
|
6379
|
-
* - Fenced code blocks ``` with an optional language (highlighted through
|
|
6380
|
-
* `mkHighlight` for its known languages, plain escaped code otherwise)
|
|
6381
|
-
* - Tight unordered (`-`, `*`, `+`) and ordered (`1.`, `1)`) lists, nested by
|
|
6382
|
-
* 2-space indent; a blank line ends the list (loose lists unsupported)
|
|
6383
|
-
* - Blockquotes `>` (nestable; no lazy continuation)
|
|
6384
|
-
* - Horizontal rules (`---`, `***`, `___`)
|
|
6385
|
-
* - GitHub pipe tables with `:---:` alignment colons and `\|` cell escapes
|
|
6386
|
-
* - Backslash escapes for ASCII punctuation (`\*`, `\|`, …)
|
|
6387
|
-
* - Bare `http(s)://` URLs autolink only when the `autolink` option is on
|
|
6388
|
-
*
|
|
6389
|
-
* NOT SUPPORTED (by design)
|
|
6390
|
-
* - Raw inline HTML — always escaped and shown as text. This is the whole
|
|
6391
|
-
* sanitisation story: with no HTML passthrough there is no XSS surface.
|
|
6392
|
-
* - Footnotes, setext headings (`===` / `---` underlines — a `---` line is
|
|
6393
|
-
* always a horizontal rule here), reference-style links, loose lists.
|
|
6394
|
-
*/
|
|
6395
|
-
/* ------------------------------------------------------------------ *
|
|
6396
|
-
* Escaping & URL safety
|
|
6397
|
-
* ------------------------------------------------------------------ */
|
|
6398
|
-
/** Escape text for safe placement in HTML content or a quoted attribute. */
|
|
6399
|
-
function escapeHtml(src) {
|
|
6400
|
-
return src
|
|
6401
|
-
.replace(/&/g, '&')
|
|
6402
|
-
.replace(/</g, '<')
|
|
6403
|
-
.replace(/>/g, '>')
|
|
6404
|
-
.replace(/"/g, '"');
|
|
6405
|
-
}
|
|
6406
|
-
/**
|
|
6407
|
-
* True for URLs safe in `href`/`src`: http(s), mailto and relative paths /
|
|
6408
|
-
* anchors (same policy as rich-text's sanitiser, minus tel/data). Any other
|
|
6409
|
-
* scheme — `javascript:`, `data:`, `vbscript:`, … — is rejected.
|
|
6410
|
-
*/
|
|
6411
|
-
function isSafeUrl(url) {
|
|
6412
|
-
const trimmed = url.trim();
|
|
6413
|
-
if (trimmed === '')
|
|
6414
|
-
return false;
|
|
6415
|
-
if (/^(https?:|mailto:)/i.test(trimmed))
|
|
6416
|
-
return true;
|
|
6417
|
-
if (/^[a-z][a-z0-9+.-]*:/i.test(trimmed))
|
|
6418
|
-
return false; // any other scheme
|
|
6419
|
-
return true; // relative path, anchor, query
|
|
6420
|
-
}
|
|
6421
|
-
/* ------------------------------------------------------------------ *
|
|
6422
|
-
* Inline parsing
|
|
6423
|
-
* ------------------------------------------------------------------ */
|
|
6424
|
-
/** Backslash escapes: any ASCII punctuation character. */
|
|
6425
|
-
const ESCAPE_RE = /^\\([!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])/;
|
|
6426
|
-
/** Inline code span: N backticks, content, N backticks (not followed by `). */
|
|
6427
|
-
const CODE_SPAN_RE = /^(`+)([\s\S]+?)\1(?!`)/;
|
|
6428
|
-
/** URL part of a link/image: bare of whitespace, one balanced-paren level. */
|
|
6429
|
-
const URL_PART = String.raw `((?:[^()\s]|\([^()\s]*\))*)`;
|
|
6430
|
-
/** Image: ``. */
|
|
6431
|
-
const IMAGE_RE = new RegExp(String.raw `^!\[([^\]]*)\]\(\s*${URL_PART}(?:\s+[^)]*)?\s*\)`);
|
|
6432
|
-
/** Link: `[label](url "ignored title")` — label may hold one `[…]` level. */
|
|
6433
|
-
const LINK_RE = new RegExp(String.raw `^\[((?:[^[\]\\]|\\[\s\S]|\[[^\]]*\])*)\]\(\s*${URL_PART}(?:\s+[^)]*)?\s*\)`);
|
|
6434
|
-
const STRONG_EM_RE = /^\*\*\*(?!\s)([\s\S]+?(?<=\S))\*\*\*(?!\*)/;
|
|
6435
|
-
const STRONG_RE = /^\*\*(?!\s)([\s\S]+?(?<=\S))\*\*(?!\*)/;
|
|
6436
|
-
const EM_STAR_RE = /^\*(?![\s*])([\s\S]+?(?<=[^\s*]))\*(?!\*)/;
|
|
6437
|
-
const EM_UNDERSCORE_RE = /^_(?!\s)([\s\S]+?(?<=\S))_(?![0-9A-Za-z_])/;
|
|
6438
|
-
const DEL_RE = /^~~(?!\s)([\s\S]+?(?<=\S))~~/;
|
|
6439
|
-
const AUTOLINK_RE = /^https?:\/\/[^\s<>]+/i;
|
|
6440
|
-
/** Parse a run of inline markdown into AST nodes. */
|
|
6441
|
-
function parseInlines(src, autolink) {
|
|
6442
|
-
const out = [];
|
|
6443
|
-
let text = '';
|
|
6444
|
-
const flush = () => {
|
|
6445
|
-
if (text !== '') {
|
|
6446
|
-
out.push({ kind: 'text', text });
|
|
6447
|
-
text = '';
|
|
6448
|
-
}
|
|
6449
|
-
};
|
|
6450
|
-
let i = 0;
|
|
6451
|
-
while (i < src.length) {
|
|
6452
|
-
const rest = src.slice(i);
|
|
6453
|
-
const ch = rest[0];
|
|
6454
|
-
let m;
|
|
6455
|
-
// Line breaks (paragraph lines are joined with '\n'; two or more trailing
|
|
6456
|
-
// spaces before the newline mark a hard break).
|
|
6457
|
-
if ((m = rest.match(/^[ \t]*\n/))) {
|
|
6458
|
-
flush();
|
|
6459
|
-
out.push(/ {2,}\n$/.test(m[0]) ? { kind: 'break' } : { kind: 'softbreak' });
|
|
6460
|
-
i += m[0].length;
|
|
6461
|
-
continue;
|
|
6462
|
-
}
|
|
6463
|
-
if (ch === '\\' && (m = rest.match(ESCAPE_RE))) {
|
|
6464
|
-
text += m[1];
|
|
6465
|
-
i += m[0].length;
|
|
6466
|
-
continue;
|
|
6467
|
-
}
|
|
6468
|
-
if (ch === '`' && (m = rest.match(CODE_SPAN_RE))) {
|
|
6469
|
-
let code = m[2].replace(/\n/g, ' ');
|
|
6470
|
-
// CommonMark: strip one space from both ends when both exist
|
|
6471
|
-
// (enables `` ` `` for a literal backtick).
|
|
6472
|
-
if (code.length > 2 && code.startsWith(' ') && code.endsWith(' ') && code.trim() !== '') {
|
|
6473
|
-
code = code.slice(1, -1);
|
|
6474
|
-
}
|
|
6475
|
-
flush();
|
|
6476
|
-
out.push({ kind: 'code', code });
|
|
6477
|
-
i += m[0].length;
|
|
6478
|
-
continue;
|
|
6479
|
-
}
|
|
6480
|
-
if (ch === '!' && (m = rest.match(IMAGE_RE))) {
|
|
6481
|
-
flush();
|
|
6482
|
-
if (isSafeUrl(m[2])) {
|
|
6483
|
-
out.push({ kind: 'image', src: m[2].trim(), alt: m[1] });
|
|
6484
|
-
}
|
|
6485
|
-
else if (m[1] !== '') {
|
|
6486
|
-
out.push({ kind: 'text', text: m[1] }); // unsafe source → alt text
|
|
6487
|
-
}
|
|
6488
|
-
i += m[0].length;
|
|
6489
|
-
continue;
|
|
6490
|
-
}
|
|
6491
|
-
if (ch === '[' && (m = rest.match(LINK_RE))) {
|
|
6492
|
-
flush();
|
|
6493
|
-
const children = parseInlines(m[1], autolink);
|
|
6494
|
-
if (isSafeUrl(m[2])) {
|
|
6495
|
-
out.push({ kind: 'link', href: m[2].trim(), children });
|
|
6496
|
-
}
|
|
6497
|
-
else {
|
|
6498
|
-
out.push(...children); // unsafe URL → href dropped, text kept
|
|
6499
|
-
}
|
|
6500
|
-
i += m[0].length;
|
|
6501
|
-
continue;
|
|
6502
|
-
}
|
|
6503
|
-
if (ch === '*') {
|
|
6504
|
-
if ((m = rest.match(STRONG_EM_RE))) {
|
|
6505
|
-
flush();
|
|
6506
|
-
out.push({
|
|
6507
|
-
kind: 'strong',
|
|
6508
|
-
children: [{ kind: 'em', children: parseInlines(m[1], autolink) }],
|
|
6509
|
-
});
|
|
6510
|
-
i += m[0].length;
|
|
6511
|
-
continue;
|
|
6512
|
-
}
|
|
6513
|
-
if ((m = rest.match(STRONG_RE))) {
|
|
6514
|
-
flush();
|
|
6515
|
-
out.push({ kind: 'strong', children: parseInlines(m[1], autolink) });
|
|
6516
|
-
i += m[0].length;
|
|
6517
|
-
continue;
|
|
6518
|
-
}
|
|
6519
|
-
if ((m = rest.match(EM_STAR_RE))) {
|
|
6520
|
-
flush();
|
|
6521
|
-
out.push({ kind: 'em', children: parseInlines(m[1], autolink) });
|
|
6522
|
-
i += m[0].length;
|
|
6523
|
-
continue;
|
|
6524
|
-
}
|
|
6525
|
-
}
|
|
6526
|
-
// `_` emphasis only at a word boundary (no intra-word `snake_case`).
|
|
6527
|
-
if (ch === '_' && (i === 0 || !/[0-9A-Za-z_]/.test(src[i - 1])) && (m = rest.match(EM_UNDERSCORE_RE))) {
|
|
6528
|
-
flush();
|
|
6529
|
-
out.push({ kind: 'em', children: parseInlines(m[1], autolink) });
|
|
6530
|
-
i += m[0].length;
|
|
6531
|
-
continue;
|
|
6532
|
-
}
|
|
6533
|
-
if (ch === '~' && (m = rest.match(DEL_RE))) {
|
|
6534
|
-
flush();
|
|
6535
|
-
out.push({ kind: 'del', children: parseInlines(m[1], autolink) });
|
|
6536
|
-
i += m[0].length;
|
|
6537
|
-
continue;
|
|
6538
|
-
}
|
|
6539
|
-
if (autolink && (ch === 'h' || ch === 'H') && (i === 0 || /[\s([]/.test(src[i - 1])) && (m = rest.match(AUTOLINK_RE))) {
|
|
6540
|
-
// Trim trailing punctuation that usually belongs to the sentence.
|
|
6541
|
-
const url = m[0].replace(/[.,;:!?'")\]]+$/, '');
|
|
6542
|
-
if (url.length > 'https://'.length) {
|
|
6543
|
-
flush();
|
|
6544
|
-
out.push({ kind: 'link', href: url, children: [{ kind: 'text', text: url }] });
|
|
6545
|
-
i += url.length;
|
|
6546
|
-
continue;
|
|
6547
|
-
}
|
|
6548
|
-
}
|
|
6549
|
-
text += ch;
|
|
6550
|
-
i += 1;
|
|
6551
|
-
}
|
|
6552
|
-
flush();
|
|
6553
|
-
return out;
|
|
6554
|
-
}
|
|
6555
|
-
/* ------------------------------------------------------------------ *
|
|
6556
|
-
* Block parsing
|
|
6557
|
-
* ------------------------------------------------------------------ */
|
|
6558
|
-
const FENCE_OPEN_RE = /^ {0,3}(`{3,})[ \t]*(\S*)[^`]*$/;
|
|
6559
|
-
const HEADING_RE = /^ {0,3}(#{1,6})(?:[ \t]+(.*))?$/;
|
|
6560
|
-
const HR_RE = /^ {0,3}([-*_])(?:[ \t]*\1){2,}[ \t]*$/;
|
|
6561
|
-
const QUOTE_RE = /^ {0,3}>/;
|
|
6562
|
-
const BULLET_ITEM_RE = /^([ \t]*)([-*+])[ \t]+(.*)$/;
|
|
6563
|
-
const ORDERED_ITEM_RE = /^([ \t]*)(\d{1,9})[.)][ \t]+(.*)$/;
|
|
6564
|
-
const TABLE_DELIM_RE = /^\s*\|?\s*:?-+:?\s*(?:\|\s*:?-+:?\s*)*\|?\s*$/;
|
|
6565
|
-
function isBlank(line) {
|
|
6566
|
-
return line.trim() === '';
|
|
6567
|
-
}
|
|
6568
|
-
/** True when `line` starts a construct that interrupts a paragraph. */
|
|
6569
|
-
function interruptsParagraph(line, next) {
|
|
6570
|
-
return (isBlank(line) ||
|
|
6571
|
-
FENCE_OPEN_RE.test(line) ||
|
|
6572
|
-
HEADING_RE.test(line) ||
|
|
6573
|
-
HR_RE.test(line) ||
|
|
6574
|
-
QUOTE_RE.test(line) ||
|
|
6575
|
-
BULLET_ITEM_RE.test(line) ||
|
|
6576
|
-
ORDERED_ITEM_RE.test(line) ||
|
|
6577
|
-
isTableStart(line, next));
|
|
6578
|
-
}
|
|
6579
|
-
/** True when `line` + `next` open a pipe table (header row + delimiter row). */
|
|
6580
|
-
function isTableStart(line, next) {
|
|
6581
|
-
if (next === undefined || !line.includes('|') || !TABLE_DELIM_RE.test(next))
|
|
6582
|
-
return false;
|
|
6583
|
-
if (!next.includes('|'))
|
|
6584
|
-
return false; // require at least one pipe in the delimiter
|
|
6585
|
-
return splitTableRow(line).length === splitTableRow(next).length;
|
|
6586
|
-
}
|
|
6587
|
-
/** Split a pipe-table row into raw cell strings, honouring `\|` escapes. */
|
|
6588
|
-
function splitTableRow(line) {
|
|
6589
|
-
let row = line.trim();
|
|
6590
|
-
if (row.startsWith('|'))
|
|
6591
|
-
row = row.slice(1);
|
|
6592
|
-
// Strip a trailing unescaped pipe.
|
|
6593
|
-
if (/(?<!\\)\|$/.test(row))
|
|
6594
|
-
row = row.slice(0, -1);
|
|
6595
|
-
const cells = [];
|
|
6596
|
-
let cell = '';
|
|
6597
|
-
for (let i = 0; i < row.length; i++) {
|
|
6598
|
-
const ch = row[i];
|
|
6599
|
-
if (ch === '\\' && i + 1 < row.length) {
|
|
6600
|
-
cell += ch + row[i + 1];
|
|
6601
|
-
i++;
|
|
6602
|
-
}
|
|
6603
|
-
else if (ch === '|') {
|
|
6604
|
-
cells.push(cell.trim());
|
|
6605
|
-
cell = '';
|
|
6606
|
-
}
|
|
6607
|
-
else {
|
|
6608
|
-
cell += ch;
|
|
6609
|
-
}
|
|
6610
|
-
}
|
|
6611
|
-
cells.push(cell.trim());
|
|
6612
|
-
return cells;
|
|
6613
|
-
}
|
|
6614
|
-
function parseAlign(cell) {
|
|
6615
|
-
const left = cell.startsWith(':');
|
|
6616
|
-
const right = cell.endsWith(':');
|
|
6617
|
-
if (left && right)
|
|
6618
|
-
return 'center';
|
|
6619
|
-
if (right)
|
|
6620
|
-
return 'right';
|
|
6621
|
-
if (left)
|
|
6622
|
-
return 'left';
|
|
6623
|
-
return null;
|
|
6624
|
-
}
|
|
6625
|
-
/** Parse consecutive list lines starting at `lines[start]` into a (nested) list. */
|
|
6626
|
-
function parseList(lines, start, autolink) {
|
|
6627
|
-
const stack = [];
|
|
6628
|
-
let i = start;
|
|
6629
|
-
while (i < lines.length) {
|
|
6630
|
-
const m = lines[i].match(BULLET_ITEM_RE) ?? lines[i].match(ORDERED_ITEM_RE);
|
|
6631
|
-
if (!m)
|
|
6632
|
-
break;
|
|
6633
|
-
const ordered = /\d/.test(m[2]);
|
|
6634
|
-
const indent = m[1].replace(/\t/g, ' ').length;
|
|
6635
|
-
let depth = Math.min(Math.floor(indent / 2), stack.length);
|
|
6636
|
-
if (stack.length === 0)
|
|
6637
|
-
depth = 0;
|
|
6638
|
-
if (depth === stack.length && depth > 0) {
|
|
6639
|
-
// One level deeper: open a sublist on the previous item.
|
|
6640
|
-
const parent = stack[depth - 1];
|
|
6641
|
-
const lastItem = parent.items[parent.items.length - 1];
|
|
6642
|
-
const sublist = {
|
|
6643
|
-
kind: 'list',
|
|
6644
|
-
ordered,
|
|
6645
|
-
start: ordered ? Number(m[2]) : 1,
|
|
6646
|
-
items: [],
|
|
6647
|
-
};
|
|
6648
|
-
lastItem.sublist = sublist;
|
|
6649
|
-
stack.push(sublist);
|
|
6650
|
-
}
|
|
6651
|
-
else {
|
|
6652
|
-
while (stack.length - 1 > depth)
|
|
6653
|
-
stack.pop();
|
|
6654
|
-
if (stack.length === 0) {
|
|
6655
|
-
stack.push({ kind: 'list', ordered, start: ordered ? Number(m[2]) : 1, items: [] });
|
|
6656
|
-
}
|
|
6657
|
-
}
|
|
6658
|
-
stack[stack.length - 1].items.push({
|
|
6659
|
-
children: parseInlines(m[3].replace(/[ \t]+$/, ''), autolink),
|
|
6660
|
-
sublist: null,
|
|
6661
|
-
});
|
|
6662
|
-
i++;
|
|
6663
|
-
}
|
|
6664
|
-
return { list: stack[0], next: i };
|
|
6665
|
-
}
|
|
6666
|
-
/** Parse an array of source lines into blocks (recursive for blockquotes). */
|
|
6667
|
-
function parseBlockLines(lines, autolink) {
|
|
6668
|
-
const blocks = [];
|
|
6669
|
-
let i = 0;
|
|
6670
|
-
while (i < lines.length) {
|
|
6671
|
-
const line = lines[i];
|
|
6672
|
-
if (isBlank(line)) {
|
|
6673
|
-
i++;
|
|
6674
|
-
continue;
|
|
6675
|
-
}
|
|
6676
|
-
// Fenced code block.
|
|
6677
|
-
let m = line.match(FENCE_OPEN_RE);
|
|
6678
|
-
if (m) {
|
|
6679
|
-
const fence = m[1];
|
|
6680
|
-
const language = (m[2].match(/^[A-Za-z0-9#+.-]*/)?.[0] ?? '').toLowerCase();
|
|
6681
|
-
const body = [];
|
|
6682
|
-
i++;
|
|
6683
|
-
while (i < lines.length) {
|
|
6684
|
-
const closing = lines[i].match(/^ {0,3}(`{3,})[ \t]*$/);
|
|
6685
|
-
if (closing && closing[1].length >= fence.length) {
|
|
6686
|
-
i++;
|
|
6687
|
-
break;
|
|
6688
|
-
}
|
|
6689
|
-
body.push(lines[i]);
|
|
6690
|
-
i++;
|
|
6691
|
-
}
|
|
6692
|
-
blocks.push({ kind: 'code', language, code: body.join('\n') });
|
|
6693
|
-
continue;
|
|
6694
|
-
}
|
|
6695
|
-
// Horizontal rule (before list: `- - -` is an hr, `- x` a list).
|
|
6696
|
-
if (HR_RE.test(line)) {
|
|
6697
|
-
blocks.push({ kind: 'hr' });
|
|
6698
|
-
i++;
|
|
6699
|
-
continue;
|
|
6700
|
-
}
|
|
6701
|
-
// ATX heading.
|
|
6702
|
-
m = line.match(HEADING_RE);
|
|
6703
|
-
if (m) {
|
|
6704
|
-
const content = (m[2] ?? '').replace(/[ \t]+#+[ \t]*$/, '').trim();
|
|
6705
|
-
blocks.push({
|
|
6706
|
-
kind: 'heading',
|
|
6707
|
-
level: m[1].length,
|
|
6708
|
-
children: parseInlines(content, autolink),
|
|
6709
|
-
});
|
|
6710
|
-
i++;
|
|
6711
|
-
continue;
|
|
6712
|
-
}
|
|
6713
|
-
// Blockquote: consecutive `>` lines, one marker level stripped, recursed.
|
|
6714
|
-
if (QUOTE_RE.test(line)) {
|
|
6715
|
-
const inner = [];
|
|
6716
|
-
while (i < lines.length && QUOTE_RE.test(lines[i])) {
|
|
6717
|
-
inner.push(lines[i].replace(/^ {0,3}> ?/, ''));
|
|
6718
|
-
i++;
|
|
6719
|
-
}
|
|
6720
|
-
blocks.push({ kind: 'blockquote', children: parseBlockLines(inner, autolink) });
|
|
6721
|
-
continue;
|
|
6722
|
-
}
|
|
6723
|
-
// List (tight; ends at the first non-item line).
|
|
6724
|
-
if (BULLET_ITEM_RE.test(line) || ORDERED_ITEM_RE.test(line)) {
|
|
6725
|
-
const { list, next } = parseList(lines, i, autolink);
|
|
6726
|
-
blocks.push(list);
|
|
6727
|
-
i = next;
|
|
6728
|
-
continue;
|
|
6729
|
-
}
|
|
6730
|
-
// Pipe table.
|
|
6731
|
-
if (isTableStart(line, lines[i + 1])) {
|
|
6732
|
-
const header = splitTableRow(line).map((c) => parseInlines(c, autolink));
|
|
6733
|
-
const align = splitTableRow(lines[i + 1]).map(parseAlign);
|
|
6734
|
-
const rows = [];
|
|
6735
|
-
i += 2;
|
|
6736
|
-
while (i < lines.length && !isBlank(lines[i]) && lines[i].includes('|')) {
|
|
6737
|
-
const cells = splitTableRow(lines[i]);
|
|
6738
|
-
rows.push(header.map((_, col) => parseInlines(cells[col] ?? '', autolink)));
|
|
6739
|
-
i++;
|
|
6740
|
-
}
|
|
6741
|
-
blocks.push({ kind: 'table', align, header, rows });
|
|
6742
|
-
continue;
|
|
6743
|
-
}
|
|
6744
|
-
// Paragraph: gather until a blank line or another block construct.
|
|
6745
|
-
const para = [line];
|
|
6746
|
-
i++;
|
|
6747
|
-
while (i < lines.length && !interruptsParagraph(lines[i], lines[i + 1])) {
|
|
6748
|
-
para.push(lines[i]);
|
|
6749
|
-
i++;
|
|
6750
|
-
}
|
|
6751
|
-
const content = para.map((l) => l.replace(/^[ \t]+/, '')).join('\n').replace(/[ \t]+$/, '');
|
|
6752
|
-
blocks.push({ kind: 'paragraph', children: parseInlines(content, autolink) });
|
|
6753
|
-
}
|
|
6754
|
-
return blocks;
|
|
6755
|
-
}
|
|
6756
|
-
/**
|
|
6757
|
-
* Parse markdown source into a typed AST. Pure and dependency-free — safe to
|
|
6758
|
-
* run on a server. Unsafe link/image URLs are already dropped at this stage,
|
|
6759
|
-
* so the AST never carries a `javascript:` (or other non-allow-listed) URL.
|
|
6760
|
-
*/
|
|
6761
|
-
function mkParseMarkdown(src, options = {}) {
|
|
6762
|
-
const lines = String(src ?? '').replace(/\r\n?/g, '\n').split('\n');
|
|
6763
|
-
return parseBlockLines(lines, options.autolink ?? false);
|
|
6764
|
-
}
|
|
6765
|
-
/* ------------------------------------------------------------------ *
|
|
6766
|
-
* Rendering
|
|
6767
|
-
* ------------------------------------------------------------------ */
|
|
6768
|
-
const ALIGN_CLASS = {
|
|
6769
|
-
left: '', // left is the document default — no class needed
|
|
6770
|
-
center: ' class="mk-markdown--center"',
|
|
6771
|
-
right: ' class="mk-markdown--right"',
|
|
6772
|
-
};
|
|
6773
|
-
function renderInlines(nodes, options) {
|
|
6774
|
-
let out = '';
|
|
6775
|
-
for (const node of nodes) {
|
|
6776
|
-
switch (node.kind) {
|
|
6777
|
-
case 'text':
|
|
6778
|
-
out += escapeHtml(node.text);
|
|
6779
|
-
break;
|
|
6780
|
-
case 'softbreak':
|
|
6781
|
-
out += '\n';
|
|
6782
|
-
break;
|
|
6783
|
-
case 'break':
|
|
6784
|
-
out += '<br>';
|
|
6785
|
-
break;
|
|
6786
|
-
case 'code':
|
|
6787
|
-
out += `<code>${escapeHtml(node.code)}</code>`;
|
|
6788
|
-
break;
|
|
6789
|
-
case 'strong':
|
|
6790
|
-
out += `<strong>${renderInlines(node.children, options)}</strong>`;
|
|
6791
|
-
break;
|
|
6792
|
-
case 'em':
|
|
6793
|
-
out += `<em>${renderInlines(node.children, options)}</em>`;
|
|
6794
|
-
break;
|
|
6795
|
-
case 'del':
|
|
6796
|
-
out += `<del>${renderInlines(node.children, options)}</del>`;
|
|
6797
|
-
break;
|
|
6798
|
-
case 'link': {
|
|
6799
|
-
const target = options.linkTarget === '_blank'
|
|
6800
|
-
? ' target="_blank" rel="noopener noreferrer"'
|
|
6801
|
-
: '';
|
|
6802
|
-
out += `<a href="${escapeHtml(node.href)}"${target}>${renderInlines(node.children, options)}</a>`;
|
|
6803
|
-
break;
|
|
6804
|
-
}
|
|
6805
|
-
case 'image':
|
|
6806
|
-
out += `<img src="${escapeHtml(node.src)}" alt="${escapeHtml(node.alt)}">`;
|
|
6807
|
-
break;
|
|
6808
|
-
}
|
|
6809
|
-
}
|
|
6810
|
-
return out;
|
|
6811
|
-
}
|
|
6812
|
-
function renderList(list, options) {
|
|
6813
|
-
const tag = list.ordered ? 'ol' : 'ul';
|
|
6814
|
-
const start = list.ordered && list.start !== 1 ? ` start="${list.start}"` : '';
|
|
6815
|
-
const items = list.items
|
|
6816
|
-
.map((item) => {
|
|
6817
|
-
const sub = item.sublist ? renderList(item.sublist, options) : '';
|
|
6818
|
-
return `<li>${renderInlines(item.children, options)}${sub}</li>`;
|
|
6819
|
-
})
|
|
6820
|
-
.join('');
|
|
6821
|
-
return `<${tag}${start}>${items}</${tag}>`;
|
|
6822
|
-
}
|
|
6823
|
-
/**
|
|
6824
|
-
* Render a parsed AST to an HTML string. The output contains only tags this
|
|
6825
|
-
* renderer generates (all source text is escaped), so it is safe to bind to
|
|
6826
|
-
* `[innerHTML]` — Angular's sanitizer keeps every element/attribute used here.
|
|
6827
|
-
* Fenced code is highlighted via `mkHighlight` for its known languages.
|
|
6828
|
-
*/
|
|
6829
|
-
function mkRenderMarkdown(blocks, options = {}) {
|
|
6830
|
-
let out = '';
|
|
6831
|
-
for (const block of blocks) {
|
|
6832
|
-
switch (block.kind) {
|
|
6833
|
-
case 'heading':
|
|
6834
|
-
out += `<h${block.level}>${renderInlines(block.children, options)}</h${block.level}>`;
|
|
6835
|
-
break;
|
|
6836
|
-
case 'paragraph':
|
|
6837
|
-
out += `<p>${renderInlines(block.children, options)}</p>`;
|
|
6838
|
-
break;
|
|
6839
|
-
case 'code': {
|
|
6840
|
-
const lang = block.language
|
|
6841
|
-
? ` class="language-${escapeHtml(block.language)}"`
|
|
6842
|
-
: '';
|
|
6843
|
-
out += `<pre class="mk-markdown__code"><code${lang}>${mkHighlight(block.code, block.language)}</code></pre>`;
|
|
6844
|
-
break;
|
|
6845
|
-
}
|
|
6846
|
-
case 'blockquote':
|
|
6847
|
-
out += `<blockquote>${mkRenderMarkdown(block.children, options)}</blockquote>`;
|
|
6848
|
-
break;
|
|
6849
|
-
case 'hr':
|
|
6850
|
-
out += '<hr>';
|
|
6851
|
-
break;
|
|
6852
|
-
case 'list':
|
|
6853
|
-
out += renderList(block, options);
|
|
6854
|
-
break;
|
|
6855
|
-
case 'table': {
|
|
6856
|
-
const alignAttr = (col) => {
|
|
6857
|
-
const align = block.align[col];
|
|
6858
|
-
return align ? ALIGN_CLASS[align] : '';
|
|
6859
|
-
};
|
|
6860
|
-
const head = block.header
|
|
6861
|
-
.map((cell, c) => `<th${alignAttr(c)}>${renderInlines(cell, options)}</th>`)
|
|
6862
|
-
.join('');
|
|
6863
|
-
const body = block.rows
|
|
6864
|
-
.map((row) => `<tr>${row
|
|
6865
|
-
.map((cell, c) => `<td${alignAttr(c)}>${renderInlines(cell, options)}</td>`)
|
|
6866
|
-
.join('')}</tr>`)
|
|
6867
|
-
.join('');
|
|
6868
|
-
out += `<table><thead><tr>${head}</tr></thead>${body ? `<tbody>${body}</tbody>` : ''}</table>`;
|
|
6869
|
-
break;
|
|
6870
|
-
}
|
|
6871
|
-
}
|
|
6872
|
-
}
|
|
6873
|
-
return out;
|
|
6874
|
-
}
|
|
6038
|
+
/** Delegates to `@mk-kit/core` — the exported names are unchanged. */
|
|
6875
6039
|
|
|
6876
6040
|
/**
|
|
6877
6041
|
* Markdown — renders a CommonMark subset (see {@link mkParseMarkdown} for the
|
|
@@ -6922,5 +6086,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
|
|
|
6922
6086
|
* Generated bundle index. Do not edit.
|
|
6923
6087
|
*/
|
|
6924
6088
|
|
|
6925
|
-
export { MK_CHART_PALETTE_SIZE, MK_HEATMAP_MIN_CONTRAST, MkAvatar, MkAvatarGroup, MkBadge, MkBadgeOverlay, MkBarChart, MkCalendarHeatmap, MkCard, MkCardFooter, MkCardHeader, MkCardTitle, MkCarousel, MkCarouselSlide, MkCode, MkCountdown, MkDescItem, MkDescriptionList, MkDiff, MkDivider, MkDonutChart, MkEmptyState, MkFunnelChart, MkGauge, MkHeatmap, MkInlineEdit, MkJsonViewer, MkKanban, MkLineChart, MkList, MkListItem, MkLogViewer, MkMarkdown, MkOrgChart, MkOrgChartNodeDef, MkProfileActions, MkProfileCard, MkProfileMeta, MkProgressBar, MkProgressRing, MkQrCode, MkRadarChart, MkScatterChart, MkSkeleton, MkSkeletonPreset, MkSparkline, MkSpinner, MkStatCard, MkTag, MkTimeline, MkTimelineItem, MkTreemap, MkVirtualScroll, mkArcPath, mkAreaPath, mkBuildJsonTree, mkChartColor,
|
|
6089
|
+
export { MK_CHART_PALETTE_SIZE, MK_HEATMAP_MIN_CONTRAST, MkAvatar, MkAvatarGroup, MkBadge, MkBadgeOverlay, MkBarChart, MkCalendarHeatmap, MkCard, MkCardFooter, MkCardHeader, MkCardTitle, MkCarousel, MkCarouselSlide, MkCode, MkCountdown, MkDescItem, MkDescriptionList, MkDiff, MkDivider, MkDonutChart, MkEmptyState, MkFunnelChart, MkGauge, MkHeatmap, MkInlineEdit, MkJsonViewer, MkKanban, MkLineChart, MkList, MkListItem, MkLogViewer, MkMarkdown, MkOrgChart, MkOrgChartNodeDef, MkProfileActions, MkProfileCard, MkProfileMeta, MkProgressBar, MkProgressRing, MkQrCode, MkRadarChart, MkScatterChart, MkSkeleton, MkSkeletonPreset, MkSparkline, MkSpinner, MkStatCard, MkTag, MkTimeline, MkTimelineItem, MkTreemap, MkVirtualScroll, mkArcPath, mkAreaPath, mkBuildJsonTree, mkChartColor, mkContrastRatio, mkEncodeQr, mkFormatCompact, mkHeatmapCellColors, mkLinePath, mkLinearScale, mkMixRgb, mkNiceTicks, mkOrgChartFromFlat, mkParseRgb, mkRelativeLuminance, mkSplitDuration, mkSquarify };
|
|
6926
6090
|
//# sourceMappingURL=mk-kit-ui-data.mjs.map
|