@8btc/mditor 0.0.24 → 0.0.26

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.
@@ -254591,6 +254591,31 @@
254591
254591
  });
254592
254592
  return md
254593
254593
  }
254594
+
254595
+ function __vditorPreprocessCustomTags(md) {
254596
+ if (!md || typeof md !== "string") return md;
254597
+
254598
+ // 第二步:处理自闭合标签 <tag attr="value" /> → <tag attr="value"></tag>
254599
+ // 匹配所有合法自定义标签(小写字母开头,含字母/数字/短横线)
254600
+ const selfClosingRegex = /<([a-z][a-z0-9-]*)\s+([^>]*?)\s*\/>/gi;
254601
+ md = md.replace(selfClosingRegex, function(match, tagName, attrs) {
254602
+ return `<${tagName} ${attrs}></${tagName}>`;
254603
+ });
254604
+
254605
+ // 第三步:处理纯开标签 <tag attr="value"> → <tag attr="value"></tag>
254606
+ // 精准匹配:非自闭合、无后续闭合标签的合法自定义标签
254607
+ const unclosedTagRegex = /<([a-z][a-z0-9-]*)\s+([^>]*?)>(?<!\/)\s*(?!<\/\1\s*>)/gi;
254608
+ md = md.replace(unclosedTagRegex, function(match, tagName, attrs) {
254609
+ // 兜底过滤:避免已闭合标签被重复处理
254610
+ if (match.includes('/>') || match.endsWith(`></${tagName}>`)) {
254611
+ return match;
254612
+ }
254613
+ return `<${tagName} ${attrs}></${tagName}>`;
254614
+ });
254615
+
254616
+ return md;
254617
+ }
254618
+
254594
254619
  if (typeof window !== "undefined" && window.Lute && typeof window.Lute.New === "function") {
254595
254620
  var __origNew = window.Lute.New;
254596
254621
  window.Lute.New = function() {
@@ -254600,7 +254625,10 @@
254600
254625
  var orig = inst && inst[name];
254601
254626
  if (typeof orig === "function") {
254602
254627
  inst[name] = function(text) {
254603
- return orig.call(inst, __vditorPreprocessBackslashMath(text))
254628
+ text = __vditorPreprocessBackslashMath(text);
254629
+ text = __vditorPreprocessCustomTags(text);
254630
+ console.log(text)
254631
+ return orig.call(inst, text)
254604
254632
  }
254605
254633
  }
254606
254634
  }
package/dist/method.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Vditor v0.0.24 - A markdown editor written in TypeScript.
2
+ * Vditor v0.0.26 - A markdown editor written in TypeScript.
3
3
  *
4
4
  * MIT License
5
5
  *
@@ -45,7 +45,7 @@ return /******/ (() => { // webpackBootstrap
45
45
  /* harmony export */ "g": () => (/* binding */ Constants)
46
46
  /* harmony export */ });
47
47
  /* unused harmony export VDITOR_VERSION */
48
- var _VDITOR_VERSION = (/* unused pure expression or super */ null && ("0.0.24"));
48
+ var _VDITOR_VERSION = (/* unused pure expression or super */ null && ("0.0.26"));
49
49
 
50
50
  var Constants = /** @class */ (function () {
51
51
  function Constants() {
@@ -347,7 +347,7 @@ var Constants = /** @class */ (function () {
347
347
  "c#",
348
348
  "bat",
349
349
  ];
350
- Constants.CDN = "https://webcdn.wujieai.com/vditor@".concat("0.0.24");
350
+ Constants.CDN = "https://webcdn.wujieai.com/vditor@".concat("0.0.26");
351
351
  Constants.MARKDOWN_OPTIONS = {
352
352
  autoSpace: false,
353
353
  gfmAutoLink: true,
@@ -4314,7 +4314,8 @@ var getTopList = function (element) {
4314
4314
  var topUlElement = hasTopClosestByTag(element, "UL");
4315
4315
  var topOlElement = hasTopClosestByTag(element, "OL");
4316
4316
  var topListElement = topUlElement;
4317
- if (topOlElement && (!topUlElement || (topUlElement && topOlElement.contains(topUlElement)))) {
4317
+ if (topOlElement &&
4318
+ (!topUlElement || (topUlElement && topOlElement.contains(topUlElement)))) {
4318
4319
  topListElement = topOlElement;
4319
4320
  }
4320
4321
  return topListElement;
@@ -4454,6 +4455,65 @@ var hasClosestByHeadings = function (element) {
4454
4455
  };
4455
4456
 
4456
4457
 
4458
+ /***/ }),
4459
+
4460
+ /***/ 35:
4461
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
4462
+
4463
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
4464
+ /* harmony export */ "I": () => (/* binding */ bindMathSelectionListener)
4465
+ /* harmony export */ });
4466
+ /* unused harmony export updateMathSelection */
4467
+ /**
4468
+ * 数学公式选中高亮工具
4469
+ * 监听选区变化,为选中的数学公式添加高亮样式
4470
+ */
4471
+ var MATH_SELECTED_CLASS = "vditor-math--selected";
4472
+ /**
4473
+ * 检查并更新数学公式的选中高亮状态
4474
+ * @param container 容器元素(编辑器或预览区域)
4475
+ */
4476
+ var updateMathSelection = function (container) {
4477
+ var selection = window.getSelection();
4478
+ // 获取所有数学公式元素
4479
+ var mathElements = container.querySelectorAll(".language-math");
4480
+ // 移除所有旧的高亮
4481
+ mathElements.forEach(function (el) { return el.classList.remove(MATH_SELECTED_CLASS); });
4482
+ // 无选中内容则返回
4483
+ if (!selection || selection.isCollapsed || selection.rangeCount === 0) {
4484
+ return;
4485
+ }
4486
+ // 检测选中的公式节点并添加高亮
4487
+ mathElements.forEach(function (element) {
4488
+ if (selection.containsNode(element, true)) {
4489
+ element.classList.add(MATH_SELECTED_CLASS);
4490
+ }
4491
+ });
4492
+ };
4493
+ /**
4494
+ * 为容器绑定数学公式选中高亮监听
4495
+ * @param container 容器元素(编辑器或预览区域)
4496
+ */
4497
+ var bindMathSelectionListener = function (container) {
4498
+ var updateHandler = function () { return updateMathSelection(container); };
4499
+ // 监听选区变化
4500
+ document.addEventListener("selectionchange", updateHandler);
4501
+ // 监听鼠标抬起(处理拖拽选择)
4502
+ container.addEventListener("mouseup", updateHandler);
4503
+ // 监听键盘选择(Shift + 方向键)
4504
+ container.addEventListener("keyup", function (e) {
4505
+ if (e.shiftKey && ["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown"].includes(e.key)) {
4506
+ updateHandler();
4507
+ }
4508
+ });
4509
+ // 返回清理函数
4510
+ return function () {
4511
+ document.removeEventListener("selectionchange", updateHandler);
4512
+ container.removeEventListener("mouseup", updateHandler);
4513
+ };
4514
+ };
4515
+
4516
+
4457
4517
  /***/ }),
4458
4518
 
4459
4519
  /***/ 673:
@@ -5074,6 +5134,150 @@ var speechRender = function (element, lang) {
5074
5134
 
5075
5135
  // EXTERNAL MODULE: ./src/ts/markdown/selectionRender.ts
5076
5136
  var selectionRender = __webpack_require__(616);
5137
+ // EXTERNAL MODULE: ./src/ts/util/mathSelection.ts
5138
+ var mathSelection = __webpack_require__(35);
5139
+ ;// CONCATENATED MODULE: ./src/ts/markdown/customRender.ts
5140
+ /**
5141
+ * 自定义组件渲染模块
5142
+ * 支持将 HTML 标签(如 <read-button label="文献解读">)转换为自定义 HTML
5143
+ */
5144
+ var __assign = (undefined && undefined.__assign) || function () {
5145
+ __assign = Object.assign || function(t) {
5146
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5147
+ s = arguments[i];
5148
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
5149
+ t[p] = s[p];
5150
+ }
5151
+ return t;
5152
+ };
5153
+ return __assign.apply(this, arguments);
5154
+ };
5155
+ /**
5156
+ * 解析 HTML 属性字符串
5157
+ * @param str 属性字符串,如 'label="文献解读" id="test"'
5158
+ * @returns 属性对象
5159
+ */
5160
+ function parseAttributes(str) {
5161
+ var attributes = {};
5162
+ if (!str)
5163
+ return attributes;
5164
+ var attrRegex = /(\w+)="([^"]*)"/g;
5165
+ var match;
5166
+ while ((match = attrRegex.exec(str)) !== null) {
5167
+ attributes[match[1]] = match[2];
5168
+ }
5169
+ return attributes;
5170
+ }
5171
+ /**
5172
+ * 从 HTML 字符串中提取自定义标签
5173
+ * @param html HTML 字符串
5174
+ * @param tagName 标签名称,如 'read-button'
5175
+ * @returns 匹配的标签信息数组
5176
+ */
5177
+ function extractCustomTags(html, tagName) {
5178
+ var results = [];
5179
+ // 匹配自闭合标签和非自闭合标签
5180
+ var selfClosingRegex = new RegExp("<".concat(tagName, "\\s+([^>]*)\\s*/>"), "g");
5181
+ var openCloseRegex = new RegExp("<".concat(tagName, "\\s+([^>]*)>([^<]*)</").concat(tagName, ">"), "g");
5182
+ var match;
5183
+ // 处理自闭合标签
5184
+ while ((match = selfClosingRegex.exec(html)) !== null) {
5185
+ results.push({
5186
+ fullTag: match[0],
5187
+ attributes: parseAttributes(match[1]),
5188
+ content: "",
5189
+ });
5190
+ }
5191
+ // 处理开闭合标签
5192
+ while ((match = openCloseRegex.exec(html)) !== null) {
5193
+ results.push({
5194
+ fullTag: match[0],
5195
+ attributes: parseAttributes(match[1]),
5196
+ content: match[2],
5197
+ });
5198
+ }
5199
+ return results;
5200
+ }
5201
+ /**
5202
+ * 使用 HTML 字符串渲染自定义标签
5203
+ * @param html HTML 字符串
5204
+ * @param tagName 标签名称
5205
+ * @param component 自定义组件配置
5206
+ * @returns 修改后的 HTML 字符串
5207
+ */
5208
+ function renderCustomComponentHTML(html, tagName, component) {
5209
+ var tags = extractCustomTags(html, tagName);
5210
+ var result = html;
5211
+ // 反向遍历以保持位置正确性
5212
+ for (var i = tags.length - 1; i >= 0; i--) {
5213
+ var tag = tags[i];
5214
+ var htmlString = component.renderHTML(tag.attributes);
5215
+ result = result.replace(tag.fullTag, htmlString);
5216
+ }
5217
+ return result;
5218
+ }
5219
+ /**
5220
+ * 在 DOM 元素中查找并渲染自定义组件
5221
+ * @param element DOM 元素
5222
+ * @param customComponents 自定义组件集合
5223
+ */
5224
+ function renderCustomComponents(element, customComponents) {
5225
+ Object.keys(customComponents).forEach(function (tagName) {
5226
+ var component = customComponents[tagName];
5227
+ var customElements = element.querySelectorAll(tagName);
5228
+ console.log(element, customComponents, "customComponents");
5229
+ // 反向遍历以避免 DOM 修改时的索引问题
5230
+ Array.from(customElements)
5231
+ .reverse()
5232
+ .forEach(function (el) {
5233
+ var attributes = {};
5234
+ el.getAttributeNames().forEach(function (name) {
5235
+ attributes[name] = el.getAttribute(name) || "";
5236
+ });
5237
+ // 使用 innerHTML 保留内部 HTML 内容,而不仅仅是纯文本
5238
+ var content = el.innerHTML || "";
5239
+ // 使用 HTML 渲染
5240
+ var htmlString = component.renderHTML(__assign(__assign({}, attributes), { children: content }));
5241
+ el.outerHTML = htmlString;
5242
+ });
5243
+ });
5244
+ }
5245
+ /**
5246
+ * 批量处理自定义组件 - 用于预处理 HTML 字符串
5247
+ * @param html HTML 字符串
5248
+ * @param customComponents 自定义组件集合
5249
+ * @returns 处理后的 HTML 字符串
5250
+ */
5251
+ function processCustomComponents(html, customComponents) {
5252
+ var result = html;
5253
+ Object.keys(customComponents).forEach(function (tagName) {
5254
+ var component = customComponents[tagName];
5255
+ result = renderCustomComponentHTML(result, tagName, component);
5256
+ });
5257
+ return result;
5258
+ }
5259
+ /**
5260
+ * 处理 markdown 中的自定义组件
5261
+ * 将 markdown 中的自定义标签转换为对应的 HTML
5262
+ * @param markdown markdown 字符串
5263
+ * @param customComponents 自定义组件集合
5264
+ * @returns 处理后的 markdown 字符串
5265
+ */
5266
+ function processMarkdownCustomComponents(markdown, customComponents) {
5267
+ var result = markdown;
5268
+ Object.keys(customComponents).forEach(function (tagName) {
5269
+ var component = customComponents[tagName];
5270
+ result = renderCustomComponentHTML(result, tagName, component);
5271
+ });
5272
+ return result;
5273
+ }
5274
+ /**
5275
+ * 导出默认函数和其他公共 API
5276
+ */
5277
+ function customRender(element, customComponents) {
5278
+ renderCustomComponents(element, customComponents);
5279
+ }
5280
+
5077
5281
  ;// CONCATENATED MODULE: ./src/ts/markdown/previewRender.ts
