@jvs-milkdown/crepe 1.2.29 → 1.2.30

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.
Files changed (38) hide show
  1. package/lib/cjs/builder.js +2 -1
  2. package/lib/cjs/builder.js.map +1 -1
  3. package/lib/cjs/feature/toolbar/index.js +84 -62
  4. package/lib/cjs/feature/toolbar/index.js.map +1 -1
  5. package/lib/cjs/index.js +1121 -988
  6. package/lib/cjs/index.js.map +1 -1
  7. package/lib/esm/builder.js +2 -1
  8. package/lib/esm/builder.js.map +1 -1
  9. package/lib/esm/feature/toolbar/index.js +84 -62
  10. package/lib/esm/feature/toolbar/index.js.map +1 -1
  11. package/lib/esm/index.js +1143 -1010
  12. package/lib/esm/index.js.map +1 -1
  13. package/lib/theme/common/image-block.css +5 -1
  14. package/lib/theme/common/reset.css +1 -1
  15. package/lib/theme/common/table.css +5 -0
  16. package/lib/theme/common/toolbar.css +23 -0
  17. package/lib/tsconfig.tsbuildinfo +1 -1
  18. package/lib/types/feature/fixed-toolbar/component.d.ts +2 -2
  19. package/lib/types/feature/fixed-toolbar/component.d.ts.map +1 -1
  20. package/lib/types/feature/fixed-toolbar/index.d.ts +2 -0
  21. package/lib/types/feature/fixed-toolbar/index.d.ts.map +1 -1
  22. package/lib/types/feature/fixed-toolbar/outline-panel.d.ts.map +1 -1
  23. package/lib/types/feature/fixed-toolbar/view-menu-state.d.ts +3 -0
  24. package/lib/types/feature/fixed-toolbar/view-menu-state.d.ts.map +1 -1
  25. package/lib/types/feature/toolbar/component.d.ts +2 -2
  26. package/lib/types/feature/toolbar/component.d.ts.map +1 -1
  27. package/lib/types/feature/toolbar/index.d.ts.map +1 -1
  28. package/package.json +4 -4
  29. package/src/feature/fixed-toolbar/component.tsx +203 -110
  30. package/src/feature/fixed-toolbar/index.ts +30 -8
  31. package/src/feature/fixed-toolbar/outline-panel.tsx +1 -2
  32. package/src/feature/fixed-toolbar/view-menu-state.ts +2 -0
  33. package/src/feature/toolbar/component.tsx +57 -44
  34. package/src/feature/toolbar/index.ts +9 -13
  35. package/src/theme/common/image-block.css +6 -1
  36. package/src/theme/common/reset.css +1 -1
  37. package/src/theme/common/table.css +5 -0
  38. package/src/theme/common/toolbar.css +30 -0
