@youtyan/code-viewer 0.11.0 → 0.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/web/app.js CHANGED
@@ -1818,7 +1818,7 @@ ${lines.join("\n")}
1818
1818
  return SOURCE_SHIKI_LANG_ALIASES[lang] || lang;
1819
1819
  }
1820
1820
  function isPreviewableSource(path) {
1821
- return /\.(md|markdown|mdown|mkdn|mdx|html|htm)$/i.test(path);
1821
+ return /\.(md|markdown|mdown|mkdn|mdx|html|htm|csv|tsv)$/i.test(path);
1822
1822
  }
1823
1823
  function sourceInternalPathKind(path) {
1824
1824
  for (const part of path.split(/[\\/]+/)) {
@@ -1831,6 +1831,8 @@ ${lines.join("\n")}
1831
1831
  function sourcePreviewKind(path) {
1832
1832
  if (/\.(md|markdown|mdown|mkdn|mdx)$/i.test(path)) return "markdown";
1833
1833
  if (/\.(html|htm)$/i.test(path)) return "html";
1834
+ if (/\.csv$/i.test(path)) return "csv";
1835
+ if (/\.tsv$/i.test(path)) return "tsv";
1834
1836
  return null;
1835
1837
  }
1836
1838
  var EXT_TO_LANG = {
@@ -8379,6 +8381,22 @@ ${lines.join("\n")}
8379
8381
  md.core.ruler.after("inline", "footnote_tail", footnote_tail);
8380
8382
  }
8381
8383
 
8384
+ // web-src/core/lazy-bundle.ts
8385
+ function createBundleLoader(bundleFile, init) {
8386
+ let pending = null;
8387
+ return () => {
8388
+ if (!pending) {
8389
+ pending = import(
8390
+ /* @vite-ignore */
8391
+ `/${bundleFile}`
8392
+ ).then(
8393
+ (mod) => init ? init(mod) : mod
8394
+ );
8395
+ }
8396
+ return pending;
8397
+ };
8398
+ }
8399
+
8382
8400
  // web-src/core/mermaid-loader.ts
8383
8401
  var DEFAULT_CONFIG = {
8384
8402
  startOnLoad: false,
@@ -8386,18 +8404,19 @@ ${lines.join("\n")}
8386
8404
  theme: "default",
8387
8405
  er: { useMaxWidth: false }
8388
8406
  };
8407
+ var loadMermaidModule = createBundleLoader("mermaid.js");
8389
8408
  var mermaidPromise = null;
8390
8409
  var initialized = false;
8391
8410
  function loadMermaid() {
8392
8411
  if (!mermaidPromise) {
8393
- mermaidPromise = import(`/${"mermaid.js"}`).then((mod) => {
8412
+ mermaidPromise = loadMermaidModule().then((mod) => {
8394
8413
  const mermaid = mod.default;
8395
8414
  if (!initialized) {
8396
8415
  mermaid.initialize(DEFAULT_CONFIG);
8397
8416
  initialized = true;
8398
8417
  }
8399
8418
  return mermaid;
8400
- }).catch(() => null);
8419
+ });
8401
8420
  }
8402
8421
  return mermaidPromise;
8403
8422
  }
@@ -8415,6 +8434,7 @@ ${lines.join("\n")}
8415
8434
  const pre = template.content.querySelector("pre");
8416
8435
  return pre ? pre.innerHTML : "";
8417
8436
  }
8437
+ var loadShikiModule = createBundleLoader("shiki.js");
8418
8438
  var cache = /* @__PURE__ */ new Map();
8419
8439
  function loadShikiHighlighter(options) {
8420
8440
  const key = JSON.stringify({
@@ -8423,12 +8443,12 @@ ${lines.join("\n")}
8423
8443
  });
8424
8444
  const cached = cache.get(key);
8425
8445
  if (cached) return cached;
8426
- const promise = import(`/${"shiki.js"}`).then(
8446
+ const promise = loadShikiModule().then(
8427
8447
  (mod) => mod.createHighlighter({
8428
8448
  themes: options.themes,
8429
8449
  langs: options.langs
8430
8450
  })
8431
- ).catch(() => null);
8451
+ );
8432
8452
  cache.set(key, promise);
8433
8453
  return promise;
8434
8454
  }
@@ -15642,8 +15662,8 @@ Details: ${JSON.stringify(output)}` : "";
15642
15662
  function formatTime(iso) {
15643
15663
  try {
15644
15664
  const d2 = new Date(iso);
15645
- const pad = (n2) => String(n2).padStart(2, "0");
15646
- return `${d2.getFullYear()}-${pad(d2.getMonth() + 1)}-${pad(d2.getDate())} ${pad(d2.getHours())}:${pad(d2.getMinutes())}:${pad(d2.getSeconds())}`;
15665
+ const pad2 = (n2) => String(n2).padStart(2, "0");
15666
+ return `${d2.getFullYear()}-${pad2(d2.getMonth() + 1)}-${pad2(d2.getDate())} ${pad2(d2.getHours())}:${pad2(d2.getMinutes())}:${pad2(d2.getSeconds())}`;
15647
15667
  } catch {
15648
15668
  return iso;
15649
15669
  }
@@ -16376,7 +16396,419 @@ Details: ${JSON.stringify(output)}` : "";
16376
16396
  return idx >= 0 ? trimmed.slice(idx + 1) : trimmed;
16377
16397
  }
