klun-ui 0.1.20 → 0.1.21

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/CHANGELOG.md CHANGED
@@ -5,6 +5,22 @@ All notable changes to **klun-ui** are documented here. The format follows
5
5
  [Semantic Versioning](https://semver.org/) (pre-1.0: minor/patch bumps may carry
6
6
  small breaking changes).
7
7
 
8
+ ## [0.1.21] — 2026-07-13
9
+
10
+ ### Added
11
+ - **`Markdown` — GFM extensions.** The dependency-free renderer now understands
12
+ the common Markdown that documents and wikis rely on, still building React
13
+ nodes (never raw HTML), so it stays XSS-safe:
14
+ - **GFM pipe tables** with per-column alignment (`:---`, `---:`, `:--:`); cell
15
+ text runs through the inline renderer, so **bold** / `code` / links work
16
+ inside cells. Wide tables scroll inside their own container.
17
+ - **Task lists** — `- [ ]` / `- [x]` render read-only checkboxes.
18
+ - **Horizontal rules** — a line of `---`, `***`, or `___`.
19
+ - **Bare autolinks** — a plain `http(s)://…` URL becomes a link.
20
+ - **`[[wiki links]]`** via a new `wikiLink` prop (`WikiLinkResolver`): resolve
21
+ `[[target]]` / `[[target|label]]` to an href (and optional display label).
22
+ Unresolved links render as plain text, never raw `[[brackets]]`.
23
+
8
24
  ## [0.1.20] — 2026-07-11
9
25
 
10
26
  ### Added
@@ -3499,8 +3499,21 @@ var ListItem = forwardRef(
3499
3499
  );
3500
3500
  ListItem.displayName = "ListItem";
3501
3501
  var k = 0;
3502
+ var wikiResolve;
3502
3503
  function inline(text) {
3503
3504
  const patterns = [
3505
+ // [[wiki link]] / [[target|label]] — resolved via the wikiLink prop; falls
3506
+ // back to plain text (not raw brackets) when unresolved.
3507
+ {
3508
+ re: /\[\[([^\]|]+)(?:\|([^\]]+))?\]\]/,
3509
+ node: (m) => {
3510
+ const target = m[1].trim();
3511
+ const r = wikiResolve?.(target);
3512
+ const resolved = typeof r === "string" ? { href: r, label: void 0 } : r || null;
3513
+ const label = m[2]?.trim() || resolved?.label || target;
3514
+ return resolved ? /* @__PURE__ */ jsx("a", { className: "klun-md-wikilink", href: resolved.href, children: label }, k++) : /* @__PURE__ */ jsx("span", { className: "klun-md-wikilink klun-md-wikilink--broken", children: label }, k++);
3515
+ }
3516
+ },
3504
3517
  { re: /`([^`]+)`/, node: (m) => /* @__PURE__ */ jsx("code", { className: "klun-md-code", children: m[1] }, k++) },
3505
3518
  // image before link (`![alt](url)` starts with `!` + link syntax). url allows
3506
3519
  // http(s) and data: URIs (base64 has no `)`), so pasted screenshots embed inline.
@@ -3512,6 +3525,13 @@ function inline(text) {
3512
3525
  {
3513
3526
  re: /\[([^\]]+)\]\(([^)]+)\)/,
3514
3527
  node: (m) => /* @__PURE__ */ jsx("a", { href: m[2], target: "_blank", rel: "noreferrer", children: m[1] }, k++)
3528
+ },
3529
+ // bare autolink: a plain http(s) URL becomes a link. Runs after the
3530
+ // [text](url)/image patterns — those start at an earlier index (the `[`/`!`)
3531
+ // and so win via the earliest-match selection below.
3532
+ {
3533
+ re: /(https?:\/\/[^\s<>()[\]]+)/,
3534
+ node: (m) => /* @__PURE__ */ jsx("a", { href: m[1], target: "_blank", rel: "noreferrer", children: m[1] }, k++)
3515
3535
  }
3516
3536
  ];
3517
3537
  const out = [];
@@ -3532,9 +3552,28 @@ function inline(text) {
3532
3552
  }
3533
3553
  return out;
3534
3554
  }
3555
+ function splitRow(line) {
3556
+ let s = line.trim();
3557
+ if (s.startsWith("|")) s = s.slice(1);
3558
+ if (s.endsWith("|")) s = s.slice(0, -1);
3559
+ return s.split("|").map((c) => c.trim());
3560
+ }
3561
+ function tableAligns(delimCells) {
3562
+ return delimCells.map((c) => {
3563
+ const l = c.startsWith(":"), r = c.endsWith(":");
3564
+ return l && r ? "center" : r ? "right" : l ? "left" : void 0;
3565
+ });
3566
+ }
3567
+ function isTableDelim(delim, cols) {
3568
+ if (!delim || !delim.includes("-")) return false;
3569
+ const cells = splitRow(delim);
3570
+ return cells.length === cols && cells.every((c) => /^:?-{1,}:?$/.test(c));
3571
+ }
3572
+ var HR = /^\s{0,3}(-{3,}|\*{3,}|_{3,})\s*$/;
3535
3573
  var SPECIAL = /^(#{1,6}\s|>\s?|[-*]\s+|\d+\.\s+|```)/;