5078
5282
  var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
5079
5283
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
@@ -5131,6 +5335,8 @@ var __generator = (undefined && undefined.__generator) || function (thisArg, bod
5131
5335
 
5132
5336
 
5133
5337
 
5338
+
5339
+
5134
5340
 
5135
5341
 
5136
5342
 
@@ -5272,6 +5478,8 @@ var previewRender = function (previewElement, markdown, options) { return __awai
5272
5478
  _a.sent();
5273
5479
  _a.label = 8;
5274
5480
  case 8:
5481
+ console.log(previewElement, "previewElement");
5482
+ customRender(previewElement, mergedOptions.customComponents || {});
5275
5483
  (0,setContentTheme/* setContentTheme */.Z)(mergedOptions.theme.current, mergedOptions.theme.path);
5276
5484
  if (mergedOptions.anchor === 1) {
5277
5485
  previewElement.classList.add("vditor-reset--anchor");
@@ -5307,6 +5515,61 @@ var previewRender = function (previewElement, markdown, options) { return __awai
5307
5515
  if (mergedOptions.lazyLoadImage) {
5308
5516
  lazyLoadImageRender(previewElement);
5309
5517
  }
5518
+ // 绑定数学公式选中高亮监听
5519
+ (0,mathSelection/* bindMathSelectionListener */.I)(previewElement);
5520
+ // 绑定复制事件,处理数学公式源码复制
5521
+ previewElement.addEventListener("copy", function (event) {
5522
+ var selection = window.getSelection();
5523
+ if (!selection || selection.isCollapsed || selection.rangeCount === 0) {
5524
+ return;
5525
+ }
5526
+ var range = selection.getRangeAt(0);
5527
+ // 检查选区是否只包含单个数学公式
5528
+ var mathElement = (0,hasClosest/* hasClosestByClassName */.fb)(range.startContainer, "language-math");
5529
+ var mathEndElement = (0,hasClosest/* hasClosestByClassName */.fb)(range.endContainer, "language-math");
5530
+ // 如果选区的起点和终点都在同一个数学公式元素内,复制源码
5531
+ if (mathElement &&
5532
+ mathEndElement &&
5533
+ mathElement.isSameNode(mathEndElement)) {
5534
+ event.stopPropagation();
5535
+ event.preventDefault();
5536
+ var mathSource = mathElement.getAttribute("data-math") || range.toString();
5537
+ event.clipboardData.setData("text/plain", mathSource);
5538
+ event.clipboardData.setData("text/html", "");
5539
+ return;
5540
+ }
5541
+ // 处理包含多个公式的混合内容
5542
+ var fragment = range.cloneContents();
5543
+ var mathElements = fragment.querySelectorAll(".language-math");
5544
+ if (mathElements.length > 0) {
5545
+ event.stopPropagation();
5546
+ event.preventDefault();
5547
+ // 创建临时容器来处理内容
5548
+ var tempDiv = document.createElement("div");
5549
+ tempDiv.appendChild(fragment);
5550
+ // 替换所有数学公式为源码
5551
+ tempDiv
5552
+ .querySelectorAll(".language-math")
5553
+ .forEach(function (mathEl) {
5554
+ var mathSource = mathEl.getAttribute("data-math");
5555
+ console.log(mathEl.tagName, "mathEl");
5556
+ if (mathSource) {
5557
+ if (mathEl.tagName === "SPAN") {
5558
+ var textNode = document.createTextNode("$".concat(mathSource, "$"));
5559
+ mathEl.parentNode.replaceChild(textNode, mathEl);
5560
+ }
5561
+ else {
5562
+ var textNode = document.createTextNode("$$".concat(mathSource, "$$"));
5563
+ mathEl.parentNode.replaceChild(textNode, mathEl);
5564
+ }
5565
+ }
5566
+ });
5567
+ // 获取纯文本内容
5568
+ var plainText = tempDiv.textContent || tempDiv.innerText || "";
5569
+ event.clipboardData.setData("text/plain", plainText);
5570
+ event.clipboardData.setData("text/html", "");
5571
+ }
5572
+ });
5310
5573
  previewElement.addEventListener("click", function (event) {
5311
5574
  var _a, _b;
5312
5575
  var spanElement = (0,hasClosest/* hasClosestByMatchTag */.lG)(event.target, "SPAN");