autumnnote 1.8.3 → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/autumnnote.es.js +107 -26
- package/dist/autumnnote.es.js.map +1 -1
- package/dist/autumnnote.umd.js +115 -26
- package/dist/autumnnote.umd.js.map +1 -1
- package/package.json +1 -2
- package/src/js/core/markdown.js +85 -35
- package/src/js/index.js +1 -1
- package/src/js/module/Clipboard.js +25 -0
- package/types/index.d.ts +1 -1
package/dist/autumnnote.umd.js
CHANGED
|
@@ -5309,7 +5309,7 @@
|
|
|
5309
5309
|
* @returns {boolean} `true` if any Markdown-like pattern is present, `false` otherwise.
|
|
5310
5310
|
*/
|
|
5311
5311
|
function isMarkdown(text) {
|
|
5312
|
-
return /^#{1,6} [^\s]|^[ \t]*[-*+] [^\s]|^[ \t]*\d+\. [^\s]|^> [^\s]|^```|^\*{2}[^*\n]+\*{2}/m.test(text);
|
|
5312
|
+
return /^#{1,6} [^\s]|^[ \t]*[-*+] [^\s]|^[ \t]*\d+\. [^\s]|^> [^\s]|^```|^\*{2}[^*\n]+\*{2}/m.test(text) || /^.+\n=+\s*$/m.test(text) || /^.+\n-{2,}\s*$/m.test(text);
|
|
5313
5313
|
}
|
|
5314
5314
|
/**
|
|
5315
5315
|
* Converts a Markdown string to an HTML string.
|
|
@@ -5336,6 +5336,18 @@
|
|
|
5336
5336
|
i++;
|
|
5337
5337
|
continue;
|
|
5338
5338
|
}
|
|
5339
|
+
if (line.trim() && !/^(-{3,}|\*{3,}|_{3,})\s*$/.test(line) && !/^#{1,6} /.test(line) && i + 1 < lines.length) {
|
|
5340
|
+
if (/^=+\s*$/.test(lines[i + 1])) {
|
|
5341
|
+
out.push(`<h1>${_inline(line.trim())}</h1>`);
|
|
5342
|
+
i += 2;
|
|
5343
|
+
continue;
|
|
5344
|
+
}
|
|
5345
|
+
if (/^-{2,}\s*$/.test(lines[i + 1])) {
|
|
5346
|
+
out.push(`<h2>${_inline(line.trim())}</h2>`);
|
|
5347
|
+
i += 2;
|
|
5348
|
+
continue;
|
|
5349
|
+
}
|
|
5350
|
+
}
|
|
5339
5351
|
if (/^(-{3,}|\*{3,}|_{3,})\s*$/.test(line)) {
|
|
5340
5352
|
out.push("<hr>");
|
|
5341
5353
|
i++;
|
|
@@ -5358,30 +5370,15 @@
|
|
|
5358
5370
|
continue;
|
|
5359
5371
|
}
|
|
5360
5372
|
if (/^[-*+] /.test(line)) {
|
|
5361
|
-
const
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
while (i < lines.length && /^[-*+] /.test(lines[i])) {
|
|
5365
|
-
if (/^[-*+]\s+\[[ xX]\]\s+/.test(lines[i]) !== isChecklist) break;
|
|
5366
|
-
const content = lines[i].slice(2);
|
|
5367
|
-
if (isChecklist) {
|
|
5368
|
-
const cbMatch = /^\[([ xX])\][ \t]+/.exec(content);
|
|
5369
|
-
const cbHtml = `<input type="checkbox" contenteditable="false"${cbMatch?.[1]?.toLowerCase() === "x" ? " checked" : ""}>`;
|
|
5370
|
-
const textContent = cbMatch ? content.slice(cbMatch[0].length) : content;
|
|
5371
|
-
items.push(`<li>${cbHtml}${_inline(textContent)}</li>`);
|
|
5372
|
-
} else items.push(`<li>${_inline(content)}</li>`);
|
|
5373
|
-
i++;
|
|
5374
|
-
}
|
|
5375
|
-
out.push(`<${listTag}>${items.join("")}</${listTag.split(" ")[0]}>`);
|
|
5373
|
+
const { html: listHtml, endIdx } = _parseListBlock(lines, i);
|
|
5374
|
+
out.push(listHtml);
|
|
5375
|
+
i = endIdx;
|
|
5376
5376
|
continue;
|
|
5377
5377
|
}
|
|
5378
5378
|
if (/^\d+\. /.test(line)) {
|
|
5379
|
-
const
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
i++;
|
|
5383
|
-
}
|
|
5384
|
-
out.push(`<ol>${items.join("")}</ol>`);
|
|
5379
|
+
const { html: listHtml, endIdx } = _parseListBlock(lines, i);
|
|
5380
|
+
out.push(listHtml);
|
|
5381
|
+
i = endIdx;
|
|
5385
5382
|
continue;
|
|
5386
5383
|
}
|
|
5387
5384
|
if (line.trim() === "") {
|
|
@@ -5390,20 +5387,29 @@
|
|
|
5390
5387
|
}
|
|
5391
5388
|
if (/^\|.+\|/.test(line) && i + 1 < lines.length && /^\|[\s|:-]+\|/.test(lines[i + 1])) {
|
|
5392
5389
|
const headerCells = _parseTableRow(line);
|
|
5390
|
+
const alignments = _parseTableRow(lines[i + 1]).map((c) => {
|
|
5391
|
+
if (c.startsWith(":") && c.endsWith(":")) return "center";
|
|
5392
|
+
if (c.endsWith(":")) return "right";
|
|
5393
|
+
if (c.startsWith(":")) return "left";
|
|
5394
|
+
return null;
|
|
5395
|
+
});
|
|
5393
5396
|
i += 2;
|
|
5394
5397
|
const bodyRows = [];
|
|
5395
5398
|
while (i < lines.length && /^\|.+\|/.test(lines[i])) {
|
|
5396
5399
|
bodyRows.push(_parseTableRow(lines[i]));
|
|
5397
5400
|
i++;
|
|
5398
5401
|
}
|
|
5399
|
-
const
|
|
5400
|
-
|
|
5402
|
+
const _cell = (tag, content, align) => {
|
|
5403
|
+
return `<${tag}${align ? ` style="text-align:${align}"` : ""}>${_inline(content)}</${tag}>`;
|
|
5404
|
+
};
|
|
5405
|
+
const thead = `<thead><tr>${headerCells.map((c, idx) => _cell("th", c, alignments[idx])).join("")}</tr></thead>`;
|
|
5406
|
+
const renderRow = (row) => `<tr>${row.map((c, idx) => _cell("td", c, alignments[idx])).join("")}</tr>`;
|
|
5401
5407
|
const tbody = bodyRows.length ? `<tbody>${bodyRows.map(renderRow).join("")}</tbody>` : "";
|
|
5402
5408
|
out.push(`<table>${thead}${tbody}</table>`);
|
|
5403
5409
|
continue;
|
|
5404
5410
|
}
|
|
5405
5411
|
const paraLines = [];
|
|
5406
|
-
while (i < lines.length && lines[i].trim() !== "" && !/^(#{1,6} |> |[-*+] |\d+\. |```|---\s*$|\*{3}\s*$|_{3}\s*$)/.test(lines[i]) && !/^\|.+\|/.test(lines[i])) {
|
|
5412
|
+
while (i < lines.length && lines[i].trim() !== "" && !/^(#{1,6} |> |[-*+] |\d+\. |```|---\s*$|\*{3}\s*$|_{3}\s*$)/.test(lines[i]) && !/^\|.+\|/.test(lines[i]) && !(i + 1 < lines.length && /^=+\s*$/.test(lines[i + 1])) && !(i + 1 < lines.length && /^-{2,}\s*$/.test(lines[i + 1]))) {
|
|
5407
5413
|
paraLines.push(lines[i]);
|
|
5408
5414
|
i++;
|
|
5409
5415
|
}
|
|
@@ -5420,6 +5426,57 @@
|
|
|
5420
5426
|
function _parseTableRow(row) {
|
|
5421
5427
|
return row.replace(/^\|/, "").replace(/\|$/, "").split("|").map((c) => c.trim());
|
|
5422
5428
|
}
|
|
5429
|
+
function _parseListBlock(lines, startIdx) {
|
|
5430
|
+
const baseIndent = lines[startIdx].match(/^(\s*)/)[1].length;
|
|
5431
|
+
const isOL = /^\s*\d+\. /.test(lines[startIdx]);
|
|
5432
|
+
const items = [];
|
|
5433
|
+
let firstIsCB = null;
|
|
5434
|
+
let i = startIdx;
|
|
5435
|
+
while (i < lines.length) {
|
|
5436
|
+
const line = lines[i];
|
|
5437
|
+
if (line.trim() === "") break;
|
|
5438
|
+
const indent = line.match(/^(\s*)/)[1].length;
|
|
5439
|
+
if (indent < baseIndent) break;
|
|
5440
|
+
if (indent === baseIndent) {
|
|
5441
|
+
if (!/^\s*(?:[-*+]|\d+\.) /.test(line)) break;
|
|
5442
|
+
if (/^\s*\d+\. /.test(line) !== isOL) break;
|
|
5443
|
+
const raw = isOL ? line.replace(/^\s*\d+\. /, "") : line.replace(/^\s*[-*+] /, "");
|
|
5444
|
+
const isCB = !isOL && /^\[[ xX]\]\s+/.test(raw);
|
|
5445
|
+
if (firstIsCB === null) firstIsCB = isCB;
|
|
5446
|
+
if (isCB !== firstIsCB) break;
|
|
5447
|
+
const checked = isCB && raw[1].toLowerCase() === "x";
|
|
5448
|
+
const text = isCB ? raw.replace(/^\[[ xX]\]\s+/, "") : raw;
|
|
5449
|
+
items.push({
|
|
5450
|
+
text,
|
|
5451
|
+
isCB,
|
|
5452
|
+
checked,
|
|
5453
|
+
sub: ""
|
|
5454
|
+
});
|
|
5455
|
+
i++;
|
|
5456
|
+
} else {
|
|
5457
|
+
if (!items.length) {
|
|
5458
|
+
i++;
|
|
5459
|
+
continue;
|
|
5460
|
+
}
|
|
5461
|
+
if (/^\s*(?:[-*+]|\d+\.) /.test(line)) {
|
|
5462
|
+
const nested = _parseListBlock(lines, i);
|
|
5463
|
+
items[items.length - 1].sub += nested.html;
|
|
5464
|
+
i = nested.endIdx;
|
|
5465
|
+
} else {
|
|
5466
|
+
items[items.length - 1].text += " " + line.trim();
|
|
5467
|
+
i++;
|
|
5468
|
+
}
|
|
5469
|
+
}
|
|
5470
|
+
}
|
|
5471
|
+
const open = isOL ? "<ol>" : !isOL && firstIsCB === true ? "<ul class=\"an-checklist\">" : "<ul>";
|
|
5472
|
+
const close = isOL ? "</ol>" : "</ul>";
|
|
5473
|
+
return {
|
|
5474
|
+
html: `${open}${items.map(({ text, isCB, checked, sub }) => {
|
|
5475
|
+
return `<li>${isCB ? `<input type="checkbox" contenteditable="false"${checked ? " checked" : ""}>` : ""}${_inline(text)}${sub}</li>`;
|
|
5476
|
+
}).join("")}${close}`,
|
|
5477
|
+
endIdx: i
|
|
5478
|
+
};
|
|
5479
|
+
}
|
|
5423
5480
|
function _inline(text) {
|
|
5424
5481
|
text = text.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, (_, alt, src) => `<img src="${_escAttr(src)}" alt="${_escAttr(alt)}" class="an-image">`);
|
|
5425
5482
|
text = text.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_, label, href) => `<a href="${_escAttr(href)}">${_esc(label)}</a>`);
|
|
@@ -6971,6 +7028,29 @@
|
|
|
6971
7028
|
return doc.body.innerHTML;
|
|
6972
7029
|
}
|
|
6973
7030
|
/**
|
|
7031
|
+
* Normalizes task lists from external sources (GitHub, GitLab, etc.) so they
|
|
7032
|
+
* pass the sanitiser's `ul.an-checklist` guard. Runs before sanitiseHTML().
|
|
7033
|
+
* @param {string} html
|
|
7034
|
+
* @returns {string}
|
|
7035
|
+
*/
|
|
7036
|
+
_normalizeExternalTaskLists(html) {
|
|
7037
|
+
const doc = new DOMParser().parseFromString(`<body>${html}</body>`, "text/html");
|
|
7038
|
+
for (const cb of doc.querySelectorAll("input[type=\"checkbox\"]")) {
|
|
7039
|
+
const li = cb.closest("li");
|
|
7040
|
+
const ul = li?.closest("ul");
|
|
7041
|
+
if (!li || !ul || ul.classList.contains("an-checklist")) continue;
|
|
7042
|
+
ul.classList.add("an-checklist");
|
|
7043
|
+
cb.removeAttribute("disabled");
|
|
7044
|
+
cb.setAttribute("contenteditable", "false");
|
|
7045
|
+
for (const attr of Array.from(cb.attributes)) if (![
|
|
7046
|
+
"type",
|
|
7047
|
+
"checked",
|
|
7048
|
+
"contenteditable"
|
|
7049
|
+
].includes(attr.name)) cb.removeAttribute(attr.name);
|
|
7050
|
+
}
|
|
7051
|
+
return doc.body.innerHTML;
|
|
7052
|
+
}
|
|
7053
|
+
/**
|
|
6974
7054
|
* Forces the next paste operation to strip all HTML formatting.
|
|
6975
7055
|
* Called by Editor when Ctrl+Shift+V is pressed.
|
|
6976
7056
|
* @param {boolean} val
|
|
@@ -7028,6 +7108,7 @@
|
|
|
7028
7108
|
let html = raw;
|
|
7029
7109
|
if (isWordContent) html = this._cleanWordHtml(html);
|
|
7030
7110
|
else if (isSocialContent) html = this._cleanSocialHtml(html);
|
|
7111
|
+
html = this._normalizeExternalTaskLists(html);
|
|
7031
7112
|
html = sanitiseHTML(html);
|
|
7032
7113
|
if (this.options.pasteStripAttributes) html = this._stripAttributes(html);
|
|
7033
7114
|
execCommand("insertHTML", html);
|
|
@@ -16971,6 +17052,14 @@
|
|
|
16971
17052
|
}
|
|
16972
17053
|
};
|
|
16973
17054
|
//#endregion
|
|
17055
|
+
//#region src/js/core/env.js
|
|
17056
|
+
/**
|
|
17057
|
+
* env.js - Environment / browser detection
|
|
17058
|
+
* Inspired by Summernote's env.js
|
|
17059
|
+
*/
|
|
17060
|
+
var userAgent = navigator.userAgent;
|
|
17061
|
+
/Chrome\//.test(userAgent), /Firefox\//.test(userAgent), /^((?!chrome|android).)*safari/i.test(userAgent), /Edg\//.test(userAgent), /Macintosh/.test(userAgent), /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent), "ontouchstart" in globalThis || navigator.maxTouchPoints, /Macintosh/.test(userAgent);
|
|
17062
|
+
//#endregion
|
|
16974
17063
|
//#region src/js/index.js
|
|
16975
17064
|
var _originalDefaults = { ...defaultOptions };
|
|
16976
17065
|
/** @type {WeakMap<Element, Context>} */
|
|
@@ -17079,7 +17168,7 @@
|
|
|
17079
17168
|
/** All pre-built button definitions — accessible in every module format including UMD/CJS. */
|
|
17080
17169
|
buttons,
|
|
17081
17170
|
/** Library version */
|
|
17082
|
-
version: "1.
|
|
17171
|
+
version: "1.9.1"
|
|
17083
17172
|
};
|
|
17084
17173
|
/**
|
|
17085
17174
|
* @param {string|Element|NodeList|Element[]} selector
|