3536
- function renderMarkdown(src) {
3574
+ function renderMarkdown(src, opts) {
3537
3575
  k = 0;
3576
+ wikiResolve = opts?.wikiLink;
3538
3577
  const lines = src.replace(/\r\n/g, "\n").split("\n");
3539
3578
  const blocks = [];
3540
3579
  let i = 0;
@@ -3550,6 +3589,30 @@ function renderMarkdown(src) {
3550
3589
  );
3551
3590
  continue;
3552
3591
  }
3592
+ if (line.includes("|")) {
3593
+ const header = splitRow(line);
3594
+ if (i + 1 < lines.length && isTableDelim(lines[i + 1], header.length)) {
3595
+ const aligns = tableAligns(splitRow(lines[i + 1]));
3596
+ i += 2;
3597
+ const rows = [];
3598
+ while (i < lines.length && lines[i].trim() !== "" && lines[i].includes("|")) {
3599
+ rows.push(splitRow(lines[i++]));
3600
+ }
3601
+ const cellStyle = (j) => aligns[j] ? { textAlign: aligns[j] } : void 0;
3602
+ blocks.push(
3603
+ /* @__PURE__ */ jsx("div", { className: "klun-md-tablewrap", children: /* @__PURE__ */ jsxs("table", { className: "klun-md-table", children: [
3604
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: header.map((c, j) => /* @__PURE__ */ jsx("th", { style: cellStyle(j), children: inline(c) }, j)) }) }),
3605
+ /* @__PURE__ */ jsx("tbody", { children: rows.map((r, ri) => /* @__PURE__ */ jsx("tr", { children: header.map((_, j) => /* @__PURE__ */ jsx("td", { style: cellStyle(j), children: inline(r[j] ?? "") }, j)) }, ri)) })
3606
+ ] }) }, k++)
3607
+ );
3608
+ continue;
3609
+ }
3610
+ }
3611
+ if (HR.test(line)) {
3612
+ blocks.push(/* @__PURE__ */ jsx("hr", { className: "klun-md-hr" }, k++));
3613
+ i++;
3614
+ continue;
3615
+ }
3553
3616
  const h = /^(#{1,6})\s+(.*)$/.exec(line);
3554
3617
  if (h) {
3555
3618
  const tag = `h${Math.min(h[1].length + 2, 6)}`;
@@ -3568,8 +3631,18 @@ function renderMarkdown(src) {
3568
3631
  if (/^[-*]\s+/.test(line)) {
3569
3632
  const items2 = [];
3570
3633
  while (i < lines.length && /^[-*]\s+/.test(lines[i])) items2.push(lines[i++].replace(/^[-*]\s+/, ""));
3634
+ const hasTask = items2.some((it) => /^\[[ xX]\]\s+/.test(it));
3571
3635
  blocks.push(
3572
- /* @__PURE__ */ jsx("ul", { className: "klun-md-ul", children: items2.map((it, j) => /* @__PURE__ */ jsx("li", { children: inline(it) }, j)) }, k++)
3636
+ /* @__PURE__ */ jsx("ul", { className: hasTask ? "klun-md-ul klun-md-tasklist" : "klun-md-ul", children: items2.map((it, j) => {
3637
+ const t = /^\[([ xX])\]\s+(.*)$/.exec(it);
3638
+ if (t) {
3639
+ return /* @__PURE__ */ jsxs("li", { className: "klun-md-task", children: [
3640
+ /* @__PURE__ */ jsx("input", { type: "checkbox", checked: t[1] !== " ", readOnly: true, disabled: true }),
3641
+ /* @__PURE__ */ jsx("span", { children: inline(t[2]) })
3642
+ ] }, j);
3643
+ }
3644
+ return /* @__PURE__ */ jsx("li", { children: inline(it) }, j);
3645
+ }) }, k++)
3573
3646
  );
3574
3647
  continue;
3575
3648
  }
@@ -3587,16 +3660,16 @@ function renderMarkdown(src) {
3587
3660
  }
3588
3661
  const buf = [line];
3589
3662
  i++;
3590
- while (i < lines.length && lines[i].trim() !== "" && !SPECIAL.test(lines[i])) buf.push(lines[i++]);
3663
+ while (i < lines.length && lines[i].trim() !== "" && !SPECIAL.test(lines[i]) && !HR.test(lines[i])) buf.push(lines[i++]);
3591
3664
  blocks.push(
3592
3665
  /* @__PURE__ */ jsx("p", { className: "klun-md-p", children: buf.flatMap((l, j) => j ? [/* @__PURE__ */ jsx("br", {}, `br${j}`), ...inline(l)] : inline(l)) }, k++)
3593
3666
  );
3594
3667
  }
3595
3668
  return /* @__PURE__ */ jsx(Fragment, { children: blocks });
3596
3669
  }
3597
- var Markdown = forwardRef(function Markdown2({ children, source, className, ...props }, ref) {
3670
+ var Markdown = forwardRef(function Markdown2({ children, source, className, wikiLink, ...props }, ref) {
3598
3671
  const src = source ?? (typeof children === "string" ? children : "") ?? "";
3599
- return /* @__PURE__ */ jsx("div", { ref, className: cx("klun-md", className), ...props, children: renderMarkdown(src) });
3672
+ return /* @__PURE__ */ jsx("div", { ref, className: cx("klun-md", className), ...props, children: renderMarkdown(src, { wikiLink }) });
3600
3673
  });
3601
3674
  Markdown.displayName = "Markdown";
3602
3675
  var Money = forwardRef(function Money2({
@@ -11524,5 +11597,5 @@ var Popconfirm = forwardRef(function Popconfirm2({
11524
11597
  Popconfirm.displayName = "Popconfirm";
11525
11598
 
11526
11599
  export { Accordion, Alert, AutoComplete, Avatar, AvatarGroup, Badge, Banner, Breadcrumb, BulkAction, BulkActionBar, Button, ButtonGroup, Card, Carousel, Cascader, CharacterCounter, ChartLegend, ChartTooltip, Checkbox, CheckboxCard, CheckboxGroup, Chip, CircularProgress, CodeViewer, Col, Collapse, ColorDot, ColorPicker, ColorSlider, CommandMenu, CompactSelect, CompactSelectForInput, ConfigProvider, Confirm, ContentLabel, ContextMenu2 as ContextMenu, CopyButton, CounterInput, CrossRefBadge, DatePicker, DateRangePicker, DateTimePicker, Descriptions, DiffViewer, DigitInput, Divider, Drawer, Dropdown, EmptyState, ExpiryCountdown, FileUpload, Flex, Form, FormItem, FormList, Format, GaugeBar, Grid, Hint, HorizontalFilter, ImageUpload, ImageViewer, InlineInput, InlineSelect, Input, Kbd, KeyIcon, Label, Layout, LayoutContent, LayoutFooter, LayoutHeader, LayoutSider, List, ListItem, LiveDot, LogViewer, Markdown, Masonry, Menu, Message, Modal, Money, Notification, PageHeader, Pagination, PasswordStrength, Popconfirm, Popover, ProgressBar, Radio, RadioCard, RangeSlider, Rating, RelativeTime, Result, RichEditorToolbar, Row, SegmentedControl, SegmentedProgress, Select, SelectMenu, Skeleton, Slider, Space, Spinner2 as Spinner, Splitter2 as Splitter, SplitterPanel, StatCard, Statistic, StatusBadge, StatusDot, StepIndicator, Switch, Table, Tabs, Tag, Textarea, TimePicker, Timeline, Toast, Toaster, Tooltip, Tree, Wizard, arSA, deDE, enUS, esES, fmt, frFR, idID, itIT, jaJP, koKR, locales, nlNL, parsePatch, plPL, primaryColorVars, ptBR, renderMarkdown, ruRU, toast, trTR, useBreakpoint, useConfig, useContextMenu, useForm, useLocale, useMappedSize, useMessage, useNotification, useSize, viVN, zhCN, zhTW };
11527
- //# sourceMappingURL=chunk-JFRI333P.js.map
11528
- //# sourceMappingURL=chunk-JFRI333P.js.map
11600
+ //# sourceMappingURL=chunk-T3IFNMYU.js.map
11601
+ //# sourceMappingURL=chunk-T3IFNMYU.js.map