@aicayzer/inkkit 0.1.4 → 0.1.5

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.
@@ -28357,6 +28357,10 @@ var defaultLabels = {
28357
28357
  sourceEditor: "Markdown source editor",
28358
28358
  placeholder: "Start typing…",
28359
28359
  copyCode: "Copy",
28360
+ codeLanguage: "Code language",
28361
+ codeLanguageSearch: "Search languages",
28362
+ codeAuto: "Auto",
28363
+ codePlainText: "Plain text",
28360
28364
  expandCallout: "Expand",
28361
28365
  collapseCallout: "Collapse",
28362
28366
  diagramRendering: "Rendering diagram…",
@@ -44991,6 +44995,16 @@ function finalCodeEnding(doc) {
44991
44995
  last = last.lastChild;
44992
44996
  }
44993
44997
  }
44998
+ /** Change only the language word, retaining fence spelling and extra metadata. */
44999
+ function languageFence(value, language) {
45000
+ const fence = readFence(value);
45001
+ if (!fence) return null;
45002
+ const match = /^(\s*)(\S+)?([\s\S]*)$/.exec(fence.info);
45003
+ return {
45004
+ ...fence,
45005
+ info: match[1] + language + match[3]
45006
+ };
45007
+ }
44994
45008
  //#endregion
44995
45009
  //#region src/literals.ts
44996
45010
  var unsupported = /* @__PURE__ */ new Set([
@@ -45027,6 +45041,7 @@ function containsUnsupported(node, images, inline = false) {
45027
45041
  return unsupported.has(node.type) && !(images && node.type === "image") || "children" in node && node.children.some((child) => containsUnsupported(child, images, inline || node.type === "paragraph" || node.type === "heading"));
45028
45042
  }
45029
45043
  function containsUnresolved(node, source) {
45044
+ if (node.type === "link") return false;
45030
45045
  if (node.type === "text") {
45031
45046
  const start = node.position?.start.offset;
45032
45047
  const end = node.position?.end.offset;
@@ -47375,7 +47390,7 @@ function completedAngle(tr, chars, from, to) {
47375
47390
  let start = end - 1;
47376
47391
  for (; start >= 0; start--) {
47377
47392
  const char = chars[start];
47378
- if (!char || char.marks.some((mark) => mark.type.spec.code) || char.link && char.form !== "literal" || !sameMarks(char.marks, closing.marks) || /[\s>]/.test(char.text)) return void 0;
47393
+ if (!char || char.marks.some((mark) => mark.type.spec.code) || char.link && char.form !== "literal" || char.text !== "<" && !sameMarks(char.marks, closing.marks) || /[\s>]/.test(char.text)) return void 0;
47379
47394
  if (char.text === "<") break;
47380
47395
  }
47381
47396
  if (start < 0) return void 0;
@@ -47550,7 +47565,12 @@ function linked(tr, blocks) {
47550
47565
  }
47551
47566
  function readsBack(ctx, tr, pos) {
47552
47567
  const block = tr.doc.nodeAt(pos);
47553
- const doc = tr.doc.type.create(null, [tr.doc.type.schema.nodes.paragraph.create(null, block.content)]);
47568
+ const references = /* @__PURE__ */ new Set();
47569
+ block.descendants((node) => {
47570
+ for (const mark of node.marks) if (mark.type.name === "link" && mark.attrs.identifier) references.add(normaliseLabel(String(mark.attrs.identifier)));
47571
+ });
47572
+ const definitions = references.size ? [...referenceDefinitions(tr.doc)].filter(([identifier]) => references.has(identifier)).map(([, definition]) => definition.node) : [];
47573
+ const doc = tr.doc.type.create(null, [tr.doc.type.schema.nodes.paragraph.create(null, block.content), ...definitions]);
47554
47574
  return semanticSignature(ctx.get(parserCtx)(serialize(ctx, doc))) === semanticSignature(doc);
47555
47575
  }
47556
47576
  var textblocks = (doc, from, to) => {
@@ -50584,16 +50604,16 @@ var literalReread = $prose((ctx) => new Plugin({
50584
50604
  //#region src/decorations.ts
50585
50605
  var copyIcon = "<svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"5.5\" y=\"5.5\" width=\"8\" height=\"8\" rx=\"1.5\"/><path d=\"M10.5 5.5v-2a1 1 0 0 0-1-1h-6a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2\"/></svg>";
50586
50606
  var doneIcon = "<svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3.5 8.5l3 3 6-6.5\"/></svg>";
50587
- function copyButton(onCopy, label) {
50607
+ function copyButton(onCopy, label, text) {
50588
50608
  const button = document.createElement("button");
50589
50609
  button.type = "button";
50610
+ button.tabIndex = 0;
50590
50611
  button.className = "inkkit-copy";
50591
50612
  button.setAttribute("aria-label", label);
50592
50613
  button.innerHTML = copyIcon;
50593
50614
  button.addEventListener("mousedown", (event) => event.preventDefault());
50594
50615
  button.addEventListener("click", () => {
50595
- const code = button.closest("pre")?.querySelector("code");
50596
- onCopy(code?.textContent ?? "");
50616
+ onCopy(text());
50597
50617
  button.dataset.copied = "";
50598
50618
  button.innerHTML = doneIcon;
50599
50619
  window.setTimeout(() => {
@@ -50610,7 +50630,10 @@ function codeCopyPlugin(onCopy) {
50610
50630
  const widgets = [];
50611
50631
  state.doc.descendants((node, pos) => {
50612
50632
  if (node.type.name !== "code_block") return true;
50613
- widgets.push(Decoration.widget(pos + 1, () => copyButton(onCopy, editorLabels(ctx).copyCode), {
50633
+ widgets.push(Decoration.widget(pos + 1, (view, getPos) => copyButton(onCopy, editorLabels(ctx).copyCode, () => {
50634
+ const at = getPos();
50635
+ return at == null ? "" : view.state.doc.nodeAt(at - 1)?.textContent ?? "";
50636
+ }), {
50614
50637
  side: -1,
50615
50638
  key: "copy",
50616
50639
  ignoreSelection: true
@@ -50633,6 +50656,315 @@ var placeholderPlugin = $prose((ctx) => new Plugin({
50633
50656
  } }
50634
50657
  }));
50635
50658
  //#endregion
50659
+ //#region src/code-languages.ts
50660
+ var codeLanguages = [
50661
+ ["arduino", "Arduino"],
50662
+ ["bash", "Bash"],
50663
+ ["c", "C"],
50664
+ ["cpp", "C++"],
50665
+ ["csharp", "C#"],
50666
+ ["css", "CSS"],
50667
+ ["diff", "Diff"],
50668
+ ["go", "Go"],
50669
+ ["graphql", "GraphQL"],
50670
+ ["ini", "INI"],
50671
+ ["java", "Java"],
50672
+ ["javascript", "JavaScript"],
50673
+ ["json", "JSON"],
50674
+ ["kotlin", "Kotlin"],
50675
+ ["less", "Less"],
50676
+ ["lua", "Lua"],
50677
+ ["makefile", "Makefile"],
50678
+ ["markdown", "Markdown"],
50679
+ ["objectivec", "Objective-C"],
50680
+ ["perl", "Perl"],
50681
+ ["php", "PHP"],
50682
+ ["php-template", "PHP template"],
50683
+ ["python", "Python"],
50684
+ ["python-repl", "Python REPL"],
50685
+ ["r", "R"],
50686
+ ["ruby", "Ruby"],
50687
+ ["rust", "Rust"],
50688
+ ["scss", "SCSS"],
50689
+ ["shell", "Shell"],
50690
+ ["sql", "SQL"],
50691
+ ["swift", "Swift"],
50692
+ ["typescript", "TypeScript"],
50693
+ ["vbnet", "Visual Basic .NET"],
50694
+ ["wasm", "WebAssembly"],
50695
+ ["xml", "HTML / XML"],
50696
+ ["yaml", "YAML"]
50697
+ ];
50698
+ //#endregion
50699
+ //#region src/code-controls.ts
50700
+ var codeControlCtx = $ctx((operation) => operation(), "inkkitCodeControl");
50701
+ function codeControlsPlugin(visibleRect) {
50702
+ return $prose((ctx) => new Plugin({
50703
+ key: new PluginKey("codeControls"),
50704
+ props: { decorations(state) {
50705
+ const widgets = [];
50706
+ state.doc.descendants((node, pos) => {
50707
+ if (node.type.name !== "code_block") return true;
50708
+ const language = String(node.attrs.language ?? "");
50709
+ widgets.push(Decoration.widget(pos + 1, (view, getPos) => {
50710
+ const labels = editorLabels(ctx);
50711
+ const wrapper = document.createElement("span");
50712
+ wrapper.className = "inkkit-code-controls";
50713
+ const button = document.createElement("button");
50714
+ button.type = "button";
50715
+ button.tabIndex = 0;
50716
+ button.className = "inkkit-code-language";
50717
+ button.textContent = language === "text" || language === "plaintext" ? labels.codePlainText : codeLanguages.find(([value]) => value === language)?.[1] ?? (language || labels.codeAuto);
50718
+ button.setAttribute("aria-label", labels.codeLanguage);
50719
+ button.setAttribute("aria-haspopup", "dialog");
50720
+ button.setAttribute("aria-expanded", "false");
50721
+ wrapper.append(button);
50722
+ let popup;
50723
+ let restore;
50724
+ const close = (focus = false) => {
50725
+ popup?.remove();
50726
+ popup = void 0;
50727
+ restore?.();
50728
+ restore = void 0;
50729
+ button.setAttribute("aria-expanded", "false");
50730
+ if (focus) button.focus();
50731
+ };
50732
+ button.addEventListener("mousedown", (event) => event.preventDefault());
50733
+ button.addEventListener("click", () => {
50734
+ if (popup) {
50735
+ close();
50736
+ return;
50737
+ }
50738
+ const captured = view.state.doc;
50739
+ popup = document.createElement("span");
50740
+ popup.className = "inkkit-code-language-menu";
50741
+ popup.setAttribute("role", "dialog");
50742
+ popup.setAttribute("aria-label", labels.codeLanguage);
50743
+ popup.contentEditable = "false";
50744
+ const search = document.createElement("input");
50745
+ search.type = "search";
50746
+ search.placeholder = labels.codeLanguageSearch;
50747
+ search.setAttribute("aria-label", labels.codeLanguageSearch);
50748
+ const list = document.createElement("span");
50749
+ list.className = "inkkit-code-language-list";
50750
+ popup.append(search, list);
50751
+ const choices = [
50752
+ ["", labels.codeAuto],
50753
+ ["text", labels.codePlainText],
50754
+ ...codeLanguages
50755
+ ];
50756
+ if (language && !choices.some(([value]) => value === language)) choices.push([language, language]);
50757
+ const render = () => {
50758
+ list.replaceChildren();
50759
+ for (const [value, name] of choices) {
50760
+ if (!`${value} ${name}`.toLowerCase().includes(search.value.toLowerCase())) continue;
50761
+ const option = document.createElement("button");
50762
+ option.type = "button";
50763
+ option.textContent = name;
50764
+ option.setAttribute("aria-pressed", String(value === language));
50765
+ option.addEventListener("click", () => {
50766
+ close();
50767
+ if (view.state.doc !== captured) return;
50768
+ ctx.get(codeControlCtx.key)(() => {
50769
+ const at = getPos();
50770
+ if (at == null) return false;
50771
+ const position = at - 1;
50772
+ const current = view.state.doc.nodeAt(position);
50773
+ if (current?.type.name !== "code_block") return false;
50774
+ if (value === language) {
50775
+ view.focus();
50776
+ return false;
50777
+ }
50778
+ const transaction = view.state.tr.setNodeMarkup(position, void 0, {
50779
+ ...current.attrs,
50780
+ language: value,
50781
+ authoredFence: languageFence(current.attrs.authoredFence, value)
50782
+ });
50783
+ view.dispatch(closeHistory(transaction));
50784
+ view.dispatch(closeHistory(view.state.tr).setMeta("addToHistory", false));
50785
+ view.focus();
50786
+ return true;
50787
+ });
50788
+ });
50789
+ list.append(option);
50790
+ }
50791
+ };
50792
+ search.addEventListener("input", render);
50793
+ popup.addEventListener("keydown", (event) => {
50794
+ if (event.key === "Escape") {
50795
+ event.preventDefault();
50796
+ event.stopPropagation();
50797
+ close(true);
50798
+ }
50799
+ if (event.key === "ArrowDown") {
50800
+ event.preventDefault();
50801
+ const options = [...list.querySelectorAll("button")];
50802
+ options[(options.indexOf(document.activeElement) + 1) % options.length]?.focus();
50803
+ }
50804
+ if (event.key === "ArrowUp") {
50805
+ event.preventDefault();
50806
+ const options = [...list.querySelectorAll("button")];
50807
+ options[(options.indexOf(document.activeElement) - 1 + options.length) % options.length]?.focus();
50808
+ }
50809
+ if (event.key === "Enter" && event.target === search) {
50810
+ event.preventDefault();
50811
+ list.querySelector("button")?.click();
50812
+ }
50813
+ });
50814
+ wrapper.append(popup);
50815
+ render();
50816
+ const bounds = button.getBoundingClientRect();
50817
+ const safe = visibleRect();
50818
+ const left = Math.max(8, safe.left + 4);
50819
+ const right = Math.min(window.innerWidth - 8, safe.right - 4);
50820
+ const top = Math.max(8, safe.top + 4);
50821
+ const bottom = Math.min(window.innerHeight - 8, safe.bottom - 4);
50822
+ const below = Math.max(0, bottom - bounds.bottom - 4);
50823
+ const above = Math.max(0, bounds.top - top - 4);
50824
+ const height = Math.min(320, Math.max(below, above));
50825
+ popup.style.width = `${Math.max(0, Math.min(220, right - left))}px`;
50826
+ popup.style.maxHeight = `${height}px`;
50827
+ popup.style.left = `${Math.max(left, Math.min(bounds.right - 220, right - 220))}px`;
50828
+ const menuHeight = Math.min(height, popup.getBoundingClientRect().height);
50829
+ popup.style.top = `${Math.max(top, Math.min(below >= menuHeight ? bounds.bottom + 4 : bounds.top - menuHeight - 4, bottom - menuHeight))}px`;
50830
+ const outside = (event) => {
50831
+ if (!wrapper.contains(event.target)) close();
50832
+ };
50833
+ const scroll = (event) => {
50834
+ if (popup?.contains(event.target)) return;
50835
+ const current = button.getBoundingClientRect();
50836
+ if (current.top !== bounds.top || current.left !== bounds.left || current.bottom !== bounds.bottom || current.right !== bounds.right) close();
50837
+ };
50838
+ document.addEventListener("pointerdown", outside, true);
50839
+ window.addEventListener("scroll", scroll, true);
50840
+ restore = () => {
50841
+ document.removeEventListener("pointerdown", outside, true);
50842
+ window.removeEventListener("scroll", scroll, true);
50843
+ };
50844
+ button.setAttribute("aria-expanded", "true");
50845
+ render();
50846
+ search.focus({ preventScroll: true });
50847
+ });
50848
+ wrapper.cleanup = close;
50849
+ return wrapper;
50850
+ }, {
50851
+ side: -1,
50852
+ key: `language:${language}`,
50853
+ ignoreSelection: true,
50854
+ stopEvent: () => true,
50855
+ destroy: (dom) => dom.cleanup?.()
50856
+ }));
50857
+ return false;
50858
+ });
50859
+ return DecorationSet.create(state.doc, widgets);
50860
+ } },
50861
+ view: (view) => ({ update(next, previous) {
50862
+ if (next.state.doc !== previous.doc || !next.editable) view.dom.querySelectorAll(".inkkit-code-controls").forEach((element) => element.cleanup?.());
50863
+ } })
50864
+ }));
50865
+ }
50866
+ //#endregion
50867
+ //#region src/mode-selection.ts
50868
+ function modeSelectionMap(ctx, source, doc) {
50869
+ const points = [];
50870
+ const bom = source.startsWith("") ? 1 : 0;
50871
+ let text = "";
50872
+ const offsets = [];
50873
+ const ends = [];
50874
+ const append = (value, positions) => {
50875
+ for (let index = 0; index < value.length; index++) offsets[text.length + index] = positions[index];
50876
+ for (let index = 1; index <= value.length; index++) ends[text.length + index] = positions[index];
50877
+ text += value;
50878
+ };
50879
+ const visit = (node) => {
50880
+ if (node.type === "definition") return;
50881
+ if ("children" in node) {
50882
+ node.children.forEach((child) => visit(child));
50883
+ return;
50884
+ }
50885
+ const start = node.position?.start.offset;
50886
+ const end = node.position?.end.offset;
50887
+ if (start == null || end == null || !("value" in node)) return;
50888
+ const raw = source.slice(start + bom, end + bom);
50889
+ if (node.type === "text") {
50890
+ const decoded = decodedOffsets(raw, true);
50891
+ if (decoded) append(decoded.decoded, decoded.offsets.map((at) => at + start + bom));
50892
+ } else if (node.type === "inlineCode") {
50893
+ const exact = raw.indexOf(node.value);
50894
+ if (exact >= 0) {
50895
+ append(node.value, Array.from({ length: node.value.length + 1 }, (_, index) => start + bom + exact + index));
50896
+ return;
50897
+ }
50898
+ const ticks = /^`+/.exec(raw)?.[0].length ?? 0;
50899
+ let value = "";
50900
+ const positions = [];
50901
+ for (let index = ticks; index < raw.length - ticks; index++) {
50902
+ positions.push(start + bom + index);
50903
+ if (raw[index] === "\r" && raw[index + 1] === "\n") index++;
50904
+ value += /[\r\n]/.test(raw[index]) ? " " : raw[index];
50905
+ }
50906
+ positions.push(start + bom + raw.length - ticks);
50907
+ if (value.startsWith(" ") && value.endsWith(" ") && /[^ ]/.test(value)) {
50908
+ value = value.slice(1, -1);
50909
+ positions.shift();
50910
+ positions.pop();
50911
+ }
50912
+ append(value, positions);
50913
+ } else if (node.type === "code") {
50914
+ const lines = [...raw.matchAll(/([^\r\n]*)(\r\n|\r|\n|$)/g)];
50915
+ let line = /^(`{3,}|~{3,})/.test(raw) ? 1 : 0;
50916
+ const value = node.value.replace(/\r\n?/g, "\n");
50917
+ const positions = [];
50918
+ let offset = 0;
50919
+ for (const content of value.split("\n")) {
50920
+ while (line < lines.length && !lines[line][1].endsWith(content)) line++;
50921
+ const match = lines[line++];
50922
+ if (!match) return;
50923
+ const at = match.index + match[1].length - content.length;
50924
+ for (let index = 0; index <= content.length; index++) positions[offset + index] = start + bom + at + index;
50925
+ offset += content.length + 1;
50926
+ }
50927
+ append(value, positions);
50928
+ } else if (node.type === "html" || node.type === "inkkitLiteral") {
50929
+ const value = node.value;
50930
+ const at = raw.indexOf(value);
50931
+ if (at >= 0) append(value, Array.from({ length: value.length + 1 }, (_, index) => start + bom + at + index));
50932
+ }
50933
+ };
50934
+ const processor = ctx.get(remarkCtx);
50935
+ processor.runSync(processor.parse(source), { value: source }).children.forEach((node) => visit(node));
50936
+ let cursor = 0;
50937
+ doc.descendants((node, position) => {
50938
+ if ([
50939
+ "comment_inline",
50940
+ "comment_block",
50941
+ "reference_definition"
50942
+ ].includes(node.type.name)) return false;
50943
+ if (!node.isText) return true;
50944
+ const value = node.text;
50945
+ const at = text.indexOf(value, cursor);
50946
+ if (at < 0) return false;
50947
+ for (let index = 0; index <= value.length; index++) {
50948
+ const offset = index === value.length ? ends[at + index] : offsets[at + index];
50949
+ if (offset != null) points.push({
50950
+ formatted: position + index,
50951
+ source: offset
50952
+ });
50953
+ }
50954
+ cursor = at + value.length;
50955
+ return false;
50956
+ });
50957
+ const nearest = (position, from, to, bias = -1) => {
50958
+ let best;
50959
+ for (const point of points) if (!best || Math.abs(point[from] - position) < Math.abs(best[from] - position) || bias > 0 && Math.abs(point[from] - position) === Math.abs(best[from] - position)) best = point;
50960
+ return best?.[to] ?? (from === "formatted" ? 0 : 1);
50961
+ };
50962
+ return {
50963
+ source: (position, bias = -1) => nearest(position, "formatted", "source", bias),
50964
+ formatted: (offset) => nearest(offset, "source", "formatted")
50965
+ };
50966
+ }
50967
+ //#endregion
50636
50968
  //#region src/reference-clipboard.ts
50637
50969
  function key(node) {
50638
50970
  if (node.type.name === "reference_definition") return `link:${node.attrs.identifier}`;
@@ -56240,14 +56572,24 @@ var InkKitEditor = class InkKitEditor {
56240
56572
  expectOneOf(mode, editingModes, "mode");
56241
56573
  this.assertCurrent(expectedGeneration);
56242
56574
  if (this.formatType === "txt" || this.mode === mode) return false;
56575
+ const wasSource = this.literalSurface;
56576
+ const view = this.editor.ctx.get(editorViewCtx);
56577
+ const focused = wasSource ? this.plain.ownerDocument.activeElement === this.plain : view.hasFocus();
56578
+ const container = this.viewportContainer ?? this.root;
56579
+ const previousSurface = wasSource ? this.plain : container;
56580
+ const fraction = previousSurface.scrollTop / Math.max(1, previousSurface.scrollHeight - previousSurface.clientHeight);
56581
+ const left = previousSurface.scrollLeft;
56582
+ const sourceSelection = wasSource ? {
56583
+ anchor: this.plain.selectionDirection === "backward" ? this.plain.selectionEnd : this.plain.selectionStart,
56584
+ head: this.plain.selectionDirection === "backward" ? this.plain.selectionStart : this.plain.selectionEnd
56585
+ } : void 0;
56243
56586
  this.settleSource();
56244
56587
  this.undoneSteps = [];
56245
56588
  this.formattedUndone = 0;
56246
- const view = this.editor.ctx.get(editorViewCtx);
56247
- const focused = this.literalSurface ? this.plain.ownerDocument.activeElement === this.plain : view.hasFocus();
56248
- const container = this.viewportContainer ?? this.root;
56249
- const top = container.scrollTop, left = container.scrollLeft;
56250
56589
  const text = this.snapshot().text;
56590
+ const mapping = modeSelectionMap(this.editor.ctx, text, view.state.doc);
56591
+ const anchor = sourceSelection ? mapping.formatted(rawOffset(text, sourceSelection.anchor)) : normalizedOffset(text, mapping.source(view.state.selection.anchor, view.state.selection.anchor < view.state.selection.head ? 1 : -1));
56592
+ const head = sourceSelection ? mapping.formatted(rawOffset(text, sourceSelection.head)) : normalizedOffset(text, mapping.source(view.state.selection.head, view.state.selection.head < view.state.selection.anchor ? 1 : -1));
56251
56593
  this.mode = mode;
56252
56594
  this.session.modeChanged();
56253
56595
  this.cancelExports();
@@ -56255,8 +56597,8 @@ var InkKitEditor = class InkKitEditor {
56255
56597
  this.literalMatch = void 0;
56256
56598
  if (mode === "source") {
56257
56599
  this.plain.value = text;
56258
- this.plain.setSelectionRange(this.plain.value.length, this.plain.value.length);
56259
- }
56600
+ this.plain.setSelectionRange(Math.min(anchor, head), Math.max(anchor, head), anchor > head ? "backward" : "forward");
56601
+ } else view.dispatch(view.state.tr.setSelection(TextSelection.between(view.state.doc.resolve(Math.min(anchor, view.state.doc.content.size)), view.state.doc.resolve(Math.min(head, view.state.doc.content.size)))).setMeta("addToHistory", false));
56260
56602
  const suppressed = this.reportingSuppressed;
56261
56603
  this.reportingSuppressed = true;
56262
56604
  try {
@@ -56264,12 +56606,14 @@ var InkKitEditor = class InkKitEditor {
56264
56606
  } finally {
56265
56607
  this.reportingSuppressed = suppressed;
56266
56608
  }
56609
+ const surface = this.literalSurface ? this.plain : container;
56610
+ surface.scrollTop = fraction * Math.max(0, surface.scrollHeight - surface.clientHeight);
56611
+ surface.scrollLeft = left;
56267
56612
  if (focused) {
56268
56613
  if (this.literalSurface) this.plain.focus({ preventScroll: true });
56269
- else view.focus();
56614
+ else view.dom.focus({ preventScroll: true });
56615
+ this.revealCurrentSelection();
56270
56616
  }
56271
- container.scrollTop = top;
56272
- container.scrollLeft = left;
56273
56617
  this.publishCommandState();
56274
56618
  return true;
56275
56619
  }
@@ -56777,6 +57121,10 @@ var InkKitEditor = class InkKitEditor {
56777
57121
  ...defaultLabels,
56778
57122
  ...options.labels
56779
57123
  }));
57124
+ ctx.set(codeControlCtx.key, (operation) => instance.forPerson(() => instance.facadeCall(() => {
57125
+ instance.assertMutation();
57126
+ return !instance.literalSurface && operation();
57127
+ }), false));
56780
57128
  ctx.set(tableControlCtx.key, (operation) => instance.forPerson(() => instance.facadeCall(() => {
56781
57129
  instance.assertMutation();
56782
57130
  return !instance.literalSurface && operation();
@@ -56841,7 +57189,7 @@ var InkKitEditor = class InkKitEditor {
56841
57189
  return true;
56842
57190
  }
56843
57191
  }));
56844
- }).use(labelsCtx).use(instance.pasteController.plugin).use(visibleClipboard).use($prose(() => instance.suggestions.plugin())).use(instance.keymapPlugin).use(createDialect(Boolean(options.images || options.files), Boolean(options.wikiLinks), Boolean(options.files))).use(tablePlugins).use(tableBlock).use(instance.changePlugin).use(instance.historyInputPlugin).use(history).use(clipboard).use(cursor).use(taskListPlugin).use(quoteBackspace).use(calloutEnter).use(literalEnter).use(literalReread).use(listItemBackspace).use(listItemShiftTab).use(nestedItemEnter).use(rejoinLists).use(movedListItems).use(textInputPolicy).use(events.copy ? codeCopyPlugin((text) => events.copy?.(text)) : []).use(placeholderPlugin).use(options.rendering?.codeHighlighting === false ? [] : (await import("./highlight-DOQk0Eyj.js")).highlightPlugin).use(options.rendering?.diagramPreview === false || !diagramsAvailable() ? [] : mermaidPreview((error) => instance.report(error))).use(selectionPlugin).use($prose(() => search())).use(instance.policyPlugin).use(options.wikiLinks ? wikiLinkView(options.wikiLinks, {
57192
+ }).use(labelsCtx).use(instance.pasteController.plugin).use(visibleClipboard).use($prose(() => instance.suggestions.plugin())).use(instance.keymapPlugin).use(createDialect(Boolean(options.images || options.files), Boolean(options.wikiLinks), Boolean(options.files))).use(codeControlCtx).use(codeControlsPlugin(() => instance.viewport().rect)).use(tablePlugins).use(tableBlock).use(instance.changePlugin).use(instance.historyInputPlugin).use(history).use(clipboard).use(cursor).use(taskListPlugin).use(quoteBackspace).use(calloutEnter).use(literalEnter).use(literalReread).use(listItemBackspace).use(listItemShiftTab).use(nestedItemEnter).use(rejoinLists).use(movedListItems).use(textInputPolicy).use(events.copy ? codeCopyPlugin((text) => events.copy?.(text)) : []).use(placeholderPlugin).use(options.rendering?.codeHighlighting === false ? [] : (await import("./highlight-BIasnL-b.js")).highlightPlugin).use(options.rendering?.diagramPreview === false || !diagramsAvailable() ? [] : mermaidPreview((error) => instance.report(error))).use(selectionPlugin).use($prose(() => search())).use(instance.policyPlugin).use(options.wikiLinks ? wikiLinkView(options.wikiLinks, {
56845
57193
  capture: () => instance.adapterCapture(),
56846
57194
  active: () => instance.ready && !instance.destroyed && !instance.literalSurface,
56847
57195
  labels: {
@@ -1,4 +1,4 @@
1
- import { a as Decoration, c as PluginKey, d as __toESM, i as $prose, o as DecorationSet, s as Plugin, u as __commonJSMin } from "./core-DP-izJDM.js";
1
+ import { a as Decoration, c as PluginKey, d as __toESM, i as $prose, o as DecorationSet, s as Plugin, u as __commonJSMin } from "./core-D7n0IhAZ.js";
2
2
  //#region node_modules/.pnpm/highlight.js@11.11.2/node_modules/highlight.js/es/languages/arduino.js
3
3
  /** @type LanguageFn */
4
4
  function cPlusPlus(hljs) {
@@ -14023,7 +14023,8 @@ var lowlight = createLowlight(grammars);
14023
14023
  function blockDecorations(node, pos, deadline) {
14024
14024
  const language = String(node.attrs.language ?? "").toLowerCase();
14025
14025
  const found = [];
14026
- if (!language || !lowlight.registered(language)) return found;
14026
+ if (language && !lowlight.registered(language)) return found;
14027
+ if (!language && node.content.size > 500) return found;
14027
14028
  if (node.content.size > 5e3 || performance.now() > deadline) return found;
14028
14029
  let offset = pos + 1;
14029
14030
  const walk = (children, classes) => {
@@ -14036,7 +14037,7 @@ function blockDecorations(node, pos, deadline) {
14036
14037
  walk(child.children, [...classes, ...own]);
14037
14038
  }
14038
14039
  };
14039
- walk(lowlight.highlight(language, node.textContent).children, []);
14040
+ walk((language ? lowlight.highlight(language, node.textContent) : lowlight.highlightAuto(node.textContent)).children, []);
14040
14041
  return found;
14041
14042
  }
14042
14043
  function decorations(doc) {
package/dist/core.js CHANGED
@@ -1,2 +1,2 @@
1
- import { r as InkKitError, t as InkKitEditor } from "./chunks/core-DP-izJDM.js";
1
+ import { r as InkKitError, t as InkKitEditor } from "./chunks/core-D7n0IhAZ.js";
2
2
  export { InkKitEditor, InkKitError };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { n as registerMermaid, r as InkKitError, t as InkKitEditor } from "./chunks/core-DP-izJDM.js";
1
+ import { n as registerMermaid, r as InkKitError, t as InkKitEditor } from "./chunks/core-D7n0IhAZ.js";
2
2
  //#region src/index.ts
3
3
  registerMermaid(async () => (await import("mermaid")).default);
4
4
  //#endregion
package/dist/style.css CHANGED
@@ -554,20 +554,6 @@
554
554
  padding-top: max(calc(var(--inkkit-font-size, 15px) * 2), 30px);
555
555
  }
556
556
 
557
- .inkkit-root .ProseMirror pre[data-language]::before {
558
- content: attr(data-language);
559
- position: absolute;
560
- top: calc(var(--inkkit-font-size, 15px) * 0.533);
561
- left: calc(var(--inkkit-font-size, 15px) * 0.933);
562
- font:
563
- calc(var(--inkkit-font-size, 15px) * 0.733)/1 -apple-system,
564
- system-ui,
565
- sans-serif;
566
- color: var(--_inkkit-muted);
567
- text-transform: lowercase;
568
- user-select: none;
569
- }
570
-
571
557
  .inkkit-root .ProseMirror pre .inkkit-copy {
572
558
  position: absolute;
573
559
  top: 6px;
@@ -582,7 +568,7 @@
582
568
  padding: 0;
583
569
  border: 0;
584
570
  border-radius: 6px;
585
- background: color-mix(in srgb, CanvasText 10%, transparent);
571
+ background: transparent;
586
572
  color: var(--_inkkit-muted);
587
573
  cursor: pointer;
588
574
  opacity: 0;
@@ -591,11 +577,13 @@
591
577
  }
592
578
 
593
579
  .inkkit-root .ProseMirror pre:hover .inkkit-copy,
580
+ .inkkit-root .ProseMirror pre:focus-within .inkkit-copy,
594
581
  .inkkit-root .ProseMirror pre .inkkit-copy[data-copied] {
595
582
  opacity: 1;
596
583
  }
597
584
 
598
585
  .inkkit-root .ProseMirror pre .inkkit-copy:hover {
586
+ background: color-mix(in srgb, CanvasText 10%, transparent);
599
587
  color: var(--_inkkit-text);
600
588
  }
601
589
 
@@ -896,7 +884,8 @@
896
884
  .inkkit-root .inkkit-comment,
897
885
  .inkkit-root [data-inkkit-callout-toggle],
898
886
  .inkkit-root .ProseMirror pre .inkkit-copy,
899
- .inkkit-root .inkkit-table-controls {
887
+ .inkkit-root .inkkit-table-controls,
888
+ .inkkit-root .inkkit-code-controls {
900
889
  display: none !important;
901
890
  }
902
891
 
@@ -1001,3 +990,85 @@
1001
990
  clip-path: inset(50%);
1002
991
  overflow: hidden;
1003
992
  }
993
+
994
+ .inkkit-root .inkkit-code-controls {
995
+ position: absolute;
996
+ top: 6px;
997
+ right: 38px;
998
+ font:
999
+ 11px/1.4 -apple-system,
1000
+ system-ui,
1001
+ sans-serif;
1002
+ white-space: normal;
1003
+ user-select: none;
1004
+ }
1005
+ .inkkit-root .inkkit-code-language {
1006
+ height: 24px;
1007
+ padding: 0 6px;
1008
+ border: 0;
1009
+ border-radius: 5px;
1010
+ background: transparent;
1011
+ color: var(--_inkkit-muted);
1012
+ font: inherit;
1013
+ cursor: pointer;
1014
+ }
1015
+ .inkkit-root .inkkit-code-language::after {
1016
+ content: '⌄';
1017
+ margin-left: 5px;
1018
+ }
1019
+ .inkkit-root .inkkit-code-language:hover {
1020
+ background: color-mix(in srgb, CanvasText 7%, transparent);
1021
+ }
1022
+ .inkkit-root .inkkit-code-language:focus-visible,
1023
+ .inkkit-root .inkkit-copy:focus-visible {
1024
+ outline: 2px solid var(--_inkkit-accent);
1025
+ outline-offset: 1px;
1026
+ }
1027
+ .inkkit-root .inkkit-code-language-menu {
1028
+ position: fixed;
1029
+ z-index: 50;
1030
+ display: flex;
1031
+ flex-direction: column;
1032
+ width: 220px;
1033
+ max-height: min(320px, 50vh);
1034
+ padding: 5px;
1035
+ box-sizing: border-box;
1036
+ border: 1px solid color-mix(in srgb, CanvasText 15%, transparent);
1037
+ border-radius: 8px;
1038
+ background: Canvas;
1039
+ color: CanvasText;
1040
+ box-shadow: 0 6px 20px #0002;
1041
+ }
1042
+ .inkkit-root .inkkit-code-language-menu input {
1043
+ box-sizing: border-box;
1044
+ min-width: 0;
1045
+ width: 100%;
1046
+ padding: 7px;
1047
+ border: 0;
1048
+ border-bottom: 1px solid color-mix(in srgb, CanvasText 12%, transparent);
1049
+ background: transparent;
1050
+ color: inherit;
1051
+ font: inherit;
1052
+ }
1053
+ .inkkit-root .inkkit-code-language-list {
1054
+ display: flex;
1055
+ flex-direction: column;
1056
+ overflow-y: auto;
1057
+ padding-top: 4px;
1058
+ }
1059
+ .inkkit-root .inkkit-code-language-list button {
1060
+ flex-shrink: 0;
1061
+ padding: 5px 8px;
1062
+ border: 0;
1063
+ border-radius: 4px;
1064
+ background: transparent;
1065
+ color: inherit;
1066
+ font: inherit;
1067
+ text-align: left;
1068
+ cursor: pointer;
1069
+ }
1070
+ .inkkit-root .inkkit-code-language-list button:hover,
1071
+ .inkkit-root .inkkit-code-language-list button:focus-visible,
1072
+ .inkkit-root .inkkit-code-language-list button[aria-pressed='true'] {
1073
+ background: color-mix(in srgb, CanvasText 8%, transparent);
1074
+ }
package/dist/types.d.ts CHANGED
@@ -255,6 +255,10 @@ export interface EditorLabels {
255
255
  sourceEditor: string;
256
256
  placeholder: string;
257
257
  copyCode: string;
258
+ codeLanguage: string;
259
+ codeLanguageSearch: string;
260
+ codeAuto: string;
261
+ codePlainText: string;
258
262
  expandCallout: string;
259
263
  collapseCallout: string;
260
264
  diagramRendering: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aicayzer/inkkit",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "A preserving Markdown editor for offline web views and the web",
5
5
  "license": "MIT",
6
6
  "type": "module",