autumnnote 1.8.2 → 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/README.md +11 -5
- package/dist/autumnnote.es.js +117 -28
- package/dist/autumnnote.es.js.map +1 -1
- package/dist/autumnnote.umd.js +117 -28
- package/dist/autumnnote.umd.js.map +1 -1
- package/dist/robots.txt +4 -0
- package/dist/sitemap.xml +18 -0
- package/package.json +6 -2
- package/src/js/core/markdown.js +85 -35
- package/src/js/index.js +1 -1
- package/src/js/module/Clipboard.js +28 -1
- package/src/js/module/ContextMenu.js +1 -1
- package/src/js/module/ImageCropOverlay.js +1 -0
- package/src/js/settings.js +7 -1
- package/types/index.d.ts +4 -2
package/README.md
CHANGED
|
@@ -177,6 +177,9 @@ Official React and Vue 3 wrappers are available as separate packages in this mon
|
|
|
177
177
|
|
|
178
178
|
```bash
|
|
179
179
|
npm install autumnnote autumnnote-react
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
```js
|
|
180
183
|
import 'autumnnote/dist/autumnnote.css';
|
|
181
184
|
```
|
|
182
185
|
|
|
@@ -206,6 +209,9 @@ The `ref` is forwarded to the underlying `Context` instance via `useImperativeHa
|
|
|
206
209
|
|
|
207
210
|
```bash
|
|
208
211
|
npm install autumnnote autumnnote-vue
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
```js
|
|
209
215
|
import 'autumnnote/dist/autumnnote.css';
|
|
210
216
|
```
|
|
211
217
|
|
|
@@ -260,7 +266,6 @@ const editor = AutumnNote.create('#my-editor', {
|
|
|
260
266
|
```js
|
|
261
267
|
const editor = AutumnNote.create('#my-editor', {
|
|
262
268
|
useBootstrap: true,
|
|
263
|
-
bootstrapVersion: 5,
|
|
264
269
|
toolbarButtonClass: 'btn btn-sm btn-light',
|
|
265
270
|
});
|
|
266
271
|
```
|
|
@@ -296,7 +301,7 @@ const editor = AutumnNote.create('#my-editor', {
|
|
|
296
301
|
fd.append('file', files[0]);
|
|
297
302
|
fetch('/api/upload', { method: 'POST', body: fd })
|
|
298
303
|
.then(r => r.json())
|
|
299
|
-
.then(({ url }) => editor.insertImage
|
|
304
|
+
.then(({ url }) => editor.invoke('editor.insertImage', url, files[0].name));
|
|
300
305
|
},
|
|
301
306
|
});
|
|
302
307
|
```
|
|
@@ -462,7 +467,6 @@ See the [full Plugin API docs →](https://autumn.konexforge.com/docs.html#plugi
|
|
|
462
467
|
| `toolbar` | `Array[]` | all buttons | Toolbar layout. See [Toolbar Customisation](#toolbar-customisation). |
|
|
463
468
|
| `toolbarOverflow` | `string` | `'wrap'` | Toolbar overflow strategy: `'wrap'` or `'scroll'`. |
|
|
464
469
|
| `useBootstrap` | `boolean` | `false` | Apply Bootstrap CSS classes to toolbar buttons. |
|
|
465
|
-
| `bootstrapVersion` | `number` | `5` | Bootstrap major version (`4` or `5`). |
|
|
466
470
|
| `toolbarButtonClass` | `string` | `'btn btn-sm btn-light'` | CSS classes for toolbar buttons when `useBootstrap` is `true`. |
|
|
467
471
|
| `useFontAwesome` | `boolean` | `true` | Use FA icons when FontAwesome is detected on the page. |
|
|
468
472
|
| `fontAwesomeClass` | `string` | `'fas'` | FA prefix: `'fas'` for FA 5, `'fa-solid'` for FA 6. |
|
|
@@ -479,7 +483,7 @@ See the [full Plugin API docs →](https://autumn.konexforge.com/docs.html#plugi
|
|
|
479
483
|
| `fontFamilies` | `string[]` | 10 fonts | Font families available in the font-family dropdown. |
|
|
480
484
|
| `stickyToolbar` | `boolean` | `false` | Pin the toolbar to the viewport top when the page is scrolled. |
|
|
481
485
|
| `stickyToolbarOffset` | `number` | `0` | Top offset in pixels for the sticky toolbar (e.g. height of a fixed nav bar). |
|
|
482
|
-
| `theme` | `string` | `'light'` | Colour theme: `'light'` or `'
|
|
486
|
+
| `theme` | `string` | `'light'` | Colour theme: `'light'`, `'dark'`, or `'auto'` (follows system preference). |
|
|
483
487
|
| `readOnly` | `boolean` | `false` | Start the editor in non-editable (read-only) mode with toolbar hidden. |
|
|
484
488
|
| `spellcheck` | `boolean` | `true` | Enable browser spellcheck in the editable area. |
|
|
485
489
|
| `direction` | `string` | `'ltr'` | Text direction: `'ltr'` or `'rtl'`. |
|
|
@@ -495,10 +499,12 @@ See the [full Plugin API docs →](https://autumn.konexforge.com/docs.html#plugi
|
|
|
495
499
|
| `lang` | `string \| object` | `'en'` | UI display language. Built-in codes: `'en'`, `'vi'`, `'ja'`, `'zh'`, `'fr'`, `'de'`, `'es'`, `'ko'`. Pass a partial locale object for custom overrides. |
|
|
496
500
|
| `markdownShortcuts` | `boolean` | `true` | Convert Markdown-style syntax typed in the editor to HTML in real time (block and inline rules). |
|
|
497
501
|
| `bubbleToolbar` | `boolean` | `false` | Show a mini floating toolbar above the text selection for quick formatting. |
|
|
498
|
-
| `bubbleToolbarItems` | `string[]` | `['bold','italic','underline','link','foreColor','removeFormat']` | Buttons shown in the bubble toolbar. Available names: `'bold'`, `'italic'`, `'underline'`, `'strikethrough'`, `'link'`, `'foreColor'`, `'removeFormat'`, `'inlineCode'`. |
|
|
502
|
+
| `bubbleToolbarItems` | `string[]` | `['bold','italic','underline','link','foreColor','hiliteColor','removeFormat']` | Buttons shown in the bubble toolbar. Available names: `'bold'`, `'italic'`, `'underline'`, `'strikethrough'`, `'link'`, `'foreColor'`, `'hiliteColor'`, `'removeFormat'`, `'inlineCode'`. |
|
|
499
503
|
| `autoSaveRestore` | `boolean` | `false` | When `autoSave` is also `true`, show a restore banner on load if a draft exists. |
|
|
500
504
|
| `autoSaveRestoreTimeout` | `number` | `7` | Max draft age in days before it is auto-discarded. `0` = no expiry. |
|
|
501
505
|
| `onAutoSaveRestore` | `Function` | `null` | `(html, context) => void` — called after the user restores a draft. |
|
|
506
|
+
| `maxPasteSize` | `number` | `5242880` | Maximum paste payload size in bytes (default 5 MB). Pastes larger than this are silently dropped. |
|
|
507
|
+
| `minImageSize` | `number` | `20` | Minimum image dimension in px during resize (width and height). |
|
|
502
508
|
| `mention` | `object` | `null` | @mention configuration object. Set `mention.onSearch` to activate. See [Mentions](#mentions). |
|
|
503
509
|
| `onChange` | `Function` | `null` | `(html: string) => void` — called on every content change. |
|
|
504
510
|
| `onFocus` | `Function` | `null` | `(context) => void` — called when the editor gains focus. |
|
package/dist/autumnnote.es.js
CHANGED
|
@@ -1724,6 +1724,8 @@ var defaultOptions = {
|
|
|
1724
1724
|
autoSaveRestoreTimeout: 7,
|
|
1725
1725
|
onAutoSaveRestore: null,
|
|
1726
1726
|
markdownShortcuts: true,
|
|
1727
|
+
maxPasteSize: 5 * 1024 * 1024,
|
|
1728
|
+
minImageSize: 20,
|
|
1727
1729
|
bubbleToolbar: false,
|
|
1728
1730
|
bubbleToolbarItems: [
|
|
1729
1731
|
"bold",
|
|
@@ -5594,7 +5596,7 @@ function _domToMd(node, depth = 0) {
|
|
|
5594
5596
|
* @returns {boolean} `true` if any Markdown-like pattern is present, `false` otherwise.
|
|
5595
5597
|
*/
|
|
5596
5598
|
function isMarkdown(text) {
|
|
5597
|
-
return /^#{1,6} [^\s]|^[ \t]*[-*+] [^\s]|^[ \t]*\d+\. [^\s]|^> [^\s]|^```|^\*{2}[^*\n]+\*{2}/m.test(text);
|
|
5599
|
+
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);
|
|
5598
5600
|
}
|
|
5599
5601
|
/**
|
|
5600
5602
|
* Converts a Markdown string to an HTML string.
|
|
@@ -5621,6 +5623,18 @@ function markdownToHTML(text) {
|
|
|
5621
5623
|
i++;
|
|
5622
5624
|
continue;
|
|
5623
5625
|
}
|
|
5626
|
+
if (line.trim() && !/^(-{3,}|\*{3,}|_{3,})\s*$/.test(line) && !/^#{1,6} /.test(line) && i + 1 < lines.length) {
|
|
5627
|
+
if (/^=+\s*$/.test(lines[i + 1])) {
|
|
5628
|
+
out.push(`<h1>${_inline(line.trim())}</h1>`);
|
|
5629
|
+
i += 2;
|
|
5630
|
+
continue;
|
|
5631
|
+
}
|
|
5632
|
+
if (/^-{2,}\s*$/.test(lines[i + 1])) {
|
|
5633
|
+
out.push(`<h2>${_inline(line.trim())}</h2>`);
|
|
5634
|
+
i += 2;
|
|
5635
|
+
continue;
|
|
5636
|
+
}
|
|
5637
|
+
}
|
|
5624
5638
|
if (/^(-{3,}|\*{3,}|_{3,})\s*$/.test(line)) {
|
|
5625
5639
|
out.push("<hr>");
|
|
5626
5640
|
i++;
|
|
@@ -5643,30 +5657,15 @@ function markdownToHTML(text) {
|
|
|
5643
5657
|
continue;
|
|
5644
5658
|
}
|
|
5645
5659
|
if (/^[-*+] /.test(line)) {
|
|
5646
|
-
const
|
|
5647
|
-
|
|
5648
|
-
|
|
5649
|
-
while (i < lines.length && /^[-*+] /.test(lines[i])) {
|
|
5650
|
-
if (/^[-*+]\s+\[[ xX]\]\s+/.test(lines[i]) !== isChecklist) break;
|
|
5651
|
-
const content = lines[i].slice(2);
|
|
5652
|
-
if (isChecklist) {
|
|
5653
|
-
const cbMatch = /^\[([ xX])\][ \t]+/.exec(content);
|
|
5654
|
-
const cbHtml = `<input type="checkbox" contenteditable="false"${cbMatch?.[1]?.toLowerCase() === "x" ? " checked" : ""}>`;
|
|
5655
|
-
const textContent = cbMatch ? content.slice(cbMatch[0].length) : content;
|
|
5656
|
-
items.push(`<li>${cbHtml}${_inline(textContent)}</li>`);
|
|
5657
|
-
} else items.push(`<li>${_inline(content)}</li>`);
|
|
5658
|
-
i++;
|
|
5659
|
-
}
|
|
5660
|
-
out.push(`<${listTag}>${items.join("")}</${listTag.split(" ")[0]}>`);
|
|
5660
|
+
const { html: listHtml, endIdx } = _parseListBlock(lines, i);
|
|
5661
|
+
out.push(listHtml);
|
|
5662
|
+
i = endIdx;
|
|
5661
5663
|
continue;
|
|
5662
5664
|
}
|
|
5663
5665
|
if (/^\d+\. /.test(line)) {
|
|
5664
|
-
const
|
|
5665
|
-
|
|
5666
|
-
|
|
5667
|
-
i++;
|
|
5668
|
-
}
|
|
5669
|
-
out.push(`<ol>${items.join("")}</ol>`);
|
|
5666
|
+
const { html: listHtml, endIdx } = _parseListBlock(lines, i);
|
|
5667
|
+
out.push(listHtml);
|
|
5668
|
+
i = endIdx;
|
|
5670
5669
|
continue;
|
|
5671
5670
|
}
|
|
5672
5671
|
if (line.trim() === "") {
|
|
@@ -5675,20 +5674,29 @@ function markdownToHTML(text) {
|
|
|
5675
5674
|
}
|
|
5676
5675
|
if (/^\|.+\|/.test(line) && i + 1 < lines.length && /^\|[\s|:-]+\|/.test(lines[i + 1])) {
|
|
5677
5676
|
const headerCells = _parseTableRow(line);
|
|
5677
|
+
const alignments = _parseTableRow(lines[i + 1]).map((c) => {
|
|
5678
|
+
if (c.startsWith(":") && c.endsWith(":")) return "center";
|
|
5679
|
+
if (c.endsWith(":")) return "right";
|
|
5680
|
+
if (c.startsWith(":")) return "left";
|
|
5681
|
+
return null;
|
|
5682
|
+
});
|
|
5678
5683
|
i += 2;
|
|
5679
5684
|
const bodyRows = [];
|
|
5680
5685
|
while (i < lines.length && /^\|.+\|/.test(lines[i])) {
|
|
5681
5686
|
bodyRows.push(_parseTableRow(lines[i]));
|
|
5682
5687
|
i++;
|
|
5683
5688
|
}
|
|
5684
|
-
const
|
|
5685
|
-
|
|
5689
|
+
const _cell = (tag, content, align) => {
|
|
5690
|
+
return `<${tag}${align ? ` style="text-align:${align}"` : ""}>${_inline(content)}</${tag}>`;
|
|
5691
|
+
};
|
|
5692
|
+
const thead = `<thead><tr>${headerCells.map((c, idx) => _cell("th", c, alignments[idx])).join("")}</tr></thead>`;
|
|
5693
|
+
const renderRow = (row) => `<tr>${row.map((c, idx) => _cell("td", c, alignments[idx])).join("")}</tr>`;
|
|
5686
5694
|
const tbody = bodyRows.length ? `<tbody>${bodyRows.map(renderRow).join("")}</tbody>` : "";
|
|
5687
5695
|
out.push(`<table>${thead}${tbody}</table>`);
|
|
5688
5696
|
continue;
|
|
5689
5697
|
}
|
|
5690
5698
|
const paraLines = [];
|
|
5691
|
-
while (i < lines.length && lines[i].trim() !== "" && !/^(#{1,6} |> |[-*+] |\d+\. |```|---\s*$|\*{3}\s*$|_{3}\s*$)/.test(lines[i]) && !/^\|.+\|/.test(lines[i])) {
|
|
5699
|
+
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]))) {
|
|
5692
5700
|
paraLines.push(lines[i]);
|
|
5693
5701
|
i++;
|
|
5694
5702
|
}
|
|
@@ -5705,6 +5713,57 @@ function markdownToHTML(text) {
|
|
|
5705
5713
|
function _parseTableRow(row) {
|
|
5706
5714
|
return row.replace(/^\|/, "").replace(/\|$/, "").split("|").map((c) => c.trim());
|
|
5707
5715
|
}
|
|
5716
|
+
function _parseListBlock(lines, startIdx) {
|
|
5717
|
+
const baseIndent = lines[startIdx].match(/^(\s*)/)[1].length;
|
|
5718
|
+
const isOL = /^\s*\d+\. /.test(lines[startIdx]);
|
|
5719
|
+
const items = [];
|
|
5720
|
+
let firstIsCB = null;
|
|
5721
|
+
let i = startIdx;
|
|
5722
|
+
while (i < lines.length) {
|
|
5723
|
+
const line = lines[i];
|
|
5724
|
+
if (line.trim() === "") break;
|
|
5725
|
+
const indent = line.match(/^(\s*)/)[1].length;
|
|
5726
|
+
if (indent < baseIndent) break;
|
|
5727
|
+
if (indent === baseIndent) {
|
|
5728
|
+
if (!/^\s*(?:[-*+]|\d+\.) /.test(line)) break;
|
|
5729
|
+
if (/^\s*\d+\. /.test(line) !== isOL) break;
|
|
5730
|
+
const raw = isOL ? line.replace(/^\s*\d+\. /, "") : line.replace(/^\s*[-*+] /, "");
|
|
5731
|
+
const isCB = !isOL && /^\[[ xX]\]\s+/.test(raw);
|
|
5732
|
+
if (firstIsCB === null) firstIsCB = isCB;
|
|
5733
|
+
if (isCB !== firstIsCB) break;
|
|
5734
|
+
const checked = isCB && raw[1].toLowerCase() === "x";
|
|
5735
|
+
const text = isCB ? raw.replace(/^\[[ xX]\]\s+/, "") : raw;
|
|
5736
|
+
items.push({
|
|
5737
|
+
text,
|
|
5738
|
+
isCB,
|
|
5739
|
+
checked,
|
|
5740
|
+
sub: ""
|
|
5741
|
+
});
|
|
5742
|
+
i++;
|
|
5743
|
+
} else {
|
|
5744
|
+
if (!items.length) {
|
|
5745
|
+
i++;
|
|
5746
|
+
continue;
|
|
5747
|
+
}
|
|
5748
|
+
if (/^\s*(?:[-*+]|\d+\.) /.test(line)) {
|
|
5749
|
+
const nested = _parseListBlock(lines, i);
|
|
5750
|
+
items[items.length - 1].sub += nested.html;
|
|
5751
|
+
i = nested.endIdx;
|
|
5752
|
+
} else {
|
|
5753
|
+
items[items.length - 1].text += " " + line.trim();
|
|
5754
|
+
i++;
|
|
5755
|
+
}
|
|
5756
|
+
}
|
|
5757
|
+
}
|
|
5758
|
+
const open = isOL ? "<ol>" : !isOL && firstIsCB === true ? "<ul class=\"an-checklist\">" : "<ul>";
|
|
5759
|
+
const close = isOL ? "</ol>" : "</ul>";
|
|
5760
|
+
return {
|
|
5761
|
+
html: `${open}${items.map(({ text, isCB, checked, sub }) => {
|
|
5762
|
+
return `<li>${isCB ? `<input type="checkbox" contenteditable="false"${checked ? " checked" : ""}>` : ""}${_inline(text)}${sub}</li>`;
|
|
5763
|
+
}).join("")}${close}`,
|
|
5764
|
+
endIdx: i
|
|
5765
|
+
};
|
|
5766
|
+
}
|
|
5708
5767
|
function _inline(text) {
|
|
5709
5768
|
text = text.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, (_, alt, src) => `<img src="${_escAttr(src)}" alt="${_escAttr(alt)}" class="an-image">`);
|
|
5710
5769
|
text = text.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_, label, href) => `<a href="${_escAttr(href)}">${_esc(label)}</a>`);
|
|
@@ -7256,6 +7315,29 @@ var Clipboard = class {
|
|
|
7256
7315
|
return doc.body.innerHTML;
|
|
7257
7316
|
}
|
|
7258
7317
|
/**
|
|
7318
|
+
* Normalizes task lists from external sources (GitHub, GitLab, etc.) so they
|
|
7319
|
+
* pass the sanitiser's `ul.an-checklist` guard. Runs before sanitiseHTML().
|
|
7320
|
+
* @param {string} html
|
|
7321
|
+
* @returns {string}
|
|
7322
|
+
*/
|
|
7323
|
+
_normalizeExternalTaskLists(html) {
|
|
7324
|
+
const doc = new DOMParser().parseFromString(`<body>${html}</body>`, "text/html");
|
|
7325
|
+
for (const cb of doc.querySelectorAll("input[type=\"checkbox\"]")) {
|
|
7326
|
+
const li = cb.closest("li");
|
|
7327
|
+
const ul = li?.closest("ul");
|
|
7328
|
+
if (!li || !ul || ul.classList.contains("an-checklist")) continue;
|
|
7329
|
+
ul.classList.add("an-checklist");
|
|
7330
|
+
cb.removeAttribute("disabled");
|
|
7331
|
+
cb.setAttribute("contenteditable", "false");
|
|
7332
|
+
for (const attr of Array.from(cb.attributes)) if (![
|
|
7333
|
+
"type",
|
|
7334
|
+
"checked",
|
|
7335
|
+
"contenteditable"
|
|
7336
|
+
].includes(attr.name)) cb.removeAttribute(attr.name);
|
|
7337
|
+
}
|
|
7338
|
+
return doc.body.innerHTML;
|
|
7339
|
+
}
|
|
7340
|
+
/**
|
|
7259
7341
|
* Forces the next paste operation to strip all HTML formatting.
|
|
7260
7342
|
* Called by Editor when Ctrl+Shift+V is pressed.
|
|
7261
7343
|
* @param {boolean} val
|
|
@@ -7313,6 +7395,7 @@ var Clipboard = class {
|
|
|
7313
7395
|
let html = raw;
|
|
7314
7396
|
if (isWordContent) html = this._cleanWordHtml(html);
|
|
7315
7397
|
else if (isSocialContent) html = this._cleanSocialHtml(html);
|
|
7398
|
+
html = this._normalizeExternalTaskLists(html);
|
|
7316
7399
|
html = sanitiseHTML(html);
|
|
7317
7400
|
if (this.options.pasteStripAttributes) html = this._stripAttributes(html);
|
|
7318
7401
|
execCommand("insertHTML", html);
|
|
@@ -7427,7 +7510,7 @@ var Clipboard = class {
|
|
|
7427
7510
|
_compressImage(file) {
|
|
7428
7511
|
const MAX_DIM = 1920;
|
|
7429
7512
|
const QUALITY = .85;
|
|
7430
|
-
return new Promise((resolve) => {
|
|
7513
|
+
return new Promise((resolve, reject) => {
|
|
7431
7514
|
const objectUrl = URL.createObjectURL(file);
|
|
7432
7515
|
const img = new Image();
|
|
7433
7516
|
img.onload = () => {
|
|
@@ -7447,6 +7530,7 @@ var Clipboard = class {
|
|
|
7447
7530
|
if (!ctx) {
|
|
7448
7531
|
const reader = new FileReader();
|
|
7449
7532
|
reader.onload = (e) => resolve(e.target.result);
|
|
7533
|
+
reader.onerror = () => reject(/* @__PURE__ */ new Error("FileReader failed"));
|
|
7450
7534
|
reader.readAsDataURL(file);
|
|
7451
7535
|
return;
|
|
7452
7536
|
}
|
|
@@ -7458,6 +7542,7 @@ var Clipboard = class {
|
|
|
7458
7542
|
URL.revokeObjectURL(objectUrl);
|
|
7459
7543
|
const reader = new FileReader();
|
|
7460
7544
|
reader.onload = (e) => resolve(e.target.result);
|
|
7545
|
+
reader.onerror = () => reject(/* @__PURE__ */ new Error("FileReader failed"));
|
|
7461
7546
|
reader.readAsDataURL(file);
|
|
7462
7547
|
};
|
|
7463
7548
|
img.src = objectUrl;
|
|
@@ -14179,7 +14264,7 @@ var defaultItems = [
|
|
|
14179
14264
|
};
|
|
14180
14265
|
if (typeof navigator.clipboard.read === "function") navigator.clipboard.read().then((items) => {
|
|
14181
14266
|
for (const item of items) if (item.types.includes("text/html")) {
|
|
14182
|
-
item.getType("text/html").then((blob) => blob.text()).then((html) => doInsert(html, null));
|
|
14267
|
+
item.getType("text/html").then((blob) => blob.text()).then((html) => doInsert(html, null)).catch(() => {});
|
|
14183
14268
|
return;
|
|
14184
14269
|
}
|
|
14185
14270
|
navigator.clipboard.readText().then((text) => doInsert(null, text)).catch(() => {});
|
|
@@ -15304,6 +15389,10 @@ function drawCropToCanvas(img, naturalRect, renderW, renderH) {
|
|
|
15304
15389
|
canvas.width = Math.round(renderW);
|
|
15305
15390
|
canvas.height = Math.round(renderH);
|
|
15306
15391
|
const ctx = canvas.getContext("2d");
|
|
15392
|
+
if (!ctx) {
|
|
15393
|
+
resolve(null);
|
|
15394
|
+
return;
|
|
15395
|
+
}
|
|
15307
15396
|
try {
|
|
15308
15397
|
ctx.drawImage(source, naturalRect.x, naturalRect.y, naturalRect.width, naturalRect.height, 0, 0, canvas.width, canvas.height);
|
|
15309
15398
|
ctx.getImageData(0, 0, 1, 1);
|
|
@@ -17492,7 +17581,7 @@ var AutumnNote = {
|
|
|
17492
17581
|
/** All pre-built button definitions — accessible in every module format including UMD/CJS. */
|
|
17493
17582
|
buttons,
|
|
17494
17583
|
/** Library version */
|
|
17495
|
-
version: "1.
|
|
17584
|
+
version: "1.9.1"
|
|
17496
17585
|
};
|
|
17497
17586
|
/**
|
|
17498
17587
|
* @param {string|Element|NodeList|Element[]} selector
|