package/lib/esm/index.js CHANGED
@@ -4011,12 +4011,12 @@ var __accessCheck$5 = (obj, member, msg) => member.has(obj) || __typeError$5("Ca
4011
4011
  var __privateGet$5 = (obj, member, getter) => (__accessCheck$5(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
4012
4012
  var __privateAdd$5 = (obj, member, value) => member.has(obj) ? __typeError$5("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
4013
4013
  var __privateSet$5 = (obj, member, value, setter) => (__accessCheck$5(obj, member, "write to private field"), member.set(obj, value), value);
4014
- var _content$3, _provider$1, _state, _app$3, _ctx$1, _syncIcon;
4014
+ var _content$3, _provider$1, _state$2, _app$3, _ctx$1, _syncIcon;
4015
4015
  class BlockHandleView {
4016
4016
  constructor(ctx, config) {
4017
4017
  __privateAdd$5(this, _content$3);
4018
4018
  __privateAdd$5(this, _provider$1);
4019
- __privateAdd$5(this, _state, reactive({ icon: textIcon }));
4019
+ __privateAdd$5(this, _state$2, reactive({ icon: textIcon }));
4020
4020
  __privateAdd$5(this, _app$3);
4021
4021
  __privateAdd$5(this, _ctx$1);
4022
4022
  this.update = () => {
@@ -4041,17 +4041,17 @@ class BlockHandleView {
4041
4041
  __privateGet$5(this, _syncIcon).call(this, node);
4042
4042
  } else {
4043
4043
  __privateGet$5(this, _content$3).classList.remove("empty-block");
4044
- __privateGet$5(this, _state).icon = textIcon;
4044
+ __privateGet$5(this, _state$2).icon = textIcon;
4045
4045
  }
4046
4046
  };
4047
4047
  __privateAdd$5(this, _syncIcon, (node) => {
4048
4048
  var _a;
4049
4049
  if (node.type.name.includes("image")) {
4050
- __privateGet$5(this, _state).icon = imageIcon;
4050
+ __privateGet$5(this, _state$2).icon = imageIcon;
4051
4051
  return;
4052
4052
  }
4053
4053
  if (node.type.name.includes("attachment")) {
4054
- __privateGet$5(this, _state).icon = fileLinkIcon;
4054
+ __privateGet$5(this, _state$2).icon = fileLinkIcon;
4055
4055
  return;
4056
4056
  }
4057
4057
  switch (node.type.name) {
@@ -4066,40 +4066,40 @@ class BlockHandleView {
4066
4066
  h5Icon,
4067
4067
  h6Icon
4068
4068
  ];
4069
- __privateGet$5(this, _state).icon = (_a = headingIcons[level]) != null ? _a : textIcon;
4069
+ __privateGet$5(this, _state$2).icon = (_a = headingIcons[level]) != null ? _a : textIcon;
4070
4070
  break;
4071
4071
  }
4072
4072
  case "blockquote":
4073
- __privateGet$5(this, _state).icon = quoteIcon;
4073
+ __privateGet$5(this, _state$2).icon = quoteIcon;
4074
4074
  break;
4075
4075
  case "code_block":
4076
- __privateGet$5(this, _state).icon = codeIcon;
4076
+ __privateGet$5(this, _state$2).icon = codeIcon;
4077
4077
  break;
4078
4078
  case "math_display":
4079
4079
  case "math_inline":
4080
- __privateGet$5(this, _state).icon = functionsIcon;
4080
+ __privateGet$5(this, _state$2).icon = functionsIcon;
4081
4081
  break;
4082
4082
  case "hr":
4083
- __privateGet$5(this, _state).icon = dividerIcon;
4083
+ __privateGet$5(this, _state$2).icon = dividerIcon;
4084
4084
  break;
4085
4085
  case "table":
4086
- __privateGet$5(this, _state).icon = tableIcon;
4086
+ __privateGet$5(this, _state$2).icon = tableIcon;
4087
4087
  break;
4088
4088
  case "list_item":
4089
4089
  if (node.attrs.checked != null) {
4090
- __privateGet$5(this, _state).icon = todoListIcon;
4090
+ __privateGet$5(this, _state$2).icon = todoListIcon;
4091
4091
  } else {
4092
- __privateGet$5(this, _state).icon = bulletListIcon;
4092
+ __privateGet$5(this, _state$2).icon = bulletListIcon;
4093
4093
  }
4094
4094
  break;
4095
4095
  case "bullet_list":
4096
- __privateGet$5(this, _state).icon = bulletListIcon;
4096
+ __privateGet$5(this, _state$2).icon = bulletListIcon;
4097
4097
  break;
4098
4098
  case "ordered_list":
4099
- __privateGet$5(this, _state).icon = orderedListIcon;
4099
+ __privateGet$5(this, _state$2).icon = orderedListIcon;
4100
4100
  break;
4101
4101
  default:
4102
- __privateGet$5(this, _state).icon = textIcon;
4102
+ __privateGet$5(this, _state$2).icon = textIcon;
4103
4103
  }
4104
4104
  });
4105
4105
  this.destroy = () => {
@@ -4162,7 +4162,7 @@ class BlockHandleView {
4162
4162
  addIcon: (_a = config == null ? void 0 : config.handleAddIcon) != null ? _a : plusIcon,
4163
4163
  handleIcon: (_b = config == null ? void 0 : config.handleDragIcon) != null ? _b : menuIcon,
4164
4164
  ctx: __privateGet$5(this, _ctx$1),
4165
- state: __privateGet$5(this, _state)
4165
+ state: __privateGet$5(this, _state$2)
4166
4166
  });
4167
4167
  app.mount(content);
4168
4168
  __privateSet$5(this, _app$3, app);
@@ -4219,7 +4219,7 @@ class BlockHandleView {
4219
4219
  }
4220
4220
  _content$3 = new WeakMap();
4221
4221
  _provider$1 = new WeakMap();
4222
- _state = new WeakMap();
4222
+ _state$2 = new WeakMap();
4223
4223
  _app$3 = new WeakMap();
4224
4224
  _ctx$1 = new WeakMap();
4225
4225
  _syncIcon = new WeakMap();
@@ -4451,8 +4451,33 @@ const diffBlockFeature = (editor, config = {}) => {
4451
4451
  }).use(diffBlock);
4452
4452
  };
4453
4453
 
4454
- const remarkHighlightMarkPlugin = $remark(
4455
- "remarkHighlightMark",
4454
+ const supportedFontsCache = /* @__PURE__ */ new Map();
4455
+ const isFontSupported = (fontFamily) => {
4456
+ if (!fontFamily) return true;
4457
+ const normalizedFont = fontFamily.replace(/['"]/g, "");
4458
+ if (supportedFontsCache.has(normalizedFont)) {
4459
+ return supportedFontsCache.get(normalizedFont);
4460
+ }
4461
+ if (typeof document === "undefined") return true;
4462
+ const canvas = document.createElement("canvas");
4463
+ const context = canvas.getContext("2d");
4464
+ if (!context) return true;
4465
+ const text = "abcdefghijklmnopqrstuvwxyz0123456789";
4466
+ const size = "72px";
4467
+ context.font = `${size} monospace`;
4468
+ const baseMono = context.measureText(text).width;
4469
+ context.font = `${size} sans-serif`;
4470
+ const baseSans = context.measureText(text).width;
4471
+ context.font = `${size} "${normalizedFont}", monospace`;
4472
+ const testMono = context.measureText(text).width;
4473
+ context.font = `${size} "${normalizedFont}", sans-serif`;
4474
+ const testSans = context.measureText(text).width;
4475
+ const supported = testMono !== baseMono || testSans !== baseSans;
4476
+ supportedFontsCache.set(normalizedFont, supported);
4477
+ return supported;
4478
+ };
4479
+ const remarkFontPlugin = $remark(
4480
+ "remarkFont",
4456
4481
  () => function() {
4457
4482
  const data = this.data();
4458
4483
  function add(key, value) {
@@ -4464,31 +4489,46 @@ const remarkHighlightMarkPlugin = $remark(
4464
4489
  }
4465
4490
  add("toMarkdownExtensions", {
4466
4491
  handlers: {
4467
- highlightMark: (node, _, state) => {
4468
- const idAttr = node.id ? ` data-id="${node.id}"` : "";
4469
- return `<mark${idAttr}>${state.containerPhrasing(node, state)}</mark>`;
4492
+ fontFamily: (node, _, state) => {
4493
+ return `<span style="font-family:${node.fontFamily}">${state.containerPhrasing(node, state)}</span>`;
4494
+ },
4495
+ fontSize: (node, _, state) => {
4496
+ return `<span style="font-size:${node.fontSize}">${state.containerPhrasing(node, state)}</span>`;
4470
4497
  }
4471
4498
  }
4472
4499
  });
4473
4500
  return (ast) => {
4474
4501
  visit(ast, (node, index, parent) => {
4475
- if ((node == null ? void 0 : node.type) === "html" && node.value.startsWith("<mark") && parent && index != null) {
4476
- const idMatch = node.value.match(/data-id="([^"]+)"/);
4477
- const id = idMatch ? idMatch[1] : null;
4502
+ if ((node == null ? void 0 : node.type) === "html" && node.value.startsWith("<span") && parent && index != null) {
4503
+ const hasFontFamily = node.value.match(/font-family:\s*([^"';>]+)/);
4504
+ const hasFontSize = node.value.match(/font-size:\s*([^"';>]+)/);
4505
+ if (!hasFontFamily && !hasFontSize) return;
4506
+ let fontFamily = null;
4507
+ let fontSize = null;
4508
+ let markType = null;
4509
+ if (hasFontFamily) {
4510
+ fontFamily = hasFontFamily[1].trim();
4511
+ markType = "fontFamily";
4512
+ } else if (hasFontSize) {
4513
+ fontSize = hasFontSize[1].trim();
4514
+ markType = "fontSize";
4515
+ }
4478
4516
  const endIndex = parent.children.findIndex(
4479
- (n, i) => i > index && n.type === "html" && n.value === "</mark>"
4517
+ (n, i) => i > index && n.type === "html" && n.value === "</span>"
4480
4518
  );
4481
- if (endIndex !== -1) {
4519
+ if (endIndex !== -1 && markType && (fontFamily || fontSize)) {
4482
4520
  const children = parent.children.splice(
4483
4521
  index,
4484
4522
  endIndex - index + 1
4485
4523
  );
4486
4524
  const content = children.slice(1, -1);
4487
- parent.children.splice(index, 0, {
4488
- type: "highlightMark",
4489
- id,
4525
+ const payload = {
4526
+ type: markType,
4490
4527
  children: content
4491
- });
4528
+ };
4529
+ if (fontFamily) payload.fontFamily = fontFamily;
4530
+ if (fontSize) payload.fontSize = fontSize;
4531
+ parent.children.splice(index, 0, payload);
4492
4532
  return index + 1;
4493
4533
  }
4494
4534
  }
@@ -4497,377 +4537,236 @@ const remarkHighlightMarkPlugin = $remark(
4497
4537
  };
4498
4538
  }
4499
4539
  );
4500
- const highlightMarkAttr = $markAttr("highlightMark");
4501
- const highlightMarkSchema = $markSchema("highlightMark", (ctx) => ({
4540
+ const fontFamilyAttr = $markAttr("fontFamily");
4541
+ const fontFamilySchema = $markSchema("fontFamily", (_ctx) => ({
4502
4542
  inclusive: true,
4503
4543
  attrs: {
4504
- id: { default: null }
4544
+ fontFamily: { default: null }
4505
4545
  },
4506
4546
  parseDOM: [
4507
4547
  {
4508
- tag: "mark",
4509
- getAttrs: (dom) => ({
4510
- id: dom.getAttribute("data-id") || null
4511
- })
4548
+ tag: 'span[style*="font-family"]',
4549
+ getAttrs: (dom) => {
4550
+ if (!(dom instanceof HTMLElement)) return false;
4551
+ const fontFamily = dom.style.fontFamily || null;
4552
+ if (!isFontSupported(fontFamily)) return false;
4553
+ return { fontFamily };
4554
+ }
4512
4555
  }
4513
4556
  ],
4514
4557
  toDOM: (mark) => {
4515
- const attrs = { ...ctx.get(highlightMarkAttr.key)(mark) };
4516
- if (mark.attrs.id) {
4517
- attrs["data-id"] = mark.attrs.id;
4558
+ return ["span", { style: `font-family: ${mark.attrs.fontFamily}` }, 0];
4559
+ },
4560
+ parseMarkdown: {
4561
+ match: (node) => node.type === "fontFamily",
4562
+ runner: (state, node, markType) => {
4563
+ state.openMark(markType, { fontFamily: node.fontFamily });
4564
+ state.next(node.children);
4565
+ state.closeMark(markType);
4518
4566
  }
4519
- return ["mark", attrs, 0];
4567
+ },
4568
+ toMarkdown: {
4569
+ match: (mark) => mark.type.name === "fontFamily",
4570
+ runner: (state, mark) => {
4571
+ state.withMark(mark, "fontFamily", void 0, {
4572
+ fontFamily: mark.attrs.fontFamily
4573
+ });
4574
+ }
4575
+ }
4576
+ }));
4577
+ const fontSizeAttr = $markAttr("fontSize");
4578
+ const fontSizeSchema = $markSchema("fontSize", (_ctx) => ({
4579
+ inclusive: true,
4580
+ attrs: {
4581
+ fontSize: { default: null }
4582
+ },
4583
+ parseDOM: [
4584
+ {
4585
+ tag: 'span[style*="font-size"]',
4586
+ getAttrs: (dom) => {
4587
+ if (!(dom instanceof HTMLElement)) return false;
4588
+ return { fontSize: dom.style.fontSize || null };
4589
+ }
4590
+ }
4591
+ ],
4592
+ toDOM: (mark) => {
4593
+ return ["span", { style: `font-size: ${mark.attrs.fontSize}` }, 0];
4520
4594
  },
4521
4595
  parseMarkdown: {
4522
- match: (node) => node.type === "highlightMark",
4596
+ match: (node) => node.type === "fontSize",
4523
4597
  runner: (state, node, markType) => {
4524
- state.openMark(markType, { id: node.id });
4598
+ state.openMark(markType, { fontSize: node.fontSize });
4525
4599
  state.next(node.children);
4526
4600
  state.closeMark(markType);
4527
4601
  }
4528
4602
  },
4529
4603
  toMarkdown: {
4530
- match: (mark) => mark.type.name === "highlightMark",
4604
+ match: (mark) => mark.type.name === "fontSize",
4531
4605
  runner: (state, mark) => {
4532
- state.withMark(mark, "highlightMark", void 0, { id: mark.attrs.id });
4606
+ state.withMark(mark, "fontSize", void 0, {
4607
+ fontSize: mark.attrs.fontSize
4608
+ });
4533
4609
  }
4534
4610
  }
4535
4611
  }));
4536
- const toggleHighlightMarkCommand = $command(
4537
- "ToggleHighlightMark",
4538
- (ctx) => () => (state, dispatch) => {
4539
- const markType = highlightMarkSchema.type(ctx);
4540
- const { $cursor, ranges, $from, $to } = state.selection;
4541
- if (dispatch) {
4542
- let tr = state.tr;
4543
- const newId = Math.random().toString(36).substring(2, 9);
4544
- const creatMark = () => markType.create({ id: newId });
4545
- if ($cursor) {
4546
- const isEmptyBlock = $cursor.parent.content.size === 0;
4547
- if (isEmptyBlock) {
4612
+ const toggleFontFamilyCommand = $command(
4613
+ "ToggleFontFamily",
4614
+ (ctx) => (fontFamily) => {
4615
+ return (state, dispatch) => {
4616
+ const markType = fontFamilySchema.type(ctx);
4617
+ const { $cursor, ranges } = state.selection;
4618
+ if (dispatch) {
4619
+ let tr = state.tr;
4620
+ if ($cursor) {
4548
4621
  const marks = state.storedMarks || $cursor.marks();
4549
4622
  const currentMark = markType.isInSet(marks);
4550
- if (currentMark) {
4623
+ if (currentMark && currentMark.attrs.fontFamily === fontFamily) {
4551
4624
  tr = tr.removeStoredMark(markType);
4552
4625
  } else {
4553
- const zwsp = "\u200B";
4554
- tr = tr.insertText(zwsp, $cursor.pos);
4555
- tr = tr.addMark($cursor.pos, $cursor.pos + 1, creatMark());
4556
- tr = tr.setSelection(TextSelection.create(tr.doc, $cursor.pos));
4557
- }
4558
- } else {
4559
- const start = $cursor.start();
4560
- const end = $cursor.end();
4561
- const hasMark = state.doc.rangeHasMark(start, end, markType);
4562
- if (hasMark) {
4563
- tr = tr.removeMark(start, end, markType);
4564
- if ($cursor.parent.content.size === 1 && $cursor.parent.textContent === "\u200B") {
4565
- tr = tr.delete(start, end);
4566
- }
4567
- } else {
4568
- tr = tr.addMark(start, end, creatMark());
4569
- }
4570
- }
4571
- } else {
4572
- let hasMark = false;
4573
- for (const range of ranges) {
4574
- const { $from: $from2, $to: $to2 } = range;
4575
- if (state.doc.rangeHasMark($from2.pos, $to2.pos, markType)) {
4576
- hasMark = true;
4577
- break;
4578
- }
4579
- }
4580
- if (hasMark) {
4581
- for (const range of ranges) {
4582
- const { $from: $from2, $to: $to2 } = range;
4583
- tr = tr.removeMark($from2.pos, $to2.pos, markType);
4626
+ tr = tr.removeStoredMark(markType);
4627
+ if (fontFamily)
4628
+ tr = tr.addStoredMark(markType.create({ fontFamily }));
4584
4629
  }
4585
4630
  } else {
4631
+ let hasSameFontFamily = false;
4586
4632
  for (const range of ranges) {
4587
- const { $from: $from2, $to: $to2 } = range;
4588
- tr = tr.removeMark($from2.pos, $to2.pos, markType);
4589
- }
4590
- let canFlatten = true;
4591
- let blockCount = 0;
4592
- state.doc.nodesBetween($from.pos, $to.pos, (node) => {
4593
- if (node.isTextblock) {
4594
- blockCount++;
4595
- }
4596
- if (node.isBlock) {
4597
- const name = node.type.name;
4598
- if (name !== "paragraph" && name !== "doc" && name !== "blockquote") {
4599
- canFlatten = false;
4600
- }
4601
- }
4602
- });
4603
- if (canFlatten && blockCount > 1) {
4604
- const nodes = [];
4633
+ const { $from, $to } = range;
4605
4634
  state.doc.nodesBetween($from.pos, $to.pos, (node) => {
4606
- if (node.isTextblock) {
4607
- const hardbreakType = state.schema.nodes.hardbreak;
4608
- if (hardbreakType && nodes.length > 0) {
4609
- nodes.push(hardbreakType.create());
4635
+ if (node.isText) {
4636
+ const mark = markType.isInSet(node.marks);
4637
+ if (mark && mark.attrs.fontFamily === fontFamily) {
4638
+ hasSameFontFamily = true;
4610
4639
  }
4611
- node.forEach((child) => nodes.push(child));
4612
4640
  }
4613
4641
  });
4614
- const paragraphType = state.schema.nodes.paragraph;
4615
- const range = $from.blockRange($to);
4616
- if (paragraphType && range) {
4617
- const p = paragraphType.create({}, nodes);
4618
- tr = tr.replaceWith(range.start, range.end, p);
4642
+ }
4643
+ for (const range of ranges) {
4644
+ const { $from, $to } = range;
4645
+ tr = tr.removeMark($from.pos, $to.pos, markType);
4646
+ if (!hasSameFontFamily && fontFamily) {
4619
4647
  tr = tr.addMark(
4620
- range.start,
4621
- range.start + p.nodeSize,
4622
- creatMark()
4648
+ $from.pos,
4649
+ $to.pos,
4650
+ markType.create({ fontFamily })
4623
4651
  );
4624
4652
  }
4625
- } else {
4626
- for (const range of ranges) {
4627
- const { $from: $from2, $to: $to2 } = range;
4628
- tr = tr.addMark($from2.pos, $to2.pos, creatMark());
4629
- }
4630
4653
  }
4631
4654
  }
4655
+ dispatch(tr.scrollIntoView());
4632
4656
  }
4633
- dispatch(tr.scrollIntoView());
4634
- }
4635
- return true;
4657
+ return true;
4658
+ };
4636
4659
  }
4637
4660
  );
4638
- const highlightMarkKeymap = $useKeymap("highlightMarkKeymap", {
4639
- ToggleHighlightMark: {
4640
- shortcuts: "Mod-Shift-h",
4641
- command: (ctx) => {
4642
- const commands = ctx.get(commandsCtx);
4643
- return () => commands.call(toggleHighlightMarkCommand.key);
4644
- }
4645
- },
4646
- HighlightMarkEnter: {
4647
- shortcuts: "Enter",
4648
- command: (ctx) => {
4649
- return (state, dispatch) => {
4650
- const markType = highlightMarkSchema.type(ctx);
4651
- const { $from, empty } = state.selection;
4652
- if (!empty) return false;
4653
- const marks = state.storedMarks || $from.marks();
4654
- if (!markType.isInSet(marks)) return false;
4655
- if (dispatch) {
4656
- const hardbreak = state.schema.nodes.hardbreak;
4657
- if (hardbreak) {
4658
- let tr = state.tr.replaceSelectionWith(hardbreak.create(), true);
4659
- dispatch(tr.scrollIntoView());
4660
- }
4661
- }
4662
- return true;
4663
- };
4664
- }
4665
- },
4666
- HighlightMarkArrowDown: {
4667
- shortcuts: "ArrowDown",
4668
- command: (ctx) => {
4669
- return (state, dispatch, view) => {
4670
- if (!view) return false;
4671
- const markType = highlightMarkSchema.type(ctx);
4672
- const { selection } = state;
4673
- const { $from, empty } = selection;
4674
- if (!empty) return false;
4675
- const isTextblock = $from.parent.isTextblock;
4676
- if (!isTextblock) return false;
4677
- let hasNodeAfter = false;
4678
- state.doc.nodesBetween(
4679
- $from.after(),
4680
- state.doc.content.size,
4681
- (node) => {
4682
- if (node.isTextblock) hasNodeAfter = true;
4683
- }
4684
- );
4685
- if (hasNodeAfter) return false;
4686
- let hasHighlight = false;
4687
- if ($from.parent.content.size === 0) {
4688
- const marks = state.storedMarks || $from.marks();
4689
- if (markType.isInSet(marks)) {
4690
- hasHighlight = true;
4691
- }
4692
- } else if ($from.parent.content.size === 1 && $from.parent.textContent === "\u200B") {
4693
- const child = $from.parent.child(0);
4694
- if (child.marks.some((m) => m.type === markType)) {
4695
- hasHighlight = true;
4661
+ const toggleFontSizeCommand = $command(
4662
+ "ToggleFontSize",
4663
+ (ctx) => (fontSize) => {
4664
+ return (state, dispatch) => {
4665
+ const markType = fontSizeSchema.type(ctx);
4666
+ const { $cursor, ranges } = state.selection;
4667
+ if (dispatch) {
4668
+ let tr = state.tr;
4669
+ if ($cursor) {
4670
+ const marks = state.storedMarks || $cursor.marks();
4671
+ const currentMark = markType.isInSet(marks);
4672
+ if (currentMark && currentMark.attrs.fontSize === fontSize) {
4673
+ tr = tr.removeStoredMark(markType);
4674
+ } else {
4675
+ tr = tr.removeStoredMark(markType);
4676
+ if (fontSize) tr = tr.addStoredMark(markType.create({ fontSize }));
4696
4677
  }
4697
4678
  } else {
4698
- $from.parent.descendants((node) => {
4699
- if (node.isText && node.marks.some((m) => m.type === markType)) {
4700
- hasHighlight = true;
4701
- }
4702
- });
4703
- }
4704
- if (!hasHighlight) return false;
4705
- if (!view.endOfTextblock("down")) return false;
4706
- const paragraphType = state.schema.nodes.paragraph;
4707
- if (!paragraphType) return false;
4708
- if (dispatch) {
4709
- const p = paragraphType.create();
4710
- const insertPos = state.doc.content.size;
4711
- let tr = state.tr.insert(insertPos, p);
4712
- const newPos = insertPos + 1;
4713
- tr = tr.setSelection(TextSelection.create(tr.doc, newPos));
4714
- tr = tr.removeStoredMark(markType);
4715
- dispatch(tr.scrollIntoView());
4716
- }
4717
- return true;
4718
- };
4719
- }
4720
- },
4721
- HighlightMarkBackspace: {
4722
- shortcuts: "Backspace",
4723
- command: (ctx) => {
4724
- return (state, dispatch) => {
4725
- const markType = highlightMarkSchema.type(ctx);
4726
- const { selection } = state;
4727
- const { $from, empty } = selection;
4728
- if (!empty) return false;
4729
- const isTextblock = $from.parent.isTextblock;
4730
- if (!isTextblock) return false;
4731
- if ($from.parentOffset === 0) {
4732
- const prevBlockPos = $from.before() - 1;
4733
- if (prevBlockPos > 0) {
4734
- const $prev = state.doc.resolve(prevBlockPos);
4735
- const prevBlock = $prev.parent;
4736
- if (prevBlock && prevBlock.isTextblock) {
4737
- let prevHasHighlight = false;
4738
- prevBlock.descendants((node) => {
4739
- if (node.marks.some((m) => m.type === markType)) {
4740
- prevHasHighlight = true;
4741
- }
4742
- });
4743
- if (prevHasHighlight) {
4744
- if (dispatch) {
4745
- let tr = state.tr;
4746
- tr = tr.delete($prev.start() - 1, $prev.end() + 1);
4747
- dispatch(tr.scrollIntoView());
4679
+ let hasSameFontSize = false;
4680
+ for (const range of ranges) {
4681
+ const { $from, $to } = range;
4682
+ state.doc.nodesBetween($from.pos, $to.pos, (node) => {
4683
+ if (node.isText) {
4684
+ const mark = markType.isInSet(node.marks);
4685
+ if (mark && mark.attrs.fontSize === fontSize) {
4686
+ hasSameFontSize = true;
4748
4687
  }
4749
- return true;
4750
4688
  }
4751
- }
4752
- }
4753
- }
4754
- let hasHighlight = false;
4755
- let isPlaceholder = false;
4756
- if ($from.parent.content.size === 0) {
4757
- const marks = state.storedMarks || $from.marks();
4758
- if (markType.isInSet(marks)) {
4759
- hasHighlight = true;
4760
- }
4761
- } else if ($from.parent.content.size === 1 && $from.parent.textContent === "\u200B") {
4762
- const child = $from.parent.child(0);
4763
- if (child.marks.some((m) => m.type === markType)) {
4764
- hasHighlight = true;
4765
- isPlaceholder = true;
4689
+ });
4766
4690
  }
4767
- }
4768
- if (hasHighlight) {
4769
- if (dispatch) {
4770
- let tr = state.tr;
4771
- if (isPlaceholder) {
4772
- const start = $from.start();
4773
- const end = $from.end();
4774
- tr = tr.delete(start, end);
4691
+ for (const range of ranges) {
4692
+ const { $from, $to } = range;
4693
+ tr = tr.removeMark($from.pos, $to.pos, markType);
4694
+ if (!hasSameFontSize && fontSize) {
4695
+ tr = tr.addMark(
4696
+ $from.pos,
4697
+ $to.pos,
4698
+ markType.create({ fontSize })
4699
+ );
4775
4700
  }
4776
- tr = tr.removeStoredMark(markType);
4777
- dispatch(tr.scrollIntoView());
4778
4701
  }
4779
- return true;
4780
4702
  }
4781
- return false;
4782
- };
4783
- }
4703
+ dispatch(tr.scrollIntoView());
4704
+ }
4705
+ return true;
4706
+ };
4784
4707
  }
4785
- });
4786
- const highlightEmptyBlockPlugin = $prose((ctx) => {
4787
- return new Plugin({
4788
- key: new PluginKey("highlightEmptyBlock"),
4789
- props: {
4790
- decorations(state) {
4791
- const markType = highlightMarkSchema.type(ctx);
4792
- const decorations = [];
4793
- state.doc.descendants((node, pos) => {
4794
- if (node.isTextblock) {
4795
- if (node.content.size === 1 && node.textContent === "\u200B") {
4796
- const child = node.child(0);
4797
- if (child.marks.some((m) => m.type === markType)) {
4798
- decorations.push(
4799
- Decoration.node(pos, pos + node.nodeSize, {
4800
- class: "crepe-placeholder crepe-highlight-empty",
4801
- "data-placeholder": "\u8BF7\u8F93\u5165\u5185\u5BB9"
4802
- })
4803
- );
4804
- }
4805
- }
4806
- }
4807
- });
4808
- const { selection } = state;
4809
- const { $from, empty } = selection;
4810
- if (empty && $from.parent.isTextblock && $from.parent.content.size === 0) {
4811
- const marks = state.storedMarks || $from.marks();
4812
- if (markType.isInSet(marks)) {
4813
- const start = $from.start() - 1;
4814
- decorations.push(
4815
- Decoration.node(start, start + $from.parent.nodeSize, {
4816
- class: "crepe-placeholder crepe-highlight-empty",
4817
- "data-placeholder": "\u8BF7\u8F93\u5165\u5185\u5BB9"
4818
- })
4819
- );
4820
- }
4821
- }
4822
- return DecorationSet.create(state.doc, decorations);
4708
+ );
4709
+ function stripFontFamilyFromExternalHTML(html) {
4710
+ if (html.includes("data-pm-slice")) return html;
4711
+ try {
4712
+ const template = document.createElement("template");
4713
+ template.innerHTML = html;
4714
+ const styledElements = template.content.querySelectorAll(
4715
+ '[style*="font-family"]'
4716
+ );
4717
+ styledElements.forEach((el) => {
4718
+ if (el instanceof HTMLElement) {
4719
+ el.style.removeProperty("font-family");
4823
4720
  }
4824
- },
4825
- appendTransaction(transactions, _oldState, newState) {
4826
- const markType = highlightMarkSchema.type(ctx);
4827
- if (!transactions.some((t) => t.docChanged)) return null;
4828
- const { empty, $from } = newState.selection;
4829
- if (!empty || !$from.parent.isTextblock) return null;
4830
- if ($from.parent.content.size !== 0) return null;
4831
- const marks = newState.storedMarks || $from.marks();
4832
- if (!markType.isInSet(marks)) return null;
4833
- const id = Math.random().toString(36).substring(2, 9);
4834
- const mark = markType.create({ id });
4835
- return newState.tr.insert($from.pos, newState.schema.text("\u200B", [mark]));
4836
- }
4837
- });
4838
- });
4839
- const highlightMark = [
4840
- highlightMarkAttr,
4841
- highlightMarkSchema,
4842
- toggleHighlightMarkCommand,
4843
- highlightMarkKeymap,
4844
- remarkHighlightMarkPlugin,
4845
- highlightEmptyBlockPlugin
4846
- ];
4847
-
4848
- const remarkUnderlinePlugin = $remark(
4849
- "remarkUnderline",
4850
- () => function() {
4851
- const data = this.data();
4852
- function add(key, value) {
4853
- if (Array.isArray(data[key])) {
4854
- data[key].push(value);
4855
- } else {
4856
- data[key] = [value];
4721
+ });
4722
+ const fontElements = template.content.querySelectorAll("font[face]");
4723
+ fontElements.forEach((el) => {
4724
+ if (el instanceof HTMLElement) {
4725
+ el.removeAttribute("face");
4726
+ }
4727
+ });
4728
+ html = template.innerHTML;
4729
+ template.remove();
4730
+ } catch (e) {
4731
+ }
4732
+ return html;
4733
+ }
4734
+ const fontPlugins = [
4735
+ fontFamilyAttr,
4736
+ fontFamilySchema,
4737
+ toggleFontFamilyCommand,
4738
+ fontSizeAttr,
4739
+ fontSizeSchema,
4740
+ toggleFontSizeCommand,
4741
+ remarkFontPlugin
4742
+ ];
4743
+
4744
+ const remarkHighlightMarkPlugin = $remark(
4745
+ "remarkHighlightMark",
4746
+ () => function() {
4747
+ const data = this.data();
4748
+ function add(key, value) {
4749
+ if (Array.isArray(data[key])) {
4750
+ data[key].push(value);
4751
+ } else {
4752
+ data[key] = [value];
4857
4753
  }
4858
4754
  }
4859
4755
  add("toMarkdownExtensions", {
4860
4756
  handlers: {
4861
- underline: (node, _, state) => {
4862
- return `<u>${state.containerPhrasing(node, state)}</u>`;
4757
+ highlightMark: (node, _, state) => {
4758
+ const idAttr = node.id ? ` data-id="${node.id}"` : "";
4759
+ return `<mark${idAttr}>${state.containerPhrasing(node, state)}</mark>`;
4863
4760
  }
4864
4761
  }
4865
4762
  });
4866
4763
  return (ast) => {
4867
4764
  visit(ast, (node, index, parent) => {
4868
- if ((node == null ? void 0 : node.type) === "html" && node.value === "<u>" && parent && index != null) {
4765
+ if ((node == null ? void 0 : node.type) === "html" && node.value.startsWith("<mark") && parent && index != null) {
4766
+ const idMatch = node.value.match(/data-id="([^"]+)"/);
4767
+ const id = idMatch ? idMatch[1] : null;
4869
4768
  const endIndex = parent.children.findIndex(
4870
- (n, i) => i > index && n.type === "html" && n.value === "</u>"
4769
+ (n, i) => i > index && n.type === "html" && n.value === "</mark>"
4871
4770
  );
4872
4771
  if (endIndex !== -1) {
4873
4772
  const children = parent.children.splice(
@@ -4876,7 +4775,8 @@ const remarkUnderlinePlugin = $remark(
4876
4775
  );
4877
4776
  const content = children.slice(1, -1);
4878
4777
  parent.children.splice(index, 0, {
4879
- type: "underline",
4778
+ type: "highlightMark",
4779
+ id,
4880
4780
  children: content
4881
4781
  });
4882
4782
  return index + 1;
@@ -4887,606 +4787,706 @@ const remarkUnderlinePlugin = $remark(
4887
4787
  };
4888
4788
  }
4889
4789
  );
4890
- const underlineAttr = $markAttr("underline");
4891
- const underlineSchema = $markSchema("underline", (ctx) => ({
4790
+ const highlightMarkAttr = $markAttr("highlightMark");
4791
+ const highlightMarkSchema = $markSchema("highlightMark", (ctx) => ({
4892
4792
  inclusive: true,
4793
+ attrs: {
4794
+ id: { default: null }
4795
+ },
4893
4796
  parseDOM: [
4894
- { tag: "u" },
4895
4797
  {
4896
- style: "text-decoration",
4897
- getAttrs: (value) => value === "underline" ? null : false
4798
+ tag: "mark",
4799
+ getAttrs: (dom) => ({
4800
+ id: dom.getAttribute("data-id") || null
4801
+ })
4898
4802
  }
4899
4803
  ],
4900
- toDOM: (mark) => ["u", ctx.get(underlineAttr.key)(mark), 0],
4804
+ toDOM: (mark) => {
4805
+ const attrs = { ...ctx.get(highlightMarkAttr.key)(mark) };
4806
+ if (mark.attrs.id) {
4807
+ attrs["data-id"] = mark.attrs.id;
4808
+ }
4809
+ return ["mark", attrs, 0];
4810
+ },
4901
4811
  parseMarkdown: {
4902
- match: (node) => node.type === "underline",
4812
+ match: (node) => node.type === "highlightMark",
4903
4813
  runner: (state, node, markType) => {
4904
- state.openMark(markType);
4814
+ state.openMark(markType, { id: node.id });
4905
4815
  state.next(node.children);
4906
4816
  state.closeMark(markType);
4907
4817
  }
4908
4818
  },
4909
4819
  toMarkdown: {
4910
- match: (mark) => mark.type.name === "underline",
4820
+ match: (mark) => mark.type.name === "highlightMark",
4911
4821
  runner: (state, mark) => {
4912
- state.withMark(mark, "underline");
4822
+ state.withMark(mark, "highlightMark", void 0, { id: mark.attrs.id });
4913
4823
  }
4914
4824
  }
4915
4825
  }));
4916
- const toggleUnderlineCommand = $command(
4917
- "ToggleUnderline",
4918
- (ctx) => () => toggleMark(underlineSchema.type(ctx))
4826
+ const toggleHighlightMarkCommand = $command(
4827
+ "ToggleHighlightMark",
4828
+ (ctx) => () => (state, dispatch) => {
4829
+ const markType = highlightMarkSchema.type(ctx);
4830
+ const { $cursor, ranges, $from, $to } = state.selection;
4831
+ if (dispatch) {
4832
+ let tr = state.tr;
4833
+ const newId = Math.random().toString(36).substring(2, 9);
4834
+ const creatMark = () => markType.create({ id: newId });
4835
+ if ($cursor) {
4836
+ const isEmptyBlock = $cursor.parent.content.size === 0;
4837
+ if (isEmptyBlock) {
4838
+ const marks = state.storedMarks || $cursor.marks();
4839
+ const currentMark = markType.isInSet(marks);
4840
+ if (currentMark) {
4841
+ tr = tr.removeStoredMark(markType);
4842
+ } else {
4843
+ const zwsp = "\u200B";
4844
+ tr = tr.insertText(zwsp, $cursor.pos);
4845
+ tr = tr.addMark($cursor.pos, $cursor.pos + 1, creatMark());
4846
+ tr = tr.setSelection(TextSelection.create(tr.doc, $cursor.pos));
4847
+ }
4848
+ } else {
4849
+ const start = $cursor.start();
4850
+ const end = $cursor.end();
4851
+ const hasMark = state.doc.rangeHasMark(start, end, markType);
4852
+ if (hasMark) {
4853
+ tr = tr.removeMark(start, end, markType);
4854
+ if ($cursor.parent.content.size === 1 && $cursor.parent.textContent === "\u200B") {
4855
+ tr = tr.delete(start, end);
4856
+ }
4857
+ } else {
4858
+ tr = tr.addMark(start, end, creatMark());
4859
+ }
4860
+ }
4861
+ } else {
4862
+ let hasMark = false;
4863
+ for (const range of ranges) {
4864
+ const { $from: $from2, $to: $to2 } = range;
4865
+ if (state.doc.rangeHasMark($from2.pos, $to2.pos, markType)) {
4866
+ hasMark = true;
4867
+ break;
4868
+ }
4869
+ }
4870
+ if (hasMark) {
4871
+ for (const range of ranges) {
4872
+ const { $from: $from2, $to: $to2 } = range;
4873
+ tr = tr.removeMark($from2.pos, $to2.pos, markType);
4874
+ }
4875
+ } else {
4876
+ for (const range of ranges) {
4877
+ const { $from: $from2, $to: $to2 } = range;
4878
+ tr = tr.removeMark($from2.pos, $to2.pos, markType);
4879
+ }
4880
+ let canFlatten = true;
4881
+ let blockCount = 0;
4882
+ state.doc.nodesBetween($from.pos, $to.pos, (node) => {
4883
+ if (node.isTextblock) {
4884
+ blockCount++;
4885
+ }
4886
+ if (node.isBlock) {
4887
+ const name = node.type.name;
4888
+ if (name !== "paragraph" && name !== "doc" && name !== "blockquote") {
4889
+ canFlatten = false;
4890
+ }
4891
+ }
4892
+ });
4893
+ if (canFlatten && blockCount > 1) {
4894
+ const nodes = [];
4895
+ state.doc.nodesBetween($from.pos, $to.pos, (node) => {
4896
+ if (node.isTextblock) {
4897
+ const hardbreakType = state.schema.nodes.hardbreak;
4898
+ if (hardbreakType && nodes.length > 0) {
4899
+ nodes.push(hardbreakType.create());
4900
+ }
4901
+ node.forEach((child) => nodes.push(child));
4902
+ }
4903
+ });
4904
+ const paragraphType = state.schema.nodes.paragraph;
4905
+ const range = $from.blockRange($to);
4906
+ if (paragraphType && range) {
4907
+ const p = paragraphType.create({}, nodes);
4908
+ tr = tr.replaceWith(range.start, range.end, p);
4909
+ tr = tr.addMark(
4910
+ range.start,
4911
+ range.start + p.nodeSize,
4912
+ creatMark()
4913
+ );
4914
+ }
4915
+ } else {
4916
+ for (const range of ranges) {
4917
+ const { $from: $from2, $to: $to2 } = range;
4918
+ tr = tr.addMark($from2.pos, $to2.pos, creatMark());
4919
+ }
4920
+ }
4921
+ }
4922
+ }
4923
+ dispatch(tr.scrollIntoView());
4924
+ }
4925
+ return true;
4926
+ }
4919
4927
  );
4920
- const underlineKeymap = $useKeymap("underlineKeymap", {
4921
- ToggleUnderline: {
4922
- shortcuts: "Mod-u",
4928
+ const highlightMarkKeymap = $useKeymap("highlightMarkKeymap", {
4929
+ ToggleHighlightMark: {
4930
+ shortcuts: "Mod-Shift-h",
4923
4931
  command: (ctx) => {
4924
4932
  const commands = ctx.get(commandsCtx);
4925
- return () => commands.call(toggleUnderlineCommand.key);
4926
- }
4927
- }
4928
- });
4929
- const underline = [
4930
- underlineAttr,
4931
- underlineSchema,
4932
- toggleUnderlineCommand,
4933
- underlineKeymap,
4934
- remarkUnderlinePlugin
4935
- ];
4936
-
4937
- const listeners = /* @__PURE__ */ new Set();
4938
- let _popupCount = 0;
4939
- function getIsAnyPopupOpen() {
4940
- return _popupCount > 0;
4941
- }
4942
- function addPopupChangeListener(fn) {
4943
- listeners.add(fn);
4944
- return () => listeners.delete(fn);
4945
- }
4946
- function incrementPopupCount() {
4947
- const wasZero = _popupCount === 0;
4948
- _popupCount++;
4949
- if (wasZero) {
4950
- listeners.forEach((fn) => fn());
4951
- }
4952
- }
4953
- function decrementPopupCount() {
4954
- _popupCount = Math.max(0, _popupCount - 1);
4955
- if (_popupCount === 0) {
4956
- listeners.forEach((fn) => fn());
4957
- }
4958
- }
4959
- function resetPopupCount() {
4960
- _popupCount = 0;
4961
- listeners.forEach((fn) => fn());
4962
- }
4963
-
4964
- function getGroups(config, ctx) {
4965
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
4966
- const groupBuilder = new GroupBuilder();
4967
- groupBuilder.addGroup("heading", ctx ? i18n(ctx, "toolbar.heading") : "Heading").addItem("h1", {
4968
- label: ctx ? i18n(ctx, "menu.item.h1") : "Heading 1",
4969
- icon: (_a = config == null ? void 0 : config.h1Icon) != null ? _a : h1Icon,
4970
- active: (ctx2) => {
4971
- const view = ctx2.get(editorViewCtx);
4972
- const result = findNodeInSelection(view.state, headingSchema.type(ctx2));
4973
- return result.hasNode && !!result.target && result.target.attrs.level === 1;
4974
- },
4975
- onRun: (ctx2) => {
4976
- const commands = ctx2.get(commandsCtx);
4977
- const view = ctx2.get(editorViewCtx);
4978
- const result = findNodeInSelection(view.state, headingSchema.type(ctx2));
4979
- const isActive = result.hasNode && !!result.target && result.target.attrs.level === 1;
4980
- if (isActive) {
4981
- commands.call(setBlockTypeCommand.key, {
4982
- nodeType: paragraphSchema.type(ctx2)
4983
- });
4984
- } else {
4985
- commands.call(wrapInHeadingCommand.key, 1);
4986
- }
4933
+ return () => commands.call(toggleHighlightMarkCommand.key);
4987
4934
  }
4988
- }).addItem("h2", {
4989
- label: ctx ? i18n(ctx, "menu.item.h2") : "Heading 2",
4990
- icon: (_b = config == null ? void 0 : config.h2Icon) != null ? _b : h2Icon,
4991
- active: (ctx2) => {
4992
- const view = ctx2.get(editorViewCtx);
4993
- const result = findNodeInSelection(view.state, headingSchema.type(ctx2));
4994
- return result.hasNode && !!result.target && result.target.attrs.level === 2;
4995
- },
4996
- onRun: (ctx2) => {
4997
- const commands = ctx2.get(commandsCtx);
4998
- const view = ctx2.get(editorViewCtx);
4999
- const result = findNodeInSelection(view.state, headingSchema.type(ctx2));
5000
- const isActive = result.hasNode && !!result.target && result.target.attrs.level === 2;
5001
- if (isActive) {
5002
- commands.call(setBlockTypeCommand.key, {
5003
- nodeType: paragraphSchema.type(ctx2)
4935
+ },
4936
+ HighlightMarkEnter: {
4937
+ shortcuts: "Enter",
4938
+ command: (ctx) => {
4939
+ return (state, dispatch) => {
4940
+ const markType = highlightMarkSchema.type(ctx);
4941
+ const { $from, empty } = state.selection;
4942
+ if (!empty) return false;
4943
+ const marks = state.storedMarks || $from.marks();
4944
+ if (!markType.isInSet(marks)) return false;
4945
+ if (dispatch) {
4946
+ const hardbreak = state.schema.nodes.hardbreak;
4947
+ if (hardbreak) {
4948
+ let tr = state.tr.replaceSelectionWith(hardbreak.create(), true);
4949
+ dispatch(tr.scrollIntoView());
4950
+ }
4951
+ }
4952
+ return true;
4953
+ };
4954
+ }
4955
+ },
4956
+ HighlightMarkArrowDown: {
4957
+ shortcuts: "ArrowDown",
4958
+ command: (ctx) => {
4959
+ return (state, dispatch, view) => {
4960
+ if (!view) return false;
4961
+ const markType = highlightMarkSchema.type(ctx);
4962
+ const { selection } = state;
4963
+ const { $from, empty } = selection;
4964
+ if (!empty) return false;
4965
+ const isTextblock = $from.parent.isTextblock;
4966
+ if (!isTextblock) return false;
4967
+ let hasNodeAfter = false;
4968
+ state.doc.nodesBetween(
4969
+ $from.after(),
4970
+ state.doc.content.size,
4971
+ (node) => {
4972
+ if (node.isTextblock) hasNodeAfter = true;
4973
+ }
4974
+ );
4975
+ if (hasNodeAfter) return false;
4976
+ let hasHighlight = false;
4977
+ if ($from.parent.content.size === 0) {
4978
+ const marks = state.storedMarks || $from.marks();
4979
+ if (markType.isInSet(marks)) {
4980
+ hasHighlight = true;
4981
+ }
4982
+ } else if ($from.parent.content.size === 1 && $from.parent.textContent === "\u200B") {
4983
+ const child = $from.parent.child(0);
4984
+ if (child.marks.some((m) => m.type === markType)) {
4985
+ hasHighlight = true;
4986
+ }
4987
+ } else {
4988
+ $from.parent.descendants((node) => {
4989
+ if (node.isText && node.marks.some((m) => m.type === markType)) {
4990
+ hasHighlight = true;
4991
+ }
4992
+ });
4993
+ }
4994
+ if (!hasHighlight) return false;
4995
+ if (!view.endOfTextblock("down")) return false;
4996
+ const paragraphType = state.schema.nodes.paragraph;
4997
+ if (!paragraphType) return false;
4998
+ if (dispatch) {
4999
+ const p = paragraphType.create();
5000
+ const insertPos = state.doc.content.size;
5001
+ let tr = state.tr.insert(insertPos, p);
5002
+ const newPos = insertPos + 1;
5003
+ tr = tr.setSelection(TextSelection.create(tr.doc, newPos));
5004
+ tr = tr.removeStoredMark(markType);
5005
+ dispatch(tr.scrollIntoView());
5006
+ }
5007
+ return true;
5008
+ };
5009
+ }
5010
+ },
5011
+ HighlightMarkBackspace: {
5012
+ shortcuts: "Backspace",
5013
+ command: (ctx) => {
5014
+ return (state, dispatch) => {
5015
+ const markType = highlightMarkSchema.type(ctx);
5016
+ const { selection } = state;
5017
+ const { $from, empty } = selection;
5018
+ if (!empty) return false;
5019
+ const isTextblock = $from.parent.isTextblock;
5020
+ if (!isTextblock) return false;
5021
+ if ($from.parentOffset === 0) {
5022
+ const prevBlockPos = $from.before() - 1;
5023
+ if (prevBlockPos > 0) {
5024
+ const $prev = state.doc.resolve(prevBlockPos);
5025
+ const prevBlock = $prev.parent;
5026
+ if (prevBlock && prevBlock.isTextblock) {
5027
+ let prevHasHighlight = false;
5028
+ prevBlock.descendants((node) => {
5029
+ if (node.marks.some((m) => m.type === markType)) {
5030
+ prevHasHighlight = true;
5031
+ }
5032
+ });
5033
+ if (prevHasHighlight) {
5034
+ if (dispatch) {
5035
+ let tr = state.tr;
5036
+ tr = tr.delete($prev.start() - 1, $prev.end() + 1);
5037
+ dispatch(tr.scrollIntoView());
5038
+ }
5039
+ return true;
5040
+ }
5041
+ }
5042
+ }
5043
+ }
5044
+ let hasHighlight = false;
5045
+ let isPlaceholder = false;
5046
+ if ($from.parent.content.size === 0) {
5047
+ const marks = state.storedMarks || $from.marks();
5048
+ if (markType.isInSet(marks)) {
5049
+ hasHighlight = true;
5050
+ }
5051
+ } else if ($from.parent.content.size === 1 && $from.parent.textContent === "\u200B") {
5052
+ const child = $from.parent.child(0);
5053
+ if (child.marks.some((m) => m.type === markType)) {
5054
+ hasHighlight = true;
5055
+ isPlaceholder = true;
5056
+ }
5057
+ }
5058
+ if (hasHighlight) {
5059
+ if (dispatch) {
5060
+ let tr = state.tr;
5061
+ if (isPlaceholder) {
5062
+ const start = $from.start();
5063
+ const end = $from.end();
5064
+ tr = tr.delete(start, end);
5065
+ }
5066
+ tr = tr.removeStoredMark(markType);
5067
+ dispatch(tr.scrollIntoView());
5068
+ }
5069
+ return true;
5070
+ }
5071
+ return false;
5072
+ };
5073
+ }
5074
+ }
5075
+ });
5076
+ const highlightEmptyBlockPlugin = $prose((ctx) => {
5077
+ return new Plugin({
5078
+ key: new PluginKey("highlightEmptyBlock"),
5079
+ props: {
5080
+ decorations(state) {
5081
+ const markType = highlightMarkSchema.type(ctx);
5082
+ const decorations = [];
5083
+ state.doc.descendants((node, pos) => {
5084
+ if (node.isTextblock) {
5085
+ if (node.content.size === 1 && node.textContent === "\u200B") {
5086
+ const child = node.child(0);
5087
+ if (child.marks.some((m) => m.type === markType)) {
5088
+ decorations.push(
5089
+ Decoration.node(pos, pos + node.nodeSize, {
5090
+ class: "crepe-placeholder crepe-highlight-empty",
5091
+ "data-placeholder": "\u8BF7\u8F93\u5165\u5185\u5BB9"
5092
+ })
5093
+ );
5094
+ }
5095
+ }
5096
+ }
5004
5097
  });
5098
+ const { selection } = state;
5099
+ const { $from, empty } = selection;
5100
+ if (empty && $from.parent.isTextblock && $from.parent.content.size === 0) {
5101
+ const marks = state.storedMarks || $from.marks();
5102
+ if (markType.isInSet(marks)) {
5103
+ const start = $from.start() - 1;
5104
+ decorations.push(
5105
+ Decoration.node(start, start + $from.parent.nodeSize, {
5106
+ class: "crepe-placeholder crepe-highlight-empty",
5107
+ "data-placeholder": "\u8BF7\u8F93\u5165\u5185\u5BB9"
5108
+ })
5109
+ );
5110
+ }
5111
+ }
5112
+ return DecorationSet.create(state.doc, decorations);
5113
+ }
5114
+ },
5115
+ appendTransaction(transactions, _oldState, newState) {
5116
+ const markType = highlightMarkSchema.type(ctx);
5117
+ if (!transactions.some((t) => t.docChanged)) return null;
5118
+ const { empty, $from } = newState.selection;
5119
+ if (!empty || !$from.parent.isTextblock) return null;
5120
+ if ($from.parent.content.size !== 0) return null;
5121
+ const marks = newState.storedMarks || $from.marks();
5122
+ if (!markType.isInSet(marks)) return null;
5123
+ const id = Math.random().toString(36).substring(2, 9);
5124
+ const mark = markType.create({ id });
5125
+ return newState.tr.insert($from.pos, newState.schema.text("\u200B", [mark]));
5126
+ }
5127
+ });
5128
+ });
5129
+ const highlightMark = [
5130
+ highlightMarkAttr,
5131
+ highlightMarkSchema,
5132
+ toggleHighlightMarkCommand,
5133
+ highlightMarkKeymap,
5134
+ remarkHighlightMarkPlugin,
5135
+ highlightEmptyBlockPlugin
5136
+ ];
5137
+
5138
+ const remarkUnderlinePlugin = $remark(
5139
+ "remarkUnderline",
5140
+ () => function() {
5141
+ const data = this.data();
5142
+ function add(key, value) {
5143
+ if (Array.isArray(data[key])) {
5144
+ data[key].push(value);
5005
5145
  } else {
5006
- commands.call(wrapInHeadingCommand.key, 2);
5146
+ data[key] = [value];
5007
5147
  }
5008
5148
  }
5009
- }).addItem("h3", {
5010
- label: ctx ? i18n(ctx, "menu.item.h3") : "Heading 3",
5011
- icon: (_c = config == null ? void 0 : config.h3Icon) != null ? _c : h3Icon,
5149
+ add("toMarkdownExtensions", {
5150
+ handlers: {
5151
+ underline: (node, _, state) => {
5152
+ return `<u>${state.containerPhrasing(node, state)}</u>`;
5153
+ }
5154
+ }
5155
+ });
5156
+ return (ast) => {
5157
+ visit(ast, (node, index, parent) => {
5158
+ if ((node == null ? void 0 : node.type) === "html" && node.value === "<u>" && parent && index != null) {
5159
+ const endIndex = parent.children.findIndex(
5160
+ (n, i) => i > index && n.type === "html" && n.value === "</u>"
5161
+ );
5162
+ if (endIndex !== -1) {
5163
+ const children = parent.children.splice(
5164
+ index,
5165
+ endIndex - index + 1
5166
+ );
5167
+ const content = children.slice(1, -1);
5168
+ parent.children.splice(index, 0, {
5169
+ type: "underline",
5170
+ children: content
5171
+ });
5172
+ return index + 1;
5173
+ }
5174
+ }
5175
+ return;
5176
+ });
5177
+ };
5178
+ }
5179
+ );
5180
+ const underlineAttr = $markAttr("underline");
5181
+ const underlineSchema = $markSchema("underline", (ctx) => ({
5182
+ inclusive: true,
5183
+ parseDOM: [
5184
+ { tag: "u" },
5185
+ {
5186
+ style: "text-decoration",
5187
+ getAttrs: (value) => value === "underline" ? null : false
5188
+ }
5189
+ ],
5190
+ toDOM: (mark) => ["u", ctx.get(underlineAttr.key)(mark), 0],
5191
+ parseMarkdown: {
5192
+ match: (node) => node.type === "underline",
5193
+ runner: (state, node, markType) => {
5194
+ state.openMark(markType);
5195
+ state.next(node.children);
5196
+ state.closeMark(markType);
5197
+ }
5198
+ },
5199
+ toMarkdown: {
5200
+ match: (mark) => mark.type.name === "underline",
5201
+ runner: (state, mark) => {
5202
+ state.withMark(mark, "underline");
5203
+ }
5204
+ }
5205
+ }));
5206
+ const toggleUnderlineCommand = $command(
5207
+ "ToggleUnderline",
5208
+ (ctx) => () => toggleMark(underlineSchema.type(ctx))
5209
+ );
5210
+ const underlineKeymap = $useKeymap("underlineKeymap", {
5211
+ ToggleUnderline: {
5212
+ shortcuts: "Mod-u",
5213
+ command: (ctx) => {
5214
+ const commands = ctx.get(commandsCtx);
5215
+ return () => commands.call(toggleUnderlineCommand.key);
5216
+ }
5217
+ }
5218
+ });
5219
+ const underline = [
5220
+ underlineAttr,
5221
+ underlineSchema,
5222
+ toggleUnderlineCommand,
5223
+ underlineKeymap,
5224
+ remarkUnderlinePlugin
5225
+ ];
5226
+
5227
+ const listeners = /* @__PURE__ */ new Set();
5228
+ let _popupCount = 0;
5229
+ function getIsAnyPopupOpen() {
5230
+ return _popupCount > 0;
5231
+ }
5232
+ function addPopupChangeListener(fn) {
5233
+ listeners.add(fn);
5234
+ return () => listeners.delete(fn);
5235
+ }
5236
+ function incrementPopupCount() {
5237
+ const wasZero = _popupCount === 0;
5238
+ _popupCount++;
5239
+ if (wasZero) {
5240
+ listeners.forEach((fn) => fn());
5241
+ }
5242
+ }
5243
+ function decrementPopupCount() {
5244
+ _popupCount = Math.max(0, _popupCount - 1);
5245
+ if (_popupCount === 0) {
5246
+ listeners.forEach((fn) => fn());
5247
+ }
5248
+ }
5249
+ function resetPopupCount() {
5250
+ _popupCount = 0;
5251
+ listeners.forEach((fn) => fn());
5252
+ }
5253
+
5254
+ function getGroups(config, ctx) {
5255
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
5256
+ const groupBuilder = new GroupBuilder();
5257
+ groupBuilder.addGroup("heading", ctx ? i18n(ctx, "toolbar.heading") : "Heading").addItem("h1", {
5258
+ label: ctx ? i18n(ctx, "menu.item.h1") : "Heading 1",
5259
+ icon: (_a = config == null ? void 0 : config.h1Icon) != null ? _a : h1Icon,
5012
5260
  active: (ctx2) => {
5013
5261
  const view = ctx2.get(editorViewCtx);
5014
5262
  const result = findNodeInSelection(view.state, headingSchema.type(ctx2));
5015
- return result.hasNode && !!result.target && result.target.attrs.level === 3;
5263
+ return result.hasNode && !!result.target && result.target.attrs.level === 1;
5016
5264
  },
5017
5265
  onRun: (ctx2) => {
5018
5266
  const commands = ctx2.get(commandsCtx);
5019
5267
  const view = ctx2.get(editorViewCtx);
5020
5268
  const result = findNodeInSelection(view.state, headingSchema.type(ctx2));
5021
- const isActive = result.hasNode && !!result.target && result.target.attrs.level === 3;
5269
+ const isActive = result.hasNode && !!result.target && result.target.attrs.level === 1;
5022
5270
  if (isActive) {
5023
5271
  commands.call(setBlockTypeCommand.key, {
5024
5272
  nodeType: paragraphSchema.type(ctx2)
5025
5273
  });
5026
5274
  } else {
5027
- commands.call(wrapInHeadingCommand.key, 3);
5275
+ commands.call(wrapInHeadingCommand.key, 1);
5028
5276
  }
5029
5277
  }
5030
- }).addItem("h4", {
5031
- label: ctx ? i18n(ctx, "menu.item.h4") : "Heading 4",
5032
- icon: (_d = config == null ? void 0 : config.h4Icon) != null ? _d : h4Icon,
5278
+ }).addItem("h2", {
5279
+ label: ctx ? i18n(ctx, "menu.item.h2") : "Heading 2",
5280
+ icon: (_b = config == null ? void 0 : config.h2Icon) != null ? _b : h2Icon,
5033
5281
  active: (ctx2) => {
5034
5282
  const view = ctx2.get(editorViewCtx);
5035
5283
  const result = findNodeInSelection(view.state, headingSchema.type(ctx2));
5036
- return result.hasNode && !!result.target && result.target.attrs.level === 4;
5284
+ return result.hasNode && !!result.target && result.target.attrs.level === 2;
5037
5285
  },
5038
5286
  onRun: (ctx2) => {
5039
5287
  const commands = ctx2.get(commandsCtx);
5040
5288
  const view = ctx2.get(editorViewCtx);
5041
5289
  const result = findNodeInSelection(view.state, headingSchema.type(ctx2));
5042
- const isActive = result.hasNode && !!result.target && result.target.attrs.level === 4;
5290
+ const isActive = result.hasNode && !!result.target && result.target.attrs.level === 2;
5043
5291
  if (isActive) {
5044
5292
  commands.call(setBlockTypeCommand.key, {
5045
5293
  nodeType: paragraphSchema.type(ctx2)
5046
5294
  });
5047
5295
  } else {
5048
- commands.call(wrapInHeadingCommand.key, 4);
5296
+ commands.call(wrapInHeadingCommand.key, 2);
5049
5297
  }
5050
5298
  }
5051
- }).addItem("h5", {
5052
- label: ctx ? i18n(ctx, "menu.item.h5") : "Heading 5",
5053
- icon: (_e = config == null ? void 0 : config.h5Icon) != null ? _e : h5Icon,
5299
+ }).addItem("h3", {
5300
+ label: ctx ? i18n(ctx, "menu.item.h3") : "Heading 3",
5301
+ icon: (_c = config == null ? void 0 : config.h3Icon) != null ? _c : h3Icon,
5054
5302
  active: (ctx2) => {
5055
5303
  const view = ctx2.get(editorViewCtx);
5056
5304
  const result = findNodeInSelection(view.state, headingSchema.type(ctx2));
5057
- return result.hasNode && !!result.target && result.target.attrs.level === 5;
5305
+ return result.hasNode && !!result.target && result.target.attrs.level === 3;
5058
5306
  },
5059
5307
  onRun: (ctx2) => {
5060
5308
  const commands = ctx2.get(commandsCtx);
5061
5309
  const view = ctx2.get(editorViewCtx);
5062
5310
  const result = findNodeInSelection(view.state, headingSchema.type(ctx2));
5063
- const isActive = result.hasNode && !!result.target && result.target.attrs.level === 5;
5311
+ const isActive = result.hasNode && !!result.target && result.target.attrs.level === 3;
5064
5312
  if (isActive) {
5065
5313
  commands.call(setBlockTypeCommand.key, {
5066
5314
  nodeType: paragraphSchema.type(ctx2)
5067
5315
  });
5068
5316
  } else {
5069
- commands.call(wrapInHeadingCommand.key, 5);
5317
+ commands.call(wrapInHeadingCommand.key, 3);
5070
5318
  }
5071
5319
  }
5072
- }).addItem("h6", {
5073
- label: ctx ? i18n(ctx, "menu.item.h6") : "Heading 6",
5074
- icon: (_f = config == null ? void 0 : config.h6Icon) != null ? _f : h6Icon,
5320
+ }).addItem("h4", {
5321
+ label: ctx ? i18n(ctx, "menu.item.h4") : "Heading 4",
5322
+ icon: (_d = config == null ? void 0 : config.h4Icon) != null ? _d : h4Icon,
5075
5323
  active: (ctx2) => {
5076
5324
  const view = ctx2.get(editorViewCtx);
5077
5325
  const result = findNodeInSelection(view.state, headingSchema.type(ctx2));
5078
- return result.hasNode && !!result.target && result.target.attrs.level === 6;
5326
+ return result.hasNode && !!result.target && result.target.attrs.level === 4;
5079
5327
  },
5080
5328
  onRun: (ctx2) => {
5081
5329
  const commands = ctx2.get(commandsCtx);
5082
5330
  const view = ctx2.get(editorViewCtx);
5083
5331
  const result = findNodeInSelection(view.state, headingSchema.type(ctx2));
5084
- const isActive = result.hasNode && !!result.target && result.target.attrs.level === 6;
5332
+ const isActive = result.hasNode && !!result.target && result.target.attrs.level === 4;
5085
5333
  if (isActive) {
5086
5334
  commands.call(setBlockTypeCommand.key, {
5087
5335
  nodeType: paragraphSchema.type(ctx2)
5088
5336
  });
5089
5337
  } else {
5090
- commands.call(wrapInHeadingCommand.key, 6);
5338
+ commands.call(wrapInHeadingCommand.key, 4);
5091
5339
  }
5092
5340
  }
5093
- });
5094
- groupBuilder.addGroup(
5095
- "formatting",
5096
- ctx ? i18n(ctx, "toolbar.formatting") : "Formatting"
5097
- ).addItem("bold", {
5098
- label: ctx ? i18n(ctx, "menu.item.bold") : "Bold",
5099
- icon: (_g = config == null ? void 0 : config.boldIcon) != null ? _g : boldIcon,
5100
- active: (ctx2) => {
5101
- const commands = ctx2.get(commandsCtx);
5102
- return commands.call(isMarkSelectedCommand.key, strongSchema.type(ctx2));
5103
- },
5104
- onRun: (ctx2) => {
5105
- const commands = ctx2.get(commandsCtx);
5106
- commands.call(toggleStrongCommand.key);
5107
- }
5108
- }).addItem("italic", {
5109
- label: ctx ? i18n(ctx, "menu.item.italic") : "Italic",
5110
- icon: (_h = config == null ? void 0 : config.italicIcon) != null ? _h : italicIcon,
5111
- active: (ctx2) => {
5112
- const commands = ctx2.get(commandsCtx);
5113
- return commands.call(
5114
- isMarkSelectedCommand.key,
5115
- emphasisSchema.type(ctx2)
5116
- );
5117
- },
5118
- onRun: (ctx2) => {
5119
- const commands = ctx2.get(commandsCtx);
5120
- commands.call(toggleEmphasisCommand.key);
5121
- }
5122
- }).addItem("strikethrough", {
5123
- label: ctx ? i18n(ctx, "menu.item.strikethrough") : "Strikethrough",
5124
- icon: (_i = config == null ? void 0 : config.strikethroughIcon) != null ? _i : strikethroughIcon,
5125
- active: (ctx2) => {
5126
- const commands = ctx2.get(commandsCtx);
5127
- return commands.call(
5128
- isMarkSelectedCommand.key,
5129
- strikethroughSchema.type(ctx2)
5130
- );
5131
- },
5132
- onRun: (ctx2) => {
5133
- const commands = ctx2.get(commandsCtx);
5134
- commands.call(toggleStrikethroughCommand.key);
5135
- }
5136
- }).addItem("underline", {
5137
- label: ctx ? i18n(ctx, "menu.item.underline") : "Underline",
5138
- icon: (_j = config == null ? void 0 : config.underlineIcon) != null ? _j : underlineIcon,
5139
- active: (ctx2) => {
5140
- const commands = ctx2.get(commandsCtx);
5141
- return commands.call(
5142
- isMarkSelectedCommand.key,
5143
- underlineSchema.type(ctx2)
5144
- );
5145
- },
5146
- onRun: (ctx2) => {
5147
- const commands = ctx2.get(commandsCtx);
5148
- commands.call(toggleUnderlineCommand.key);
5149
- }
5150
- });
5151
- const functionGroup = groupBuilder.addGroup(
5152
- "function",
5153
- ctx ? i18n(ctx, "toolbar.function") : "Function"
5154
- );
5155
- functionGroup.addItem("highlight", {
5156
- label: ctx ? i18n(ctx, "menu.item.highlight") : "Highlight",
5157
- icon: (_k = config == null ? void 0 : config.highlightIcon) != null ? _k : highLineCodeIcon,
5158
- active: (ctx2) => {
5159
- const commands = ctx2.get(commandsCtx);
5160
- return commands.call(
5161
- isMarkSelectedCommand.key,
5162
- highlightMarkSchema.type(ctx2)
5163
- );
5164
- },
5165
- onRun: (ctx2) => {
5166
- const commands = ctx2.get(commandsCtx);
5167
- commands.call(toggleHighlightMarkCommand.key);
5168
- }
5169
- });
5170
- functionGroup.addItem("code", {
5171
- label: ctx ? i18n(ctx, "menu.item.lineCode") : "Inline Code",
5172
- icon: (_l = config == null ? void 0 : config.codeIcon) != null ? _l : linCodeIcon,
5173
- active: (ctx2) => {
5174
- const commands = ctx2.get(commandsCtx);
5175
- return commands.call(
5176
- isMarkSelectedCommand.key,
5177
- inlineCodeSchema.type(ctx2)
5178
- );
5179
- },
5180
- onRun: (ctx2) => {
5181
- const commands = ctx2.get(commandsCtx);
5182
- commands.call(toggleInlineCodeCommand.key);
5183
- }
5184
- });
5185
- functionGroup.addItem("link", {
5186
- label: ctx ? i18n(ctx, "menu.item.link") : "Link",
5187
- icon: (_m = config == null ? void 0 : config.linkIcon) != null ? _m : linkIcon,
5341
+ }).addItem("h5", {
5342
+ label: ctx ? i18n(ctx, "menu.item.h5") : "Heading 5",
5343
+ icon: (_e = config == null ? void 0 : config.h5Icon) != null ? _e : h5Icon,
5188
5344
  active: (ctx2) => {
5189
- const commands = ctx2.get(commandsCtx);
5190
- return commands.call(isMarkSelectedCommand.key, linkSchema.type(ctx2));
5345
+ const view = ctx2.get(editorViewCtx);
5346
+ const result = findNodeInSelection(view.state, headingSchema.type(ctx2));
5347
+ return result.hasNode && !!result.target && result.target.attrs.level === 5;
5191
5348
  },
5192
5349
  onRun: (ctx2) => {
5193
5350
  const commands = ctx2.get(commandsCtx);
5194
- commands.call(toggleLinkCommand.key);
5195
- }
5196
- });
5197
- (_n = config == null ? void 0 : config.buildToolbar) == null ? void 0 : _n.call(config, groupBuilder);
5198
- return groupBuilder.build();
5199
- }
5200
-
5201
- const supportedFontsCache = /* @__PURE__ */ new Map();
5202
- const isFontSupported = (fontFamily) => {
5203
- if (!fontFamily) return true;
5204
- const normalizedFont = fontFamily.replace(/['"]/g, "");
5205
- if (supportedFontsCache.has(normalizedFont)) {
5206
- return supportedFontsCache.get(normalizedFont);
5207
- }
5208
- if (typeof document === "undefined") return true;
5209
- const canvas = document.createElement("canvas");
5210
- const context = canvas.getContext("2d");
5211
- if (!context) return true;
5212
- const text = "abcdefghijklmnopqrstuvwxyz0123456789";
5213
- const size = "72px";
5214
- context.font = `${size} monospace`;
5215
- const baseMono = context.measureText(text).width;
5216
- context.font = `${size} sans-serif`;
5217
- const baseSans = context.measureText(text).width;
5218
- context.font = `${size} "${normalizedFont}", monospace`;
5219
- const testMono = context.measureText(text).width;
5220
- context.font = `${size} "${normalizedFont}", sans-serif`;
5221
- const testSans = context.measureText(text).width;
5222
- const supported = testMono !== baseMono || testSans !== baseSans;
5223
- supportedFontsCache.set(normalizedFont, supported);
5224
- return supported;
5225
- };
5226
- const remarkFontPlugin = $remark(
5227
- "remarkFont",
5228
- () => function() {
5229
- const data = this.data();
5230
- function add(key, value) {
5231
- if (Array.isArray(data[key])) {
5232
- data[key].push(value);
5233
- } else {
5234
- data[key] = [value];
5235
- }
5236
- }
5237
- add("toMarkdownExtensions", {
5238
- handlers: {
5239
- fontFamily: (node, _, state) => {
5240
- return `<span style="font-family:${node.fontFamily}">${state.containerPhrasing(node, state)}</span>`;
5241
- },
5242
- fontSize: (node, _, state) => {
5243
- return `<span style="font-size:${node.fontSize}">${state.containerPhrasing(node, state)}</span>`;
5244
- }
5245
- }
5246
- });
5247
- return (ast) => {
5248
- visit(ast, (node, index, parent) => {
5249
- if ((node == null ? void 0 : node.type) === "html" && node.value.startsWith("<span") && parent && index != null) {
5250
- const hasFontFamily = node.value.match(/font-family:\s*([^"';>]+)/);
5251
- const hasFontSize = node.value.match(/font-size:\s*([^"';>]+)/);
5252
- if (!hasFontFamily && !hasFontSize) return;
5253
- let fontFamily = null;
5254
- let fontSize = null;
5255
- let markType = null;
5256
- if (hasFontFamily) {
5257
- fontFamily = hasFontFamily[1].trim();
5258
- markType = "fontFamily";
5259
- } else if (hasFontSize) {
5260
- fontSize = hasFontSize[1].trim();
5261
- markType = "fontSize";
5262
- }
5263
- const endIndex = parent.children.findIndex(
5264
- (n, i) => i > index && n.type === "html" && n.value === "</span>"
5265
- );
5266
- if (endIndex !== -1 && markType && (fontFamily || fontSize)) {
5267
- const children = parent.children.splice(
5268
- index,
5269
- endIndex - index + 1
5270
- );
5271
- const content = children.slice(1, -1);
5272
- const payload = {
5273
- type: markType,
5274
- children: content
5275
- };
5276
- if (fontFamily) payload.fontFamily = fontFamily;
5277
- if (fontSize) payload.fontSize = fontSize;
5278
- parent.children.splice(index, 0, payload);
5279
- return index + 1;
5280
- }
5281
- }
5282
- return;
5283
- });
5284
- };
5285
- }
5286
- );
5287
- const fontFamilyAttr = $markAttr("fontFamily");
5288
- const fontFamilySchema = $markSchema("fontFamily", (_ctx) => ({
5289
- inclusive: true,
5290
- attrs: {
5291
- fontFamily: { default: null }
5292
- },
5293
- parseDOM: [
5294
- {
5295
- tag: 'span[style*="font-family"]',
5296
- getAttrs: (dom) => {
5297
- if (!(dom instanceof HTMLElement)) return false;
5298
- const fontFamily = dom.style.fontFamily || null;
5299
- if (!isFontSupported(fontFamily)) return false;
5300
- return { fontFamily };
5351
+ const view = ctx2.get(editorViewCtx);
5352
+ const result = findNodeInSelection(view.state, headingSchema.type(ctx2));
5353
+ const isActive = result.hasNode && !!result.target && result.target.attrs.level === 5;
5354
+ if (isActive) {
5355
+ commands.call(setBlockTypeCommand.key, {
5356
+ nodeType: paragraphSchema.type(ctx2)
5357
+ });
5358
+ } else {
5359
+ commands.call(wrapInHeadingCommand.key, 5);
5301
5360
  }
5302
5361
  }
5303
- ],
5304
- toDOM: (mark) => {
5305
- return ["span", { style: `font-family: ${mark.attrs.fontFamily}` }, 0];
5306
- },
5307
- parseMarkdown: {
5308
- match: (node) => node.type === "fontFamily",
5309
- runner: (state, node, markType) => {
5310
- state.openMark(markType, { fontFamily: node.fontFamily });
5311
- state.next(node.children);
5312
- state.closeMark(markType);
5362
+ }).addItem("h6", {
5363
+ label: ctx ? i18n(ctx, "menu.item.h6") : "Heading 6",
5364
+ icon: (_f = config == null ? void 0 : config.h6Icon) != null ? _f : h6Icon,
5365
+ active: (ctx2) => {
5366
+ const view = ctx2.get(editorViewCtx);
5367
+ const result = findNodeInSelection(view.state, headingSchema.type(ctx2));
5368
+ return result.hasNode && !!result.target && result.target.attrs.level === 6;
5369
+ },
5370
+ onRun: (ctx2) => {
5371
+ const commands = ctx2.get(commandsCtx);
5372
+ const view = ctx2.get(editorViewCtx);
5373
+ const result = findNodeInSelection(view.state, headingSchema.type(ctx2));
5374
+ const isActive = result.hasNode && !!result.target && result.target.attrs.level === 6;
5375
+ if (isActive) {
5376
+ commands.call(setBlockTypeCommand.key, {
5377
+ nodeType: paragraphSchema.type(ctx2)
5378
+ });
5379
+ } else {
5380
+ commands.call(wrapInHeadingCommand.key, 6);
5381
+ }
5313
5382
  }
5314
- },
5315
- toMarkdown: {
5316
- match: (mark) => mark.type.name === "fontFamily",
5317
- runner: (state, mark) => {
5318
- state.withMark(mark, "fontFamily", void 0, {
5319
- fontFamily: mark.attrs.fontFamily
5320
- });
5383
+ });
5384
+ groupBuilder.addGroup(
5385
+ "formatting",
5386
+ ctx ? i18n(ctx, "toolbar.formatting") : "Formatting"
5387
+ ).addItem("bold", {
5388
+ label: ctx ? i18n(ctx, "menu.item.bold") : "Bold",
5389
+ icon: (_g = config == null ? void 0 : config.boldIcon) != null ? _g : boldIcon,
5390
+ active: (ctx2) => {
5391
+ const commands = ctx2.get(commandsCtx);
5392
+ return commands.call(isMarkSelectedCommand.key, strongSchema.type(ctx2));
5393
+ },
5394
+ onRun: (ctx2) => {
5395
+ const commands = ctx2.get(commandsCtx);
5396
+ commands.call(toggleStrongCommand.key);
5321
5397
  }
5322
- }
5323
- }));
5324
- const fontSizeAttr = $markAttr("fontSize");
5325
- const fontSizeSchema = $markSchema("fontSize", (_ctx) => ({
5326
- inclusive: true,
5327
- attrs: {
5328
- fontSize: { default: null }
5329
- },
5330
- parseDOM: [
5331
- {
5332
- tag: 'span[style*="font-size"]',
5333
- getAttrs: (dom) => {
5334
- if (!(dom instanceof HTMLElement)) return false;
5335
- return { fontSize: dom.style.fontSize || null };
5336
- }
5398
+ }).addItem("italic", {
5399
+ label: ctx ? i18n(ctx, "menu.item.italic") : "Italic",
5400
+ icon: (_h = config == null ? void 0 : config.italicIcon) != null ? _h : italicIcon,
5401
+ active: (ctx2) => {
5402
+ const commands = ctx2.get(commandsCtx);
5403
+ return commands.call(
5404
+ isMarkSelectedCommand.key,
5405
+ emphasisSchema.type(ctx2)
5406
+ );
5407
+ },
5408
+ onRun: (ctx2) => {
5409
+ const commands = ctx2.get(commandsCtx);
5410
+ commands.call(toggleEmphasisCommand.key);
5337
5411
  }
5338
- ],
5339
- toDOM: (mark) => {
5340
- return ["span", { style: `font-size: ${mark.attrs.fontSize}` }, 0];
5341
- },
5342
- parseMarkdown: {
5343
- match: (node) => node.type === "fontSize",
5344
- runner: (state, node, markType) => {
5345
- state.openMark(markType, { fontSize: node.fontSize });
5346
- state.next(node.children);
5347
- state.closeMark(markType);
5412
+ }).addItem("strikethrough", {
5413
+ label: ctx ? i18n(ctx, "menu.item.strikethrough") : "Strikethrough",
5414
+ icon: (_i = config == null ? void 0 : config.strikethroughIcon) != null ? _i : strikethroughIcon,
5415
+ active: (ctx2) => {
5416
+ const commands = ctx2.get(commandsCtx);
5417
+ return commands.call(
5418
+ isMarkSelectedCommand.key,
5419
+ strikethroughSchema.type(ctx2)
5420
+ );
5421
+ },
5422
+ onRun: (ctx2) => {
5423
+ const commands = ctx2.get(commandsCtx);
5424
+ commands.call(toggleStrikethroughCommand.key);
5348
5425
  }
5349
- },
5350
- toMarkdown: {
5351
- match: (mark) => mark.type.name === "fontSize",
5352
- runner: (state, mark) => {
5353
- state.withMark(mark, "fontSize", void 0, {
5354
- fontSize: mark.attrs.fontSize
5355
- });
5426
+ }).addItem("underline", {
5427
+ label: ctx ? i18n(ctx, "menu.item.underline") : "Underline",
5428
+ icon: (_j = config == null ? void 0 : config.underlineIcon) != null ? _j : underlineIcon,
5429
+ active: (ctx2) => {
5430
+ const commands = ctx2.get(commandsCtx);
5431
+ return commands.call(
5432
+ isMarkSelectedCommand.key,
5433
+ underlineSchema.type(ctx2)
5434
+ );
5435
+ },
5436
+ onRun: (ctx2) => {
5437
+ const commands = ctx2.get(commandsCtx);
5438
+ commands.call(toggleUnderlineCommand.key);
5356
5439
  }
5357
- }
5358
- }));
5359
- const toggleFontFamilyCommand = $command(
5360
- "ToggleFontFamily",
5361
- (ctx) => (fontFamily) => {
5362
- return (state, dispatch) => {
5363
- const markType = fontFamilySchema.type(ctx);
5364
- const { $cursor, ranges } = state.selection;
5365
- if (dispatch) {
5366
- let tr = state.tr;
5367
- if ($cursor) {
5368
- const marks = state.storedMarks || $cursor.marks();
5369
- const currentMark = markType.isInSet(marks);
5370
- if (currentMark && currentMark.attrs.fontFamily === fontFamily) {
5371
- tr = tr.removeStoredMark(markType);
5372
- } else {
5373
- tr = tr.removeStoredMark(markType);
5374
- if (fontFamily)
5375
- tr = tr.addStoredMark(markType.create({ fontFamily }));
5376
- }
5377
- } else {
5378
- let hasSameFontFamily = false;
5379
- for (const range of ranges) {
5380
- const { $from, $to } = range;
5381
- state.doc.nodesBetween($from.pos, $to.pos, (node) => {
5382
- if (node.isText) {
5383
- const mark = markType.isInSet(node.marks);
5384
- if (mark && mark.attrs.fontFamily === fontFamily) {
5385
- hasSameFontFamily = true;
5386
- }
5387
- }
5388
- });
5389
- }
5390
- for (const range of ranges) {
5391
- const { $from, $to } = range;
5392
- tr = tr.removeMark($from.pos, $to.pos, markType);
5393
- if (!hasSameFontFamily && fontFamily) {
5394
- tr = tr.addMark(
5395
- $from.pos,
5396
- $to.pos,
5397
- markType.create({ fontFamily })
5398
- );
5399
- }
5400
- }
5401
- }
5402
- dispatch(tr.scrollIntoView());
5403
- }
5404
- return true;
5405
- };
5406
- }
5407
- );
5408
- const toggleFontSizeCommand = $command(
5409
- "ToggleFontSize",
5410
- (ctx) => (fontSize) => {
5411
- return (state, dispatch) => {
5412
- const markType = fontSizeSchema.type(ctx);
5413
- const { $cursor, ranges } = state.selection;
5414
- if (dispatch) {
5415
- let tr = state.tr;
5416
- if ($cursor) {
5417
- const marks = state.storedMarks || $cursor.marks();
5418
- const currentMark = markType.isInSet(marks);
5419
- if (currentMark && currentMark.attrs.fontSize === fontSize) {
5420
- tr = tr.removeStoredMark(markType);
5421
- } else {
5422
- tr = tr.removeStoredMark(markType);
5423
- if (fontSize) tr = tr.addStoredMark(markType.create({ fontSize }));
5424
- }
5425
- } else {
5426
- let hasSameFontSize = false;
5427
- for (const range of ranges) {
5428
- const { $from, $to } = range;
5429
- state.doc.nodesBetween($from.pos, $to.pos, (node) => {
5430
- if (node.isText) {
5431
- const mark = markType.isInSet(node.marks);
5432
- if (mark && mark.attrs.fontSize === fontSize) {
5433
- hasSameFontSize = true;
5434
- }
5435
- }
5436
- });
5437
- }
5438
- for (const range of ranges) {
5439
- const { $from, $to } = range;
5440
- tr = tr.removeMark($from.pos, $to.pos, markType);
5441
- if (!hasSameFontSize && fontSize) {
5442
- tr = tr.addMark(
5443
- $from.pos,
5444
- $to.pos,
5445
- markType.create({ fontSize })
5446
- );
5447
- }
5448
- }
5449
- }
5450
- dispatch(tr.scrollIntoView());
5451
- }
5452
- return true;
5453
- };
5454
- }
5455
- );
5456
- function stripFontFamilyFromExternalHTML(html) {
5457
- if (html.includes("data-pm-slice")) return html;
5458
- try {
5459
- const template = document.createElement("template");
5460
- template.innerHTML = html;
5461
- const styledElements = template.content.querySelectorAll(
5462
- '[style*="font-family"]'
5463
- );
5464
- styledElements.forEach((el) => {
5465
- if (el instanceof HTMLElement) {
5466
- el.style.removeProperty("font-family");
5467
- }
5468
- });
5469
- const fontElements = template.content.querySelectorAll("font[face]");
5470
- fontElements.forEach((el) => {
5471
- if (el instanceof HTMLElement) {
5472
- el.removeAttribute("face");
5473
- }
5474
- });
5475
- html = template.innerHTML;
5476
- template.remove();
5477
- } catch (e) {
5478
- }
5479
- return html;
5440
+ });
5441
+ const functionGroup = groupBuilder.addGroup(
5442
+ "function",
5443
+ ctx ? i18n(ctx, "toolbar.function") : "Function"
5444
+ );
5445
+ functionGroup.addItem("highlight", {
5446
+ label: ctx ? i18n(ctx, "menu.item.highlight") : "Highlight",
5447
+ icon: (_k = config == null ? void 0 : config.highlightIcon) != null ? _k : highLineCodeIcon,
5448
+ active: (ctx2) => {
5449
+ const commands = ctx2.get(commandsCtx);
5450
+ return commands.call(
5451
+ isMarkSelectedCommand.key,
5452
+ highlightMarkSchema.type(ctx2)
5453
+ );
5454
+ },
5455
+ onRun: (ctx2) => {
5456
+ const commands = ctx2.get(commandsCtx);
5457
+ commands.call(toggleHighlightMarkCommand.key);
5458
+ }
5459
+ });
5460
+ functionGroup.addItem("code", {
5461
+ label: ctx ? i18n(ctx, "menu.item.lineCode") : "Inline Code",
5462
+ icon: (_l = config == null ? void 0 : config.codeIcon) != null ? _l : linCodeIcon,
5463
+ active: (ctx2) => {
5464
+ const commands = ctx2.get(commandsCtx);
5465
+ return commands.call(
5466
+ isMarkSelectedCommand.key,
5467
+ inlineCodeSchema.type(ctx2)
5468
+ );
5469
+ },
5470
+ onRun: (ctx2) => {
5471
+ const commands = ctx2.get(commandsCtx);
5472
+ commands.call(toggleInlineCodeCommand.key);
5473
+ }
5474
+ });
5475
+ functionGroup.addItem("link", {
5476
+ label: ctx ? i18n(ctx, "menu.item.link") : "Link",
5477
+ icon: (_m = config == null ? void 0 : config.linkIcon) != null ? _m : linkIcon,
5478
+ active: (ctx2) => {
5479
+ const commands = ctx2.get(commandsCtx);
5480
+ return commands.call(isMarkSelectedCommand.key, linkSchema.type(ctx2));
5481
+ },
5482
+ onRun: (ctx2) => {
5483
+ const commands = ctx2.get(commandsCtx);
5484
+ commands.call(toggleLinkCommand.key);
5485
+ }
5486
+ });
5487
+ (_n = config == null ? void 0 : config.buildToolbar) == null ? void 0 : _n.call(config, groupBuilder);
5488
+ return groupBuilder.build();
5480
5489
  }
5481
- const fontPlugins = [
5482
- fontFamilyAttr,
5483
- fontFamilySchema,
5484
- toggleFontFamilyCommand,
5485
- fontSizeAttr,
5486
- fontSizeSchema,
5487
- toggleFontSizeCommand,
5488
- remarkFontPlugin
5489
- ];
5490
5490
 
5491
5491
  const activeIconMap = {
5492
5492
  [boldIcon]: boldIconActive,
@@ -5519,7 +5519,7 @@ const Toolbar = defineComponent({
5519
5519
  ctx: { type: Object, required: true },
5520
5520
  hide: { type: Function, required: true },
5521
5521
  show: { type: Object, required: true },
5522
- selection: { type: Object, required: true },
5522
+ state: { type: Object, required: true },
5523
5523
  config: { type: Object, required: false },
5524
5524
  isFixed: { type: Boolean, required: false }
5525
5525
  },
@@ -6121,17 +6121,17 @@ const Toolbar = defineComponent({
6121
6121
  if (ctx) fn(ctx);
6122
6122
  };
6123
6123
  function checkActive(checker) {
6124
- var _a;
6125
- keepAlive(props.selection.value);
6126
- const status = (_a = ctx == null ? void 0 : ctx.get(editorCtx)) == null ? void 0 : _a.status;
6124
+ var _a, _b;
6125
+ keepAlive(props.state, (_a = props.state) == null ? void 0 : _a.value);
6126
+ const status = (_b = ctx == null ? void 0 : ctx.get(editorCtx)) == null ? void 0 : _b.status;
6127
6127
  if (status !== EditorStatus.Created) return false;
6128
6128
  return checker(ctx);
6129
6129
  }
6130
6130
  const blockGroups = computed(() => getGroups$1("", void 0, ctx));
6131
6131
  const activeBlockItem = computed(() => {
6132
- var _a;
6133
- keepAlive(props.selection.value);
6134
- const status = (_a = ctx == null ? void 0 : ctx.get(editorCtx)) == null ? void 0 : _a.status;
6132
+ var _a, _b;
6133
+ keepAlive(props.state, (_a = props.state) == null ? void 0 : _a.value);
6134
+ const status = (_b = ctx == null ? void 0 : ctx.get(editorCtx)) == null ? void 0 : _b.status;
6135
6135
  if (status !== EditorStatus.Created) return null;
6136
6136
  const view = ctx.get(editorViewCtx);
6137
6137
  const { $from } = view.state.selection;
@@ -6169,9 +6169,9 @@ const Toolbar = defineComponent({
6169
6169
  return targetIcon;
6170
6170
  });
6171
6171
  const currentAlignIndent = computed(() => {
6172
- var _a;
6173
- keepAlive(props.selection.value);
6174
- const status = (_a = ctx == null ? void 0 : ctx.get(editorCtx)) == null ? void 0 : _a.status;
6172
+ var _a, _b;
6173
+ keepAlive(props.state, (_a = props.state) == null ? void 0 : _a.value);
6174
+ const status = (_b = ctx == null ? void 0 : ctx.get(editorCtx)) == null ? void 0 : _b.status;
6175
6175
  if (status !== EditorStatus.Created) return { align: "left", indent: 0 };
6176
6176
  const view = ctx.get(editorViewCtx);
6177
6177
  let align = "left";
@@ -6241,13 +6241,15 @@ const Toolbar = defineComponent({
6241
6241
  }
6242
6242
  };
6243
6243
  const canMerge = computed(() => {
6244
- keepAlive(props.selection.value);
6244
+ var _a;
6245
+ keepAlive(props.state, (_a = props.state) == null ? void 0 : _a.value);
6245
6246
  const view = ctx == null ? void 0 : ctx.get(editorViewCtx);
6246
6247
  if (!view) return false;
6247
6248
  return mergeCells(view.state);
6248
6249
  });
6249
6250
  const canSplit = computed(() => {
6250
- keepAlive(props.selection.value);
6251
+ var _a;
6252
+ keepAlive(props.state, (_a = props.state) == null ? void 0 : _a.value);
6251
6253
  const view = ctx == null ? void 0 : ctx.get(editorViewCtx);
6252
6254
  if (!view) return false;
6253
6255
  return splitCell(view.state);
@@ -6307,16 +6309,16 @@ const Toolbar = defineComponent({
6307
6309
  showAlignMenu.value = false;
6308
6310
  };
6309
6311
  const currentColorState = computed(() => {
6310
- var _a;
6311
- keepAlive(props.selection.value);
6312
- const status = (_a = ctx == null ? void 0 : ctx.get(editorCtx)) == null ? void 0 : _a.status;
6312
+ var _a, _b;
6313
+ keepAlive(props.state, (_a = props.state) == null ? void 0 : _a.value);
6314
+ const status = (_b = ctx == null ? void 0 : ctx.get(editorCtx)) == null ? void 0 : _b.status;
6313
6315
  if (status !== EditorStatus.Created)
6314
6316
  return { textColor: null, bgColor: null };
6315
6317
  const view = ctx.get(editorViewCtx);
6316
6318
  const { state } = view;
6317
6319
  const schema = ctx.get(schemaCtx);
6318
- const tcHasMark = schema.marks[textColorSchema.id];
6319
- const bcHasMark = schema.marks[bgColorSchema.id];
6320
+ const tcHasMark = schema.marks["textColor"];
6321
+ const bcHasMark = schema.marks["bgColor"];
6320
6322
  if (!tcHasMark || !bcHasMark) return { textColor: null, bgColor: null };
6321
6323
  const tcType = textColorSchema.type(ctx);
6322
6324
  const bcType = bgColorSchema.type(ctx);
@@ -6363,8 +6365,8 @@ const Toolbar = defineComponent({
6363
6365
  const { tr } = state;
6364
6366
  const { from, to, empty } = state.selection;
6365
6367
  const schema = ctx.get(schemaCtx);
6366
- const tcHasMark = schema.marks[textColorSchema.id];
6367
- const bcHasMark = schema.marks[bgColorSchema.id];
6368
+ const tcHasMark = schema.marks["textColor"];
6369
+ const bcHasMark = schema.marks["bgColor"];
6368
6370
  if (!tcHasMark || !bcHasMark) return;
6369
6371
  const textColorType = textColorSchema.type(ctx);
6370
6372
  const bgColorType = bgColorSchema.type(ctx);
@@ -6380,29 +6382,37 @@ const Toolbar = defineComponent({
6380
6382
  showColorMenu.value = false;
6381
6383
  };
6382
6384
  const currentFontState = computed(() => {
6383
- var _a;
6384
- keepAlive(props.selection.value);
6385
- const status = (_a = ctx == null ? void 0 : ctx.get(editorCtx)) == null ? void 0 : _a.status;
6385
+ var _a, _b;
6386
+ keepAlive(props.state, (_a = props.state) == null ? void 0 : _a.value);
6387
+ const status = (_b = ctx == null ? void 0 : ctx.get(editorCtx)) == null ? void 0 : _b.status;
6386
6388
  if (status !== EditorStatus.Created)
6387
6389
  return { fontFamily: null, fontSize: null };
6388
6390
  const view = ctx.get(editorViewCtx);
6389
6391
  const { state } = view;
6390
6392
  const schema = ctx.get(schemaCtx);
6391
- const ffHasMark = schema.marks[fontFamilySchema.id];
6392
- const fsHasMark = schema.marks[fontSizeSchema.id];
6393
- if (!ffHasMark || !fsHasMark) return { fontFamily: null, fontSize: null };
6393
+ const ffHasMark = schema.marks["fontFamily"];
6394
+ const fsHasMark = schema.marks["fontSize"];
6395
+ if (!ffHasMark || !fsHasMark) {
6396
+ return { fontFamily: null, fontSize: null };
6397
+ }
6394
6398
  const ffType = fontFamilySchema.type(ctx);
6395
6399
  const fsType = fontSizeSchema.type(ctx);
6396
6400
  const { $cursor, ranges } = state.selection;
6401
+ let result = {
6402
+ fontFamily: null,
6403
+ fontSize: null
6404
+ };
6397
6405
  if ($cursor) {
6398
6406
  let fontFamily = null;
6399
6407
  let fontSize = null;
6400
6408
  const marks = state.storedMarks || $cursor.marks();
6401
6409
  for (const mark of marks) {
6402
- if (mark.type === ffType) fontFamily = mark.attrs.fontFamily;
6403
- if (mark.type === fsType) fontSize = mark.attrs.fontSize;
6410
+ if (mark.type === ffType)
6411
+ fontFamily = mark.attrs.fontFamily || null;
6412
+ if (mark.type === fsType)
6413
+ fontSize = mark.attrs.fontSize || null;
6404
6414
  }
6405
- return { fontFamily, fontSize };
6415
+ result = { fontFamily, fontSize };
6406
6416
  } else {
6407
6417
  const fontFamilies = /* @__PURE__ */ new Set();
6408
6418
  const fontSizes = /* @__PURE__ */ new Set();
@@ -6412,15 +6422,20 @@ const Toolbar = defineComponent({
6412
6422
  if (node.isText) {
6413
6423
  const ffMark = ffType.isInSet(node.marks);
6414
6424
  const fsMark = fsType.isInSet(node.marks);
6415
- fontFamilies.add(ffMark ? ffMark.attrs.fontFamily : null);
6416
- fontSizes.add(fsMark ? fsMark.attrs.fontSize : null);
6425
+ fontFamilies.add(
6426
+ ffMark ? ffMark.attrs.fontFamily : null
6427
+ );
6428
+ fontSizes.add(
6429
+ fsMark ? fsMark.attrs.fontSize : null
6430
+ );
6417
6431
  }
6418
6432
  });
6419
6433
  }
6420
6434
  const fontFamily = fontFamilies.size === 1 ? Array.from(fontFamilies)[0] : "mixed";
6421
6435
  const fontSize = fontSizes.size === 1 ? Array.from(fontSizes)[0] : "mixed";
6422
- return { fontFamily, fontSize };
6436
+ result = { fontFamily, fontSize };
6423
6437
  }
6438
+ return result;
6424
6439
  });
6425
6440
  const setFontFamily = (fontFamily) => {
6426
6441
  const commands = ctx.get(commandsCtx);
@@ -6651,7 +6666,11 @@ const Toolbar = defineComponent({
6651
6666
  color: "#363B4C"
6652
6667
  }
6653
6668
  },
6654
- currentFontState.value.fontFamily && currentFontState.value.fontFamily !== "mixed" ? currentFontState.value.fontFamily.split(",")[0].replace(/['"]/g, "") || (ctx ? i18n(ctx, "customMenu.fontDefault") : "\u9ED8\u8BA4") : ctx ? i18n(ctx, "customMenu.fontDefault") : "\u9ED8\u8BA4"
6669
+ (() => {
6670
+ const fontState = currentFontState.value;
6671
+ const fontFamily = fontState == null ? void 0 : fontState.fontFamily;
6672
+ return fontFamily && fontFamily !== "mixed" ? fontFamily.split(",")[0].replace(/['"]/g, "") || (ctx ? i18n(ctx, "customMenu.fontDefault") : "\u9ED8\u8BA4") : ctx ? i18n(ctx, "customMenu.fontDefault") : "\u9ED8\u8BA4";
6673
+ })()
6655
6674
  ),
6656
6675
  /* @__PURE__ */ h(
6657
6676
  "span",
@@ -6681,7 +6700,10 @@ const Toolbar = defineComponent({
6681
6700
  flexShrink: 0
6682
6701
  }
6683
6702
  },
6684
- /* @__PURE__ */ h("span", { style: { fontSize: "13px", color: "#363B4C" } }, currentFontState.value.fontSize && currentFontState.value.fontSize !== "mixed" ? currentFontState.value.fontSize : "16px"),
6703
+ /* @__PURE__ */ h("span", { style: { fontSize: "13px", color: "#363B4C" } }, (() => {
6704
+ const fs = currentFontState.value.fontSize;
6705
+ return fs && fs !== "mixed" ? fs : "16px";
6706
+ })()),
6685
6707
  /* @__PURE__ */ h(
6686
6708
  "span",
6687
6709
  {
@@ -7829,7 +7851,8 @@ const createViewMenuState = () => reactive({
7829
7851
  showTitle: false,
7830
7852
  showCover: false,
7831
7853
  coverUrl: "",
7832
- editorWidth: "default"
7854
+ editorWidth: "default",
7855
+ fixedToolbarVisible: true
7833
7856
  });
7834
7857
  const viewMenuStateCtx = $ctx(createViewMenuState(), "viewMenuStateCtx");
7835
7858
 
@@ -8580,7 +8603,7 @@ const FixedToolbarComponent = defineComponent({
8580
8603
  ctx: { type: Object, required: true },
8581
8604
  hide: { type: Function, required: true },
8582
8605
  show: { type: Object, required: true },
8583
- selection: { type: Object, required: true },
8606
+ state: { type: Object, required: true },
8584
8607
  config: { type: Object, required: false },
8585
8608
  canUndo: { type: Object, required: true },
8586
8609
  canRedo: { type: Object, required: true }
@@ -8601,140 +8624,234 @@ const FixedToolbarComponent = defineComponent({
8601
8624
  });
8602
8625
  });
8603
8626
  return () => {
8604
- var _a, _b, _c, _d;
8605
- props.selection.value;
8606
- const canUndo = (typeof props.canUndo === "boolean" ? props.canUndo : (_a = props.canUndo) == null ? void 0 : _a.value) || false;
8607
- const canRedo = (typeof props.canRedo === "boolean" ? props.canRedo : (_b = props.canRedo) == null ? void 0 : _b.value) || false;
8627
+ var _a, _b, _c, _d, _e;
8628
+ ((_a = props.state) == null ? void 0 : _a.value) || props.state;
8629
+ const canUndo = (typeof props.canUndo === "boolean" ? props.canUndo : (_b = props.canUndo) == null ? void 0 : _b.value) || false;
8630
+ const canRedo = (typeof props.canRedo === "boolean" ? props.canRedo : (_c = props.canRedo) == null ? void 0 : _c.value) || false;
8631
+ const viewState = props.ctx.get(viewMenuStateCtx.key);
8632
+ const maxWidth = editorWidthMap[viewState.editorWidth];
8633
+ const isFull = maxWidth === "none";
8634
+ if (!viewState.fixedToolbarVisible) {
8635
+ return /* @__PURE__ */ h(
8636
+ "button",
8637
+ {
8638
+ type: "button",
8639
+ class: "fixed-toolbar-expand-btn",
8640
+ title: "\u5C55\u5F00\u5DE5\u5177\u680F",
8641
+ onClick: (e) => {
8642
+ e.preventDefault();
8643
+ e.stopPropagation();
8644
+ viewState.fixedToolbarVisible = true;
8645
+ },
8646
+ style: {
8647
+ position: "absolute",
8648
+ top: "0",
8649
+ right: "32px",
8650
+ display: "flex",
8651
+ alignItems: "center",
8652
+ justifyContent: "center",
8653
+ width: "32px",
8654
+ height: "24px",
8655
+ border: "1px solid var(--crepe-color-outline-variant, color-mix(in srgb, var(--crepe-color-outline), transparent 85%))",
8656
+ borderTop: "none",
8657
+ background: "var(--crepe-color-surface, #ffffff)",
8658
+ cursor: "pointer",
8659
+ borderRadius: "0 0 6px 6px",
8660
+ boxShadow: "0 4px 8px rgba(0, 0, 0, 0.06)",
8661
+ color: "var(--crepe-color-on-surface, #363b4c)",
8662
+ pointerEvents: "auto",
8663
+ zIndex: 200
8664
+ }
8665
+ },
8666
+ /* @__PURE__ */ h(
8667
+ "span",
8668
+ {
8669
+ style: { display: "inline-flex", alignItems: "center" },
8670
+ innerHTML: chevronDownIcon
8671
+ }
8672
+ )
8673
+ );
8674
+ }
8608
8675
  return /* @__PURE__ */ h(
8609
8676
  "div",
8610
8677
  {
8611
8678
  style: {
8679
+ position: "relative",
8680
+ width: "100%",
8681
+ height: "100%",
8612
8682
  display: "flex",
8613
8683
  alignItems: "center",
8614
- justifyContent: "center",
8615
- width: "100%",
8616
- gap: "0px",
8617
- minWidth: "0",
8618
- overflow: "hidden"
8684
+ justifyContent: "center"
8619
8685
  }
8620
8686
  },
8621
- ((_c = props.config) == null ? void 0 : _c.showMenuBar) !== false && [
8622
- /* @__PURE__ */ h(MenuBar, { ctx: props.ctx, config: props.config }),
8623
- /* @__PURE__ */ h(
8624
- "div",
8625
- {
8626
- style: {
8627
- width: "1px",
8628
- minWidth: "1px",
8629
- height: "20px",
8630
- backgroundColor: "var(--crepe-color-outline-variant, color-mix(in srgb, var(--crepe-color-outline), transparent 80%))"
8631
- }
8687
+ /* @__PURE__ */ h(
8688
+ "div",
8689
+ {
8690
+ style: {
8691
+ display: "flex",
8692
+ alignItems: "center",
8693
+ justifyContent: "center",
8694
+ width: "100%",
8695
+ maxWidth: isFull ? "100%" : maxWidth,
8696
+ margin: isFull ? "0" : "0 auto",
8697
+ gap: "0px",
8698
+ minWidth: "0",
8699
+ overflow: "hidden"
8632
8700
  }
8633
- )
8634
- ],
8635
- ((_d = props.config) == null ? void 0 : _d.showHistory) !== false && [
8636
- /* @__PURE__ */ h(
8637
- "button",
8638
- {
8639
- type: "button",
8640
- class: ["toolbar-item", !canUndo && "disabled"],
8641
- disabled: !canUndo,
8642
- title: "\u64A4\u9500",
8643
- onPointerdown: (e) => {
8644
- e.preventDefault();
8645
- e.stopPropagation();
8646
- },
8647
- onClick: (e) => {
8648
- e.preventDefault();
8649
- e.stopPropagation();
8650
- if (canUndo) {
8651
- props.ctx.get(commandsCtx).call("Undo");
8652
- }
8653
- },
8654
- style: {
8655
- display: "flex",
8656
- alignItems: "center",
8657
- justifyContent: "center",
8658
- border: "none",
8659
- background: "transparent",
8660
- cursor: canUndo ? "pointer" : "default",
8661
- padding: "6px",
8662
- borderRadius: "4px",
8663
- color: canUndo ? "#363b4c" : "#c0c4cc",
8664
- "--toolbar-icon-color": canUndo ? "#363b4c" : "#c0c4cc"
8665
- }
8666
- },
8701
+ },
8702
+ ((_d = props.config) == null ? void 0 : _d.showMenuBar) !== false && [
8703
+ /* @__PURE__ */ h(MenuBar, { ctx: props.ctx, config: props.config }),
8667
8704
  /* @__PURE__ */ h(
8668
- "span",
8705
+ "div",
8669
8706
  {
8670
- style: { display: "inline-flex", alignItems: "center" },
8671
- innerHTML: undoIcon
8707
+ style: {
8708
+ width: "1px",
8709
+ minWidth: "1px",
8710
+ height: "20px",
8711
+ backgroundColor: "var(--crepe-color-outline-variant, color-mix(in srgb, var(--crepe-color-outline), transparent 80%))"
8712
+ }
8672
8713
  }
8673
8714
  )
8674
- ),
8675
- /* @__PURE__ */ h(
8676
- "button",
8677
- {
8678
- type: "button",
8679
- class: ["toolbar-item", !canRedo && "disabled"],
8680
- disabled: !canRedo,
8681
- title: "\u6062\u590D",
8682
- onPointerdown: (e) => {
8683
- e.preventDefault();
8684
- e.stopPropagation();
8715
+ ],
8716
+ ((_e = props.config) == null ? void 0 : _e.showHistory) !== false && [
8717
+ /* @__PURE__ */ h(
8718
+ "button",
8719
+ {
8720
+ type: "button",
8721
+ class: ["toolbar-item", !canUndo && "disabled"],
8722
+ disabled: !canUndo,
8723
+ title: "\u64A4\u9500",
8724
+ onPointerdown: (e) => {
8725
+ e.preventDefault();
8726
+ e.stopPropagation();
8727
+ },
8728
+ onClick: (e) => {
8729
+ e.preventDefault();
8730
+ e.stopPropagation();
8731
+ if (canUndo) {
8732
+ props.ctx.get(commandsCtx).call("Undo");
8733
+ }
8734
+ },
8735
+ style: {
8736
+ display: "flex",
8737
+ alignItems: "center",
8738
+ justifyContent: "center",
8739
+ border: "none",
8740
+ background: "transparent",
8741
+ cursor: canUndo ? "pointer" : "default",
8742
+ padding: "6px",
8743
+ borderRadius: "4px",
8744
+ color: canUndo ? "#363b4c" : "#c0c4cc",
8745
+ "--toolbar-icon-color": canUndo ? "#363b4c" : "#c0c4cc"
8746
+ }
8685
8747
  },
8686
- onClick: (e) => {
8687
- e.preventDefault();
8688
- e.stopPropagation();
8689
- if (canRedo) {
8690
- props.ctx.get(commandsCtx).call("Redo");
8748
+ /* @__PURE__ */ h(
8749
+ "span",
8750
+ {
8751
+ style: { display: "inline-flex", alignItems: "center" },
8752
+ innerHTML: undoIcon
8753
+ }
8754
+ )
8755
+ ),
8756
+ /* @__PURE__ */ h(
8757
+ "button",
8758
+ {
8759
+ type: "button",
8760
+ class: ["toolbar-item", !canRedo && "disabled"],
8761
+ disabled: !canRedo,
8762
+ title: "\u6062\u590D",
8763
+ onPointerdown: (e) => {
8764
+ e.preventDefault();
8765
+ e.stopPropagation();
8766
+ },
8767
+ onClick: (e) => {
8768
+ e.preventDefault();
8769
+ e.stopPropagation();
8770
+ if (canRedo) {
8771
+ props.ctx.get(commandsCtx).call("Redo");
8772
+ }
8773
+ },
8774
+ style: {
8775
+ display: "flex",
8776
+ alignItems: "center",
8777
+ justifyContent: "center",
8778
+ border: "none",
8779
+ background: "transparent",
8780
+ cursor: canRedo ? "pointer" : "default",
8781
+ padding: "6px",
8782
+ borderRadius: "4px",
8783
+ color: canRedo ? "#363b4c" : "#c0c4cc",
8784
+ "--toolbar-icon-color": canRedo ? "#363b4c" : "#c0c4cc"
8691
8785
  }
8692
8786
  },
8693
- style: {
8694
- display: "flex",
8695
- alignItems: "center",
8696
- justifyContent: "center",
8697
- border: "none",
8698
- background: "transparent",
8699
- cursor: canRedo ? "pointer" : "default",
8700
- padding: "6px",
8701
- borderRadius: "4px",
8702
- color: canRedo ? "#363b4c" : "#c0c4cc",
8703
- "--toolbar-icon-color": canRedo ? "#363b4c" : "#c0c4cc"
8704
- }
8705
- },
8787
+ /* @__PURE__ */ h(
8788
+ "span",
8789
+ {
8790
+ style: { display: "inline-flex", alignItems: "center" },
8791
+ innerHTML: redoIcon
8792
+ }
8793
+ )
8794
+ ),
8706
8795
  /* @__PURE__ */ h(
8707
- "span",
8796
+ "div",
8708
8797
  {
8709
- style: { display: "inline-flex", alignItems: "center" },
8710
- innerHTML: redoIcon
8798
+ style: {
8799
+ width: "1px",
8800
+ minWidth: "1px",
8801
+ height: "20px",
8802
+ backgroundColor: "var(--crepe-color-outline-variant, color-mix(in srgb, var(--crepe-color-outline), transparent 80%))"
8803
+ }
8711
8804
  }
8712
8805
  )
8806
+ ],
8807
+ /* @__PURE__ */ h(
8808
+ Toolbar,
8809
+ {
8810
+ ctx: props.ctx,
8811
+ hide: props.hide,
8812
+ show: props.show,
8813
+ state: props.state,
8814
+ config: props.config,
8815
+ isFixed: true
8816
+ }
8713
8817
  ),
8818
+ showShortcuts.value && /* @__PURE__ */ h(ShortcutHelpModal, { ctx: props.ctx, visible: showShortcuts })
8819
+ ),
8820
+ /* @__PURE__ */ h(
8821
+ "button",
8822
+ {
8823
+ type: "button",
8824
+ class: "toolbar-item collapse-btn",
8825
+ title: "\u6298\u53E0\u5DE5\u5177\u680F",
8826
+ onClick: (e) => {
8827
+ e.preventDefault();
8828
+ e.stopPropagation();
8829
+ viewState.fixedToolbarVisible = false;
8830
+ },
8831
+ style: {
8832
+ position: "absolute",
8833
+ top: "6px",
8834
+ right: "32px",
8835
+ margin: "0",
8836
+ display: "flex",
8837
+ alignItems: "center",
8838
+ justifyContent: "center",
8839
+ pointerEvents: "auto",
8840
+ zIndex: 200
8841
+ }
8842
+ },
8714
8843
  /* @__PURE__ */ h(
8715
- "div",
8844
+ "span",
8716
8845
  {
8717
8846
  style: {
8718
- width: "1px",
8719
- minWidth: "1px",
8720
- height: "20px",
8721
- backgroundColor: "var(--crepe-color-outline-variant, color-mix(in srgb, var(--crepe-color-outline), transparent 80%))"
8722
- }
8847
+ display: "inline-flex",
8848
+ alignItems: "center",
8849
+ transform: "rotate(180deg)"
8850
+ },
8851
+ innerHTML: chevronDownIcon
8723
8852
  }
8724
8853
  )
8725
- ],
8726
- /* @__PURE__ */ h(
8727
- Toolbar,
8728
- {
8729
- ctx: props.ctx,
8730
- hide: props.hide,
8731
- show: props.show,
8732
- selection: props.selection,
8733
- config: props.config,
8734
- isFixed: true
8735
- }
8736
- ),
8737
- showShortcuts.value && /* @__PURE__ */ h(ShortcutHelpModal, { ctx: props.ctx, visible: showShortcuts })
8854
+ )
8738
8855
  );
8739
8856
  };
8740
8857
  }
@@ -10252,7 +10369,7 @@ const OutlinePanel = defineComponent({
10252
10369
  width: `${state.outlineWidth}px`,
10253
10370
  minWidth: "200px",
10254
10371
  maxWidth: "400px",
10255
- backgroundColor: state.documentBackground || "var(--crepe-color-background)",
10372
+ backgroundColor: "transparent",
10256
10373
  borderRight: isLeft ? "1px solid var(--crepe-color-outline-variant, color-mix(in srgb, var(--crepe-color-outline), transparent 80%))" : "none",
10257
10374
  borderLeft: !isLeft ? "1px solid var(--crepe-color-outline-variant, color-mix(in srgb, var(--crepe-color-outline), transparent 80%))" : "none",
10258
10375
  boxSizing: "border-box",
@@ -10453,7 +10570,7 @@ var __accessCheck$4 = (obj, member, msg) => member.has(obj) || __typeError$4("Ca
10453
10570
  var __privateGet$4 = (obj, member, getter) => (__accessCheck$4(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
10454
10571
  var __privateAdd$4 = (obj, member, value) => member.has(obj) ? __typeError$4("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
10455
10572
  var __privateSet$4 = (obj, member, value, setter) => (__accessCheck$4(obj, member, "write to private field"), member.set(obj, value), value);
10456
- var _content$2, _app$2, _headerContent, _headerApp, _outlineContent, _outlineApp, _watcher, _selection$1, _show$1, _canUndo, _canRedo, _resizeObserver$1, _updateOutlineGeometry, _scrollContainers$1, _onDblClick, _view$1, _editorContainer;
10573
+ var _content$2, _app$2, _headerContent, _headerApp, _outlineContent, _outlineApp, _watcher, _state$1, _show$1, _canUndo, _canRedo, _resizeObserver$1, _updateOutlineGeometry, _scrollContainers$1, _onDblClick, _view$1, _editorContainer;
10457
10574
  const fixedToolbarConfig = $ctx(
10458
10575
  {},
10459
10576
  "fixedToolbarConfigCtx"
@@ -10468,7 +10585,7 @@ class FixedToolbarView {
10468
10585
  __privateAdd$4(this, _outlineContent);
10469
10586
  __privateAdd$4(this, _outlineApp);
10470
10587
  __privateAdd$4(this, _watcher);
10471
- __privateAdd$4(this, _selection$1);
10588
+ __privateAdd$4(this, _state$1);
10472
10589
  __privateAdd$4(this, _show$1, ref(true));
10473
10590
  __privateAdd$4(this, _canUndo, ref(false));
10474
10591
  __privateAdd$4(this, _canRedo, ref(false));
@@ -10479,7 +10596,7 @@ class FixedToolbarView {
10479
10596
  __privateAdd$4(this, _view$1);
10480
10597
  __privateAdd$4(this, _editorContainer);
10481
10598
  this.update = (view) => {
10482
- __privateGet$4(this, _selection$1).value = view.state.selection;
10599
+ __privateGet$4(this, _state$1).value = view.state;
10483
10600
  try {
10484
10601
  __privateGet$4(this, _canUndo).value = undo(view.state);
10485
10602
  __privateGet$4(this, _canRedo).value = redo(view.state);
@@ -10523,6 +10640,10 @@ class FixedToolbarView {
10523
10640
  if ((config == null ? void 0 : config.coverUrl) !== void 0) viewState.coverUrl = config.coverUrl;
10524
10641
  if ((config == null ? void 0 : config.editorWidth) !== void 0)
10525
10642
  viewState.editorWidth = config.editorWidth;
10643
+ if ((config == null ? void 0 : config.showFloatingToolbar) !== void 0)
10644
+ viewState.fixedToolbarVisible = config.showFloatingToolbar;
10645
+ if ((config == null ? void 0 : config.fixedToolbarVisible) !== void 0)
10646
+ viewState.fixedToolbarVisible = config.fixedToolbarVisible;
10526
10647
  if (config == null ? void 0 : config.useLocalStorage) {
10527
10648
  try {
10528
10649
  const stored = localStorage.getItem("jvs-milkdown-data");
@@ -10544,6 +10665,10 @@ class FixedToolbarView {
10544
10665
  viewState.coverUrl = parsed.coverUrl;
10545
10666
  if (parsed.editorWidth !== void 0)
10546
10667
  viewState.editorWidth = parsed.editorWidth;
10668
+ if (parsed.showFloatingToolbar !== void 0)
10669
+ viewState.fixedToolbarVisible = parsed.showFloatingToolbar;
10670
+ if (parsed.fixedToolbarVisible !== void 0)
10671
+ viewState.fixedToolbarVisible = parsed.fixedToolbarVisible;
10547
10672
  }
10548
10673
  } catch (e) {
10549
10674
  console.error("Error loading view state from localStorage:", e);
@@ -10566,7 +10691,8 @@ class FixedToolbarView {
10566
10691
  showTitle: newState.showTitle,
10567
10692
  showCover: newState.showCover,
10568
10693
  coverUrl: newState.coverUrl,
10569
- editorWidth: newState.editorWidth
10694
+ editorWidth: newState.editorWidth,
10695
+ fixedToolbarVisible: newState.fixedToolbarVisible
10570
10696
  };
10571
10697
  localStorage.setItem("jvs-milkdown-data", JSON.stringify(merged));
10572
10698
  } catch (e) {
@@ -10578,14 +10704,14 @@ class FixedToolbarView {
10578
10704
  }
10579
10705
  const content = document.createElement("div");
10580
10706
  content.className = "milkdown-fixed-toolbar";
10581
- __privateSet$4(this, _selection$1, shallowRef(view.state.selection));
10707
+ __privateSet$4(this, _state$1, shallowRef(view.state));
10582
10708
  const app = createApp(FixedToolbarComponent, {
10583
10709
  ctx,
10584
10710
  hide: () => {
10585
10711
  },
10586
10712
  // No-op for fixed toolbar
10587
10713
  config,
10588
- selection: __privateGet$4(this, _selection$1),
10714
+ state: __privateGet$4(this, _state$1),
10589
10715
  show: __privateGet$4(this, _show$1),
10590
10716
  canUndo: __privateGet$4(this, _canUndo),
10591
10717
  canRedo: __privateGet$4(this, _canRedo)
@@ -10729,13 +10855,20 @@ class FixedToolbarView {
10729
10855
  viewState2.outlineWidth,
10730
10856
  viewState2.documentBackground,
10731
10857
  viewState2.showCover,
10732
- viewState2.editorWidth
10858
+ viewState2.editorWidth,
10859
+ viewState2.fixedToolbarVisible
10733
10860
  ],
10734
10861
  () => {
10862
+ if (viewState2.fixedToolbarVisible === false) {
10863
+ __privateGet$4(this, _content$2).classList.add("collapsed");
10864
+ } else {
10865
+ __privateGet$4(this, _content$2).classList.remove("collapsed");
10866
+ }
10867
+ root.style.backgroundColor = "";
10735
10868
  if (viewState2.documentBackground) {
10736
- root.style.backgroundColor = viewState2.documentBackground;
10869
+ __privateGet$4(this, _view$1).dom.style.backgroundColor = viewState2.documentBackground;
10737
10870
  } else {
10738
- root.style.backgroundColor = "";
10871
+ __privateGet$4(this, _view$1).dom.style.backgroundColor = "";
10739
10872
  }
10740
10873
  root.style.paddingLeft = "0";
10741
10874
  root.style.paddingRight = "0";
@@ -10758,7 +10891,7 @@ class FixedToolbarView {
10758
10891
  }
10759
10892
  const maxWidth = editorWidthMap[viewState2.editorWidth];
10760
10893
  const isFull = maxWidth === "none";
10761
- const px = isFull ? "80px" : "0";
10894
+ const px = isFull ? "80px" : "10px";
10762
10895
  __privateGet$4(this, _view$1).dom.style.maxWidth = maxWidth;
10763
10896
  __privateGet$4(this, _view$1).dom.style.width = isFull ? "100%" : maxWidth;
10764
10897
  __privateGet$4(this, _view$1).dom.style.margin = isFull ? "0" : "0 auto";
@@ -10788,7 +10921,7 @@ _headerApp = new WeakMap();
10788
10921
  _outlineContent = new WeakMap();
10789
10922
  _outlineApp = new WeakMap();
10790
10923
  _watcher = new WeakMap();
10791
- _selection$1 = new WeakMap();
10924
+ _state$1 = new WeakMap();
10792
10925
  _show$1 = new WeakMap();
10793
10926
  _canUndo = new WeakMap();
10794
10927
  _canRedo = new WeakMap();
@@ -10820,7 +10953,7 @@ const fixedToolbar = (editor, config) => {
10820
10953
  ...prev,
10821
10954
  ...mergedConfig
10822
10955
  }));
10823
- }).use(viewMenuStateCtx).use(fixedToolbarConfig).use(underline).use(highlightMark).use(fixedToolbarPlugin);
10956
+ }).use(viewMenuStateCtx).use(fixedToolbarConfig).use(underline).use(highlightMark).use(colorPlugins).use(fontPlugins).use(fixedToolbarPlugin);
10824
10957
  };
10825
10958
 
10826
10959
  const imageBlock = (editor, config) => {
@@ -12310,21 +12443,21 @@ var __accessCheck$1 = (obj, member, msg) => member.has(obj) || __typeError$1("Ca
12310
12443
  var __privateGet$1 = (obj, member, getter) => (__accessCheck$1(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
12311
12444
  var __privateAdd$1 = (obj, member, value) => member.has(obj) ? __typeError$1("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
12312
12445
  var __privateSet$1 = (obj, member, value, setter) => (__accessCheck$1(obj, member, "write to private field"), member.set(obj, value), value);
12313
- var _tooltipProvider, _content, _app, _selection, _show, _mousePressed, _removePopupListener, _onDocumentMouseUp;
12446
+ var _tooltipProvider, _content, _app, _state, _show, _mousePressed, _removePopupListener, _onDocumentMouseUp;
12314
12447
  const toolbarTooltip = tooltipFactory("CREPE_TOOLBAR");
12315
12448
  class ToolbarView {
12316
12449
  constructor(ctx, view, config) {
12317
12450
  __privateAdd$1(this, _tooltipProvider);
12318
12451
  __privateAdd$1(this, _content);
12319
12452
  __privateAdd$1(this, _app);
12320
- __privateAdd$1(this, _selection);
12453
+ __privateAdd$1(this, _state);
12321
12454
  __privateAdd$1(this, _show, ref(false));
12322
12455
  __privateAdd$1(this, _mousePressed, false);
12323
12456
  __privateAdd$1(this, _removePopupListener);
12324
12457
  __privateAdd$1(this, _onDocumentMouseUp);
12325
12458
  this.update = (view, prevState) => {
12326
12459
  __privateGet$1(this, _tooltipProvider).update(view, prevState);
12327
- __privateGet$1(this, _selection).value = view.state.selection;
12460
+ __privateGet$1(this, _state).value = view.state;
12328
12461
  };
12329
12462
  this.destroy = () => {
12330
12463
  var _a;
@@ -12341,12 +12474,12 @@ class ToolbarView {
12341
12474
  };
12342
12475
  const content = document.createElement("div");
12343
12476
  content.className = "milkdown-toolbar";
12344
- __privateSet$1(this, _selection, shallowRef(view.state.selection));
12477
+ __privateSet$1(this, _state, shallowRef(view.state));
12345
12478
  const app = createApp(Toolbar, {
12346
12479
  ctx,
12347
12480
  hide: this.hide,
12348
12481
  config,
12349
- selection: __privateGet$1(this, _selection),
12482
+ state: __privateGet$1(this, _state),
12350
12483
  show: __privateGet$1(this, _show)
12351
12484
  });
12352
12485
  app.mount(content);
@@ -12410,7 +12543,7 @@ class ToolbarView {
12410
12543
  _tooltipProvider = new WeakMap();
12411
12544
  _content = new WeakMap();
12412
12545
  _app = new WeakMap();
12413
- _selection = new WeakMap();
12546
+ _state = new WeakMap();
12414
12547
  _show = new WeakMap();
12415
12548
  _mousePressed = new WeakMap();
12416
12549
  _removePopupListener = new WeakMap();