16378
16398
 
16399
+ // node_modules/.pnpm/d3-dsv@3.0.1/node_modules/d3-dsv/src/dsv.js
16400
+ var EOL = {};
16401
+ var EOF = {};
16402
+ var QUOTE = 34;
16403
+ var NEWLINE = 10;
16404
+ var RETURN = 13;
16405
+ function objectConverter(columns) {
16406
+ return new Function("d", "return {" + columns.map(function(name, i2) {
16407
+ return JSON.stringify(name) + ": d[" + i2 + '] || ""';
16408
+ }).join(",") + "}");
16409
+ }
16410
+ function customConverter(columns, f2) {
16411
+ var object = objectConverter(columns);
16412
+ return function(row, i2) {
16413
+ return f2(object(row), i2, columns);
16414
+ };
16415
+ }
16416
+ function inferColumns(rows) {
16417
+ var columnSet = /* @__PURE__ */ Object.create(null), columns = [];
16418
+ rows.forEach(function(row) {
16419
+ for (var column in row) {
16420
+ if (!(column in columnSet)) {
16421
+ columns.push(columnSet[column] = column);
16422
+ }
16423
+ }
16424
+ });
16425
+ return columns;
16426
+ }
16427
+ function pad(value, width) {
16428
+ var s2 = value + "", length = s2.length;
16429
+ return length < width ? new Array(width - length + 1).join(0) + s2 : s2;
16430
+ }
16431
+ function formatYear(year) {
16432
+ return year < 0 ? "-" + pad(-year, 6) : year > 9999 ? "+" + pad(year, 6) : pad(year, 4);
16433
+ }
16434
+ function formatDate(date) {
16435
+ var hours = date.getUTCHours(), minutes = date.getUTCMinutes(), seconds = date.getUTCSeconds(), milliseconds = date.getUTCMilliseconds();
16436
+ return isNaN(date) ? "Invalid Date" : formatYear(date.getUTCFullYear(), 4) + "-" + pad(date.getUTCMonth() + 1, 2) + "-" + pad(date.getUTCDate(), 2) + (milliseconds ? "T" + pad(hours, 2) + ":" + pad(minutes, 2) + ":" + pad(seconds, 2) + "." + pad(milliseconds, 3) + "Z" : seconds ? "T" + pad(hours, 2) + ":" + pad(minutes, 2) + ":" + pad(seconds, 2) + "Z" : minutes || hours ? "T" + pad(hours, 2) + ":" + pad(minutes, 2) + "Z" : "");
16437
+ }
16438
+ function dsv_default(delimiter2) {
16439
+ var reFormat = new RegExp('["' + delimiter2 + "\n\r]"), DELIMITER = delimiter2.charCodeAt(0);
16440
+ function parse(text3, f2) {
16441
+ var convert, columns, rows = parseRows(text3, function(row, i2) {
16442
+ if (convert) return convert(row, i2 - 1);
16443
+ columns = row, convert = f2 ? customConverter(row, f2) : objectConverter(row);
16444
+ });
16445
+ rows.columns = columns || [];
16446
+ return rows;
16447
+ }
16448
+ function parseRows(text3, f2) {
16449
+ var rows = [], N = text3.length, I = 0, n2 = 0, t2, eof = N <= 0, eol = false;
16450
+ if (text3.charCodeAt(N - 1) === NEWLINE) --N;
16451
+ if (text3.charCodeAt(N - 1) === RETURN) --N;
16452
+ function token() {
16453
+ if (eof) return EOF;
16454
+ if (eol) return eol = false, EOL;
16455
+ var i2, j = I, c2;
16456
+ if (text3.charCodeAt(j) === QUOTE) {
16457
+ while (I++ < N && text3.charCodeAt(I) !== QUOTE || text3.charCodeAt(++I) === QUOTE) ;
16458
+ if ((i2 = I) >= N) eof = true;
16459
+ else if ((c2 = text3.charCodeAt(I++)) === NEWLINE) eol = true;
16460
+ else if (c2 === RETURN) {
16461
+ eol = true;
16462
+ if (text3.charCodeAt(I) === NEWLINE) ++I;
16463
+ }
16464
+ return text3.slice(j + 1, i2 - 1).replace(/""/g, '"');
16465
+ }
16466
+ while (I < N) {
16467
+ if ((c2 = text3.charCodeAt(i2 = I++)) === NEWLINE) eol = true;
16468
+ else if (c2 === RETURN) {
16469
+ eol = true;
16470
+ if (text3.charCodeAt(I) === NEWLINE) ++I;
16471
+ } else if (c2 !== DELIMITER) continue;
16472
+ return text3.slice(j, i2);
16473
+ }
16474
+ return eof = true, text3.slice(j, N);
16475
+ }
16476
+ while ((t2 = token()) !== EOF) {
16477
+ var row = [];
16478
+ while (t2 !== EOL && t2 !== EOF) row.push(t2), t2 = token();
16479
+ if (f2 && (row = f2(row, n2++)) == null) continue;
16480
+ rows.push(row);
16481
+ }
16482
+ return rows;
16483
+ }
16484
+ function preformatBody(rows, columns) {
16485
+ return rows.map(function(row) {
16486
+ return columns.map(function(column) {
16487
+ return formatValue2(row[column]);
16488
+ }).join(delimiter2);
16489
+ });
16490
+ }
16491
+ function format2(rows, columns) {
16492
+ if (columns == null) columns = inferColumns(rows);
16493
+ return [columns.map(formatValue2).join(delimiter2)].concat(preformatBody(rows, columns)).join("\n");
16494
+ }
16495
+ function formatBody(rows, columns) {
16496
+ if (columns == null) columns = inferColumns(rows);
16497
+ return preformatBody(rows, columns).join("\n");
16498
+ }
16499
+ function formatRows(rows) {
16500
+ return rows.map(formatRow).join("\n");
16501
+ }
16502
+ function formatRow(row) {
16503
+ return row.map(formatValue2).join(delimiter2);
16504
+ }
16505
+ function formatValue2(value) {
16506
+ return value == null ? "" : value instanceof Date ? formatDate(value) : reFormat.test(value += "") ? '"' + value.replace(/"/g, '""') + '"' : value;
16507
+ }
16508
+ return {
16509
+ parse,
16510
+ parseRows,
16511
+ format: format2,
16512
+ formatBody,
16513
+ formatRows,
16514
+ formatRow,
16515
+ formatValue: formatValue2
16516
+ };
16517
+ }
16518
+
16519
+ // node_modules/.pnpm/d3-dsv@3.0.1/node_modules/d3-dsv/src/csv.js
16520
+ var csv = dsv_default(",");
16521
+ var csvParse = csv.parse;
16522
+ var csvParseRows = csv.parseRows;
16523
+ var csvFormat = csv.format;
16524
+ var csvFormatBody = csv.formatBody;
16525
+ var csvFormatRows = csv.formatRows;
16526
+ var csvFormatRow = csv.formatRow;
16527
+ var csvFormatValue = csv.formatValue;
16528
+
16529
+ // node_modules/.pnpm/d3-dsv@3.0.1/node_modules/d3-dsv/src/tsv.js
16530
+ var tsv = dsv_default(" ");
16531
+ var tsvParse = tsv.parse;
16532
+ var tsvParseRows = tsv.parseRows;
16533
+ var tsvFormat = tsv.format;
16534
+ var tsvFormatBody = tsv.formatBody;
16535
+ var tsvFormatRows = tsv.formatRows;
16536
+ var tsvFormatRow = tsv.formatRow;
16537
+ var tsvFormatValue = tsv.formatValue;
16538
+
16539
+ // web-src/views/source-preview-i18n.ts
16540
+ var DELIMITED_PREVIEW_TEXT = {
16541
+ en: (format2) => ({
16542
+ searchLabel: `Search all ${format2.toUpperCase()} columns`,
16543
+ searchPlaceholder: "Search all columns…",
16544
+ resetLabel: "Reset",
16545
+ resetAction: "Clear search, column filters, and sorting",
16546
+ resultCount: (visible, total) => `${visible} / ${total} rows`,
16547
+ resultCountLabel: `Visible ${format2.toUpperCase()} rows`,
16548
+ columnLabel: (index) => `Column ${index}`,
16549
+ columnFilterLabel: (column) => `Filter ${column}`,
16550
+ columnFilterPlaceholder: "Filter…",
16551
+ sortAscending: (column) => `Sort ${column} ascending`,
16552
+ sortDescending: (column) => `Sort ${column} descending`,
16553
+ clearSort: (column) => `Clear sorting for ${column}`,
16554
+ noMatches: "No rows match the current filters."
16555
+ }),
16556
+ ja: (format2) => ({
16557
+ searchLabel: `${format2.toUpperCase()}の全列を検索`,
16558
+ searchPlaceholder: "全列を検索…",
16559
+ resetLabel: "リセット",
16560
+ resetAction: "検索、列フィルタ、並べ替えを解除",
16561
+ resultCount: (visible, total) => `${visible} / ${total} 行`,
16562
+ resultCountLabel: `表示中の${format2.toUpperCase()}行数`,
16563
+ columnLabel: (index) => `列 ${index}`,
16564
+ columnFilterLabel: (column) => `${column}を絞り込み`,
16565
+ columnFilterPlaceholder: "絞り込み…",
16566
+ sortAscending: (column) => `${column}を昇順に並べ替え`,
16567
+ sortDescending: (column) => `${column}を降順に並べ替え`,
16568
+ clearSort: (column) => `${column}の並べ替えを解除`,
16569
+ noMatches: "現在の条件に一致する行はありません。"
16570
+ })
16571
+ };
16572
+ function delimitedPreviewText(language, format2) {
16573
+ return DELIMITED_PREVIEW_TEXT[language](format2);
16574
+ }
16575
+
16379
16576
  // web-src/views/source-preview-elements.ts
16577
+ function renderDelimitedPreview(text3, format2, getText = () => delimitedPreviewText("en", format2)) {
16578
+ const preview = Object.assign(
16579
+ document.createElement("div"),
16580
+ { localize: () => void 0 }
16581
+ );
16582
+ preview.className = "gdp-csv-preview";
16583
+ const parseRows = format2 === "tsv" ? tsvParseRows : csvParseRows;
16584
+ const rows = parseRows(text3.charCodeAt(0) === 65279 ? text3.slice(1) : text3);
16585
+ if (rows.length === 0) return preview;
16586
+ const columnCount = rows.reduce(
16587
+ (largest, row) => Math.max(largest, row.length),
16588
+ 0
16589
+ );
16590
+ const dataRows = rows.slice(1).map((row, index) => ({
16591
+ sourceIndex: index + 1,
16592
+ cells: Array.from(
16593
+ { length: columnCount },
16594
+ (_, column) => row[column] ?? ""
16595
+ )
16596
+ }));
16597
+ const collator = new Intl.Collator(void 0, {
16598
+ numeric: true,
16599
+ sensitivity: "base"
16600
+ });
16601
+ const columnFilters = Array.from({ length: columnCount }, () => "");
16602
+ let sortColumn = null;
16603
+ let sortDirection = null;
16604
+ let visibleCount = dataRows.length;
16605
+ let emptyCell = null;
16606
+ const shell = document.createElement("section");
16607
+ shell.className = "gdp-csv-shell";
16608
+ const toolbar = document.createElement("div");
16609
+ toolbar.className = "gdp-csv-toolbar";
16610
+ const searchIcon = document.createElement("span");
16611
+ searchIcon.className = "gdp-csv-search-icon";
16612
+ searchIcon.setAttribute("aria-hidden", "true");
16613
+ searchIcon.innerHTML = iconSvg("octicon-search", SEARCH_16_PATH);
16614
+ const search = document.createElement("input");
16615
+ search.type = "search";
16616
+ search.className = "gdp-csv-search";
16617
+ search.autocomplete = "off";
16618
+ search.spellcheck = false;
16619
+ const status = document.createElement("span");
16620
+ status.className = "gdp-csv-result-count";
16621
+ status.setAttribute("role", "status");
16622
+ status.setAttribute("aria-live", "polite");
16623
+ const reset = document.createElement("button");
16624
+ reset.type = "button";
16625
+ reset.className = "gdp-csv-reset";
16626
+ toolbar.append(searchIcon, search, status, reset);
16627
+ const table2 = document.createElement("table");
16628
+ table2.className = "gdp-csv-table";
16629
+ const thead = document.createElement("thead");
16630
+ const headRow = document.createElement("tr");
16631
+ const corner = document.createElement("th");
16632
+ corner.className = "gdp-csv-row-number";
16633
+ corner.setAttribute("aria-hidden", "true");
16634
+ headRow.appendChild(corner);
16635
+ const sortHeaders = [];
16636
+ for (let column = 0; column < columnCount; column++) {
16637
+ const th = document.createElement("th");
16638
+ th.scope = "col";
16639
+ const button = document.createElement("button");
16640
+ button.type = "button";
16641
+ button.className = "gdp-csv-sort-button";
16642
+ button.dataset.csvSortColumn = String(column);
16643
+ const label = document.createElement("span");
16644
+ label.textContent = rows[0][column] ?? "";
16645
+ button.appendChild(label);
16646
+ button.addEventListener("click", () => {
16647
+ if (sortColumn !== column) {
16648
+ sortColumn = column;
16649
+ sortDirection = "asc";
16650
+ } else if (sortDirection === "asc") {
16651
+ sortDirection = "desc";
16652
+ } else if (sortDirection === "desc") {
16653
+ sortColumn = null;
16654
+ sortDirection = null;
16655
+ } else {
16656
+ sortDirection = "asc";
16657
+ }
16658
+ renderBody();
16659
+ button.focus();
16660
+ });
16661
+ th.appendChild(button);
16662
+ headRow.appendChild(th);
16663
+ sortHeaders.push({ cell: th, button, label });
16664
+ }
16665
+ thead.appendChild(headRow);
16666
+ const filterRow = document.createElement("tr");
16667
+ filterRow.className = "gdp-csv-filter-row";
16668
+ const filterCorner = document.createElement("th");
16669
+ filterCorner.className = "gdp-csv-row-number";
16670
+ filterCorner.setAttribute("aria-hidden", "true");
16671
+ filterRow.appendChild(filterCorner);
16672
+ const filterInputs = [];
16673
+ for (let column = 0; column < columnCount; column++) {
16674
+ const th = document.createElement("th");
16675
+ const input2 = document.createElement("input");
16676
+ input2.type = "search";
16677
+ input2.className = "gdp-csv-column-filter";
16678
+ input2.dataset.csvColumnFilter = String(column);
16679
+ input2.autocomplete = "off";
16680
+ input2.spellcheck = false;
16681
+ input2.addEventListener("input", () => {
16682
+ columnFilters[column] = input2.value;
16683
+ renderBody();
16684
+ });
16685
+ input2.addEventListener("keydown", (event) => {
16686
+ if (isImeComposing(event) || event.key !== "Escape" || !input2.value)
16687
+ return;
16688
+ input2.value = "";
16689
+ columnFilters[column] = "";
16690
+ renderBody();
16691
+ });
16692
+ th.appendChild(input2);
16693
+ filterRow.appendChild(th);
16694
+ filterInputs.push(input2);
16695
+ }
16696
+ thead.appendChild(filterRow);
16697
+ table2.appendChild(thead);
16698
+ const tbody = document.createElement("tbody");
16699
+ table2.appendChild(tbody);
16700
+ shell.append(toolbar, table2);
16701
+ preview.appendChild(shell);
16702
+ function normalized(value) {
16703
+ return value.trim().toLocaleLowerCase();
16704
+ }
16705
+ function activeStateCount() {
16706
+ return (normalized(search.value) ? 1 : 0) + columnFilters.filter((value) => normalized(value)).length + (sortColumn === null ? 0 : 1);
16707
+ }
16708
+ function localizedColumnLabel(column, textValue) {
16709
+ return rows[0][column] || textValue.columnLabel(column + 1);
16710
+ }
16711
+ function syncLocalizedText() {
16712
+ const textValue = getText();
16713
+ toolbar.setAttribute("aria-label", textValue.searchLabel);
16714
+ search.placeholder = textValue.searchPlaceholder;
16715
+ search.setAttribute("aria-label", textValue.searchLabel);
16716
+ reset.textContent = textValue.resetLabel;
16717
+ reset.title = textValue.resetAction;
16718
+ reset.setAttribute("aria-label", textValue.resetAction);
16719
+ status.textContent = textValue.resultCount(visibleCount, dataRows.length);
16720
+ status.setAttribute("aria-label", textValue.resultCountLabel);
16721
+ if (emptyCell) emptyCell.textContent = textValue.noMatches;
16722
+ sortHeaders.forEach(({ cell, button }, column) => {
16723
+ const columnLabel = localizedColumnLabel(column, textValue);
16724
+ const active = sortColumn === column ? sortDirection : null;
16725
+ cell.setAttribute(
16726
+ "aria-sort",
16727
+ active === "asc" ? "ascending" : active === "desc" ? "descending" : "none"
16728
+ );
16729
+ button.dataset.sortDirection = active ?? "none";
16730
+ const action = active === "asc" ? textValue.sortDescending(columnLabel) : active === "desc" ? textValue.clearSort(columnLabel) : textValue.sortAscending(columnLabel);
16731
+ button.title = action;
16732
+ button.setAttribute("aria-label", action);
16733
+ });
16734
+ filterInputs.forEach((input2, column) => {
16735
+ const columnLabel = localizedColumnLabel(column, textValue);
16736
+ input2.placeholder = textValue.columnFilterPlaceholder;
16737
+ input2.setAttribute(
16738
+ "aria-label",
16739
+ textValue.columnFilterLabel(columnLabel)
16740
+ );
16741
+ });
16742
+ }
16743
+ function renderBody() {
16744
+ const globalQuery = normalized(search.value);
16745
+ const filters = columnFilters.map(normalized);
16746
+ const filtered = dataRows.filter(
16747
+ (row) => (!globalQuery || row.cells.some(
16748
+ (cell) => cell.toLocaleLowerCase().includes(globalQuery)
16749
+ )) && filters.every(
16750
+ (filter, column) => !filter || row.cells[column].toLocaleLowerCase().includes(filter)
16751
+ )
16752
+ );
16753
+ const visibleRows = sortColumn === null || sortDirection === null ? filtered : [...filtered].sort((a2, b2) => {
16754
+ const aValue = a2.cells[sortColumn];
16755
+ const bValue = b2.cells[sortColumn];
16756
+ if (!aValue && bValue) return 1;
16757
+ if (aValue && !bValue) return -1;
16758
+ const compared = collator.compare(aValue, bValue);
16759
+ if (compared === 0) return a2.sourceIndex - b2.sourceIndex;
16760
+ return sortDirection === "asc" ? compared : -compared;
16761
+ });
16762
+ tbody.replaceChildren();
16763
+ emptyCell = null;
16764
+ for (const row of visibleRows) {
16765
+ const tr = document.createElement("tr");
16766
+ const rowNumber = document.createElement("th");
16767
+ rowNumber.className = "gdp-csv-row-number";
16768
+ rowNumber.scope = "row";
16769
+ rowNumber.textContent = String(row.sourceIndex);
16770
+ tr.appendChild(rowNumber);
16771
+ for (const value of row.cells) {
16772
+ const td = document.createElement("td");
16773
+ td.textContent = value;
16774
+ tr.appendChild(td);
16775
+ }
16776
+ tbody.appendChild(tr);
16777
+ }
16778
+ if (visibleRows.length === 0) {
16779
+ const tr = document.createElement("tr");
16780
+ tr.className = "gdp-csv-empty-row";
16781
+ emptyCell = document.createElement("td");
16782
+ emptyCell.colSpan = columnCount + 1;
16783
+ tr.appendChild(emptyCell);
16784
+ tbody.appendChild(tr);
16785
+ }
16786
+ visibleCount = visibleRows.length;
16787
+ reset.disabled = activeStateCount() === 0;
16788
+ syncLocalizedText();
16789
+ }
16790
+ search.addEventListener("input", renderBody);
16791
+ search.addEventListener("keydown", (event) => {
16792
+ if (isImeComposing(event) || event.key !== "Escape" || !search.value)
16793
+ return;
16794
+ search.value = "";
16795
+ renderBody();
16796
+ });
16797
+ reset.addEventListener("click", () => {
16798
+ search.value = "";
16799
+ columnFilters.fill("");
16800
+ filterInputs.forEach((input2) => {
16801
+ input2.value = "";
16802
+ });
16803
+ sortColumn = null;
16804
+ sortDirection = null;
16805
+ renderBody();
16806
+ search.focus();
16807
+ });
16808
+ preview.localize = syncLocalizedText;
16809
+ renderBody();
16810
+ return preview;
16811
+ }
16380
16812
  function renderHtmlPreviewFrame(title, html, extraClass = "") {
16381
16813
  const preview = document.createElement("div");
16382
16814
  preview.className = ["gdp-html-preview", extraClass].filter(Boolean).join(" ");
@@ -17106,6 +17538,8 @@ Details: ${JSON.stringify(output)}` : "";
17106
17538
  data.text,
17107
17539
  "s3-html-preview"
17108
17540
  );
17541
+ } else if (previewKind === "csv" || previewKind === "tsv") {
17542
+ body = renderDelimitedPreview(data.text, previewKind);
17109
17543
  } else if (previewKind === "markdown") {
17110
17544
  body = await renderMarkdownPreview(
17111
17545
  data.text,
@@ -18166,8 +18600,8 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
18166
18600
  }
18167
18601
  function formatTime2(timestamp) {
18168
18602
  const d2 = new Date(timestamp);
18169
- const pad = (n2) => String(n2).padStart(2, "0");
18170
- return `${pad(d2.getHours())}:${pad(d2.getMinutes())}:${pad(d2.getSeconds())}`;
18603
+ const pad2 = (n2) => String(n2).padStart(2, "0");
18604
+ return `${pad2(d2.getHours())}:${pad2(d2.getMinutes())}:${pad2(d2.getSeconds())}`;
18171
18605
  }
18172
18606
 
18173
18607
  // web-src/views/database/snapshot-view.ts
@@ -26510,8 +26944,8 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
26510
26944
  const t2 = Date.parse(iso);
26511
26945
  if (!Number.isFinite(t2)) return iso;
26512
26946
  const d2 = new Date(t2);
26513
- const pad = (n2) => String(n2).padStart(2, "0");
26514
- return `${d2.getFullYear()}-${pad(d2.getMonth() + 1)}-${pad(d2.getDate())} ${pad(d2.getHours())}:${pad(d2.getMinutes())}`;
26947
+ const pad2 = (n2) => String(n2).padStart(2, "0");
26948
+ return `${d2.getFullYear()}-${pad2(d2.getMonth() + 1)}-${pad2(d2.getDate())} ${pad2(d2.getHours())}:${pad2(d2.getMinutes())}`;
26515
26949
  }
26516
26950
  function displayWhen(iso) {
26517
26951
  const relative = relativeWhen(iso);
@@ -28054,6 +28488,10 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
28054
28488
  kind: "paragraph",
28055
28489
  text: "A file detail page exposes up to four tabs — Preview, Code, Blame, History. For text files Code is the default and ?preview=1 opts in to the Markdown / HTML preview; media files (images, video, audio, PDF) show a Preview tab only, with no Code tab. Blame and History have their own canonical URLs (view=blame, view=history) so deep links and the browser back/forward stay in sync, and they keep the Repository sidebar visible. Opening another file from the repository tree keeps the active tab (a file that cannot be previewed falls back to Code)."
28056
28490
  },
28491
+ {
28492
+ kind: "paragraph",
28493
+ text: "CSV and TSV previews provide all-column search, per-column filters, three-state column sorting (ascending, descending, then source order), a visible-row count, and a reset action. Filtering and sorting keep each row's original file row number."
28494
+ },
28057
28495
  {
28058
28496
  kind: "paragraph",
28059
28497
  text: "Relative links inside a Markdown preview lead to the same destinations as they do on GitHub: another Markdown file opens its file page, an #anchor opens the preview and scrolls to that heading, a non-Markdown file opens in the Code view, and a link to a directory opens that folder in the repository tree."
@@ -28784,6 +29222,10 @@ code-viewer annotate add-db --db app.db --tab query \\
28784
29222
  kind: "paragraph",
28785
29223
  text: "ファイル詳細ページには最大 4 つのタブ (Preview / Code / Blame / History) があります。テキストファイルは Code がデフォルトで、?preview=1 を付けると Markdown / HTML プレビューに切り替わります。画像・動画・音声・PDF などのメディアファイルは Preview タブのみ表示され、Code タブは表示されません。Blame と History はそれぞれ専用 URL (view=blame, view=history) を持つため、ディープリンクとブラウザの戻る / 進むが同期し、いずれも Repository サイドバーは表示されたままです。ツリーから別のファイルを開いても選択中のタブは維持されます (プレビューできないファイルでは Code に戻ります)。"
28786
29224
  },
29225
+ {
29226
+ kind: "paragraph",
29227
+ text: "CSV・TSVプレビューでは、全列検索、列ごとの絞り込み、昇順・降順・元の順番の3段階ソート、表示件数、リセットを利用できます。絞り込みや並べ替えの後も、各行には元ファイル上の行番号が表示されます。"
29228
+ },
28787
29229
  {
28788
29230
  kind: "paragraph",
28789
29231
  text: "Markdown プレビュー内の相対リンクは GitHub と同じ行き先に解決されます。別の Markdown ファイルはそのファイルページを開き、#見出し 付きのリンクはプレビューを開いて該当見出しまでスクロールし、Markdown 以外のファイルは Code ビュー、ディレクトリへのリンクはリポジトリツリーのそのフォルダを開きます。"
@@ -32497,8 +32939,8 @@ code-viewer annotate add-db --db app.db --tab query \\
32497
32939
  const t2 = Date.parse(iso);
32498
32940
  if (!Number.isFinite(t2)) return iso;
32499
32941
  const d2 = new Date(t2);
32500
- const pad = (n2) => String(n2).padStart(2, "0");
32501
- return `${d2.getFullYear()}-${pad(d2.getMonth() + 1)}-${pad(d2.getDate())} ${pad(d2.getHours())}:${pad(d2.getMinutes())}`;
32942
+ const pad2 = (n2) => String(n2).padStart(2, "0");
32943
+ return `${d2.getFullYear()}-${pad2(d2.getMonth() + 1)}-${pad2(d2.getDate())} ${pad2(d2.getHours())}:${pad2(d2.getMinutes())}`;
32502
32944
  }
32503
32945
  function displayWhen(iso) {
32504
32946
  const relative = relativeWhen(iso);
@@ -36872,7 +37314,8 @@ code-viewer annotate add-db --db app.db --tab query \\
36872
37314
  setViewFileButtonState,
36873
37315
  scrollMainPanel,
36874
37316
  focusMainSurface,
36875
- isPaletteOpen
37317
+ isPaletteOpen,
37318
+ getLanguage
36876
37319
  } = deps;
36877
37320
  function markdownLinkNavigationDeps() {
36878
37321
  return {
@@ -37189,15 +37632,10 @@ code-viewer annotate add-db --db app.db --tab query \\
37189
37632
  function setPreferredSourceTab(tab) {
37190
37633
  PREFERRED_SOURCE_TAB = tab;
37191
37634
  }
37192
- function consumePreferredSourceTab(previewable) {
37193
- if (!previewable) {
37194
- PREFERRED_SOURCE_TAB = null;
37195
- return "code";
37196
- }
37635
+ function preferredSourceTabFor(previewable) {
37636
+ if (!previewable) return "code";
37197
37637
  const routeTab = STATE.route.screen === "file" && STATE.route.view === "blob" && STATE.route.preview ? "preview" : "code";
37198
- const tab = PREFERRED_SOURCE_TAB || routeTab;
37199
- PREFERRED_SOURCE_TAB = null;
37200
- return tab;
37638
+ return PREFERRED_SOURCE_TAB || routeTab;
37201
37639
  }
37202
37640
  let SOURCE_REQ_SEQ = 0;
37203
37641
  let ACTIVE_SOURCE_LOAD = null;
@@ -37449,7 +37887,7 @@ code-viewer annotate add-db --db app.db --tab query \\
37449
37887
  if (signal?.aborted) return false;
37450
37888
  const previewable = isPreviewableSource(target.path);
37451
37889
  const previewKind = sourcePreviewKind(target.path);
37452
- const initialSourceTab = consumePreferredSourceTab(previewable);
37890
+ const initialSourceTab = preferredSourceTabFor(previewable);
37453
37891
  const tabsHost = card.querySelector(".gdp-file-detail-tabs");
37454
37892
  if (usesVirtualSource) {
37455
37893
  const virtualCode = renderVirtualSource(
@@ -37471,7 +37909,11 @@ code-viewer annotate add-db --db app.db --tab query \\
37471
37909
  tabsHost.hidden = false;
37472
37910
  tabsHost.replaceChildren(tabs3);
37473
37911
  }
37474
- let preview = previewKind === "html" ? renderHtmlPreview(target, textValue) : await (deps.renderMarkdownPreview ?? renderMarkdownPreview)(
37912
+ let preview = previewKind === "html" ? renderHtmlPreview(target, textValue) : previewKind === "csv" || previewKind === "tsv" ? renderDelimitedPreview(
37913
+ textValue,
37914
+ previewKind,
37915
+ () => delimitedPreviewText(getLanguage(), previewKind)
37916
+ ) : await (deps.renderMarkdownPreview ?? renderMarkdownPreview)(
37475
37917
  textValue,
37476
37918
  target,
37477
37919
  {
@@ -37484,7 +37926,7 @@ code-viewer annotate add-db --db app.db --tab query \\
37484
37926
  preview.dataset.sourcePane = "preview";
37485
37927
  let previewHighlightScheduled = false;
37486
37928
  const ensurePreviewHighlight = () => {
37487
- if (previewKind === "html" || !STATE.syntaxHighlight || previewHighlightScheduled)
37929
+ if (previewKind !== "markdown" || !STATE.syntaxHighlight || previewHighlightScheduled)
37488
37930
  return;
37489
37931
  previewHighlightScheduled = true;
37490
37932
  scheduleMarkdownPreviewHighlight(
@@ -37591,7 +38033,11 @@ code-viewer annotate add-db --db app.db --tab query \\
37591
38033
  tabsHost.replaceChildren(tabs);
37592
38034
  }
37593
38035
  if (previewable) {
37594
- let preview = previewKind === "html" ? renderHtmlPreview(target, textValue) : await (deps.renderMarkdownPreview ?? renderMarkdownPreview)(
38036
+ let preview = previewKind === "html" ? renderHtmlPreview(target, textValue) : previewKind === "csv" || previewKind === "tsv" ? renderDelimitedPreview(
38037
+ textValue,
38038
+ previewKind,
38039
+ () => delimitedPreviewText(getLanguage(), previewKind)
38040
+ ) : await (deps.renderMarkdownPreview ?? renderMarkdownPreview)(
37595
38041
  textValue,
37596
38042
  target,
37597
38043
  {
@@ -37604,7 +38050,7 @@ code-viewer annotate add-db --db app.db --tab query \\
37604
38050
  preview.dataset.sourcePane = "preview";
37605
38051
  let previewHighlightScheduled = false;
37606
38052
  const ensurePreviewHighlight = () => {
37607
- if (previewKind === "html" || !STATE.syntaxHighlight || previewHighlightScheduled)
38053
+ if (previewKind !== "markdown" || !STATE.syntaxHighlight || previewHighlightScheduled)
37608
38054
  return;
37609
38055
  previewHighlightScheduled = true;
37610
38056
  scheduleMarkdownPreviewHighlight(
@@ -38770,6 +39216,11 @@ code-viewer annotate add-db --db app.db --tab query \\
38770
39216
  function handleVirtualSourcePagingKeydown(e2) {
38771
39217
  handleVirtualSourcePagingKey(e2, e2.target);
38772
39218
  }
39219
+ function localize() {
39220
+ document.querySelectorAll(".gdp-csv-preview").forEach((preview) => {
39221
+ preview.localize();
39222
+ });
39223
+ }
38773
39224
  return {
38774
39225
  renderStandaloneSource,
38775
39226
  applySourceRouteToShell,
@@ -38804,7 +39255,8 @@ code-viewer annotate add-db --db app.db --tab query \\
38804
39255
  loadSourceShikiHighlighter,
38805
39256
  sourceShikiLines,
38806
39257
  shouldVirtualizeSource,
38807
- inferLang
39258
+ inferLang,
39259
+ localize
38808
39260
  };
38809
39261
  }
38810
39262
 
@@ -39746,17 +40198,6 @@ code-viewer annotate add-db --db app.db --tab query \\
39746
40198
  return null;
39747
40199
  }
39748
40200
 
39749
- // web-src/core/lazy-bundle.ts
39750
- function createBundleLoader(bundleFile, init) {
39751
- let pending = null;
39752
- return () => {
39753
- if (!pending) {
39754
- pending = import(`/${bundleFile}`).then((mod) => init ? init(mod) : mod).catch(() => null);
39755
- }
39756
- return pending;
39757
- };
39758
- }
39759
-
39760
40201
  // web-src/core/xterm-loader.ts
39761
40202
  var loadXterm = createBundleLoader("xterm.js");
39762
40203
 
@@ -42833,7 +43274,8 @@ ${formatErrorDetail(error2)}`);
42833
43274
  setViewFileButtonState: (button, sourceMode) => DIFF_VIEW.setViewFileButtonState(button, sourceMode),
42834
43275
  scrollMainPanel,
42835
43276
  focusMainSurface,
42836
- isPaletteOpen: () => SEARCH_PALETTE.isPaletteOpen()
43277
+ isPaletteOpen: () => SEARCH_PALETTE.isPaletteOpen(),
43278
+ getLanguage: () => STATE.language
42837
43279
  });
42838
43280
  const {
42839
43281
  renderStandaloneSource,
@@ -43793,6 +44235,7 @@ ${formatErrorDetail(error2)}`);
43793
44235
  relocalizeHistory?.();
43794
44236
  relocalizeJournal?.();
43795
44237
  relocalizeViewerSettings?.();
44238
+ SOURCE_VIEW.localize();
43796
44239
  setElementText(".annotation-panel-head strong", text3.annotations.title);
43797
44240
  const followLabel = document.querySelector(
43798
44241
  ".annotation-follow-label"