autumnnote 1.6.3 → 1.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/autumnnote.es.js +46 -46
- package/dist/autumnnote.es.js.map +1 -1
- package/dist/autumnnote.umd.js +46 -46
- package/dist/autumnnote.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/js/core/detectLang.js +1 -1
- package/src/js/core/dom.js +3 -5
- package/src/js/editing/Style.js +10 -10
- package/src/js/editing/Typing.js +5 -5
- package/src/js/index.js +1 -1
- package/src/js/module/BaseDialog.js +1 -1
- package/src/js/module/BubbleToolbar.js +2 -2
- package/src/js/module/Buttons.js +8 -8
- package/src/js/module/Editor.js +4 -4
- package/src/js/module/IconDialog.js +1 -1
- package/src/js/module/ImageCropOverlay.js +1 -1
- package/src/js/module/ImageResizer.js +1 -1
- package/src/js/module/Mention.js +1 -1
- package/src/js/module/TableTooltip.js +7 -7
- package/src/js/module/Toolbar.js +9 -11
package/dist/autumnnote.umd.js
CHANGED
|
@@ -321,7 +321,7 @@
|
|
|
321
321
|
*/
|
|
322
322
|
function underline() {
|
|
323
323
|
const sel = globalThis.getSelection();
|
|
324
|
-
if (!sel
|
|
324
|
+
if (!sel?.rangeCount) return;
|
|
325
325
|
let container = sel.getRangeAt(0).commonAncestorContainer;
|
|
326
326
|
if (container.nodeType === 3) container = container.parentElement;
|
|
327
327
|
const uEl = container?.closest("u");
|
|
@@ -341,7 +341,7 @@
|
|
|
341
341
|
*/
|
|
342
342
|
function strikethrough() {
|
|
343
343
|
const sel = globalThis.getSelection();
|
|
344
|
-
if (!sel
|
|
344
|
+
if (!sel?.rangeCount) return;
|
|
345
345
|
let sc = sel.getRangeAt(0).startContainer;
|
|
346
346
|
if (sc.nodeType === 3) sc = sc.parentElement;
|
|
347
347
|
const sEl = sc?.closest("s") || sc?.closest("strike");
|
|
@@ -385,7 +385,7 @@
|
|
|
385
385
|
*/
|
|
386
386
|
function fontSize(size, editable = document) {
|
|
387
387
|
const sel = globalThis.getSelection();
|
|
388
|
-
const wasCollapsed = !sel
|
|
388
|
+
const wasCollapsed = !sel?.rangeCount || sel.getRangeAt(0).collapsed;
|
|
389
389
|
if (wasCollapsed && sel && sel.rangeCount > 0) {
|
|
390
390
|
try {
|
|
391
391
|
const range = sel.getRangeAt(0);
|
|
@@ -460,7 +460,7 @@
|
|
|
460
460
|
*/
|
|
461
461
|
function outdent() {
|
|
462
462
|
const sel = globalThis.getSelection();
|
|
463
|
-
if (sel
|
|
463
|
+
if (sel?.rangeCount) {
|
|
464
464
|
let container = sel.getRangeAt(0).commonAncestorContainer;
|
|
465
465
|
if (container.nodeType === 3) container = container.parentElement;
|
|
466
466
|
const checkLi = container?.closest(".an-checklist li");
|
|
@@ -510,7 +510,7 @@
|
|
|
510
510
|
try {
|
|
511
511
|
const nr = document.createRange();
|
|
512
512
|
const firstChild = p.firstChild;
|
|
513
|
-
nr.setStart(firstChild
|
|
513
|
+
nr.setStart(firstChild?.nodeType === 3 ? firstChild : p, 0);
|
|
514
514
|
nr.collapse(true);
|
|
515
515
|
const s = globalThis.getSelection();
|
|
516
516
|
if (s) {
|
|
@@ -589,7 +589,7 @@
|
|
|
589
589
|
*/
|
|
590
590
|
function toggleInlineCode(_editable) {
|
|
591
591
|
const sel = globalThis.getSelection();
|
|
592
|
-
if (!sel
|
|
592
|
+
if (!sel?.rangeCount) return;
|
|
593
593
|
const range = sel.getRangeAt(0);
|
|
594
594
|
let container = range.commonAncestorContainer;
|
|
595
595
|
if (container.nodeType === 3) container = container.parentElement;
|
|
@@ -645,7 +645,7 @@
|
|
|
645
645
|
*/
|
|
646
646
|
function isInlineCode() {
|
|
647
647
|
const sel = globalThis.getSelection();
|
|
648
|
-
if (!sel
|
|
648
|
+
if (!sel?.rangeCount) return false;
|
|
649
649
|
let sc = sel.getRangeAt(0).startContainer;
|
|
650
650
|
if (sc.nodeType === 3) sc = sc.parentElement;
|
|
651
651
|
const code = sc?.closest("code");
|
|
@@ -667,7 +667,7 @@
|
|
|
667
667
|
*/
|
|
668
668
|
function toggleChecklist() {
|
|
669
669
|
const sel = globalThis.getSelection();
|
|
670
|
-
if (!sel
|
|
670
|
+
if (!sel?.rangeCount) return;
|
|
671
671
|
const range = sel.getRangeAt(0);
|
|
672
672
|
let container = range.commonAncestorContainer;
|
|
673
673
|
if (container.nodeType === 3) container = container.parentElement;
|
|
@@ -716,7 +716,7 @@
|
|
|
716
716
|
"LI"
|
|
717
717
|
]);
|
|
718
718
|
let block = container;
|
|
719
|
-
while (block
|
|
719
|
+
while (block?.parentNode && !BLOCK_TAGS.has(block.tagName)) block = block.parentNode;
|
|
720
720
|
const itemText = block && BLOCK_TAGS.has(block.tagName) ? Array.from(block.childNodes).map((n) => n.textContent).join("").replaceAll("\xA0", " ") : "";
|
|
721
721
|
const ul = document.createElement("ul");
|
|
722
722
|
ul.className = "an-checklist";
|
|
@@ -803,7 +803,7 @@
|
|
|
803
803
|
*/
|
|
804
804
|
function isInChecklist() {
|
|
805
805
|
const sel = globalThis.getSelection();
|
|
806
|
-
if (!sel
|
|
806
|
+
if (!sel?.rangeCount) return false;
|
|
807
807
|
let container = sel.getRangeAt(0).commonAncestorContainer;
|
|
808
808
|
if (container.nodeType === 3) container = container.parentElement;
|
|
809
809
|
return !!container?.closest(".an-checklist li");
|
|
@@ -889,10 +889,10 @@
|
|
|
889
889
|
var underlineBtn = btn("underline", "underline", "Underline (Ctrl+U)", () => underline(), () => {
|
|
890
890
|
if (document.queryCommandState("underline")) return true;
|
|
891
891
|
const sel = globalThis.getSelection();
|
|
892
|
-
if (!sel
|
|
892
|
+
if (!sel?.rangeCount) return false;
|
|
893
893
|
let sc = sel.getRangeAt(0).startContainer;
|
|
894
894
|
if (sc.nodeType === 3) sc = sc.parentElement;
|
|
895
|
-
return !!
|
|
895
|
+
return !!sc?.closest("u");
|
|
896
896
|
});
|
|
897
897
|
var strikeBtn = btn("strikethrough", "strikethrough", "Strikethrough", () => strikethrough(), () => document.queryCommandState("strikeThrough"));
|
|
898
898
|
var superscriptBtn = btn("superscript", "superscript", "Superscript", () => superscript(), () => document.queryCommandState("superscript"));
|
|
@@ -952,11 +952,11 @@
|
|
|
952
952
|
getValue: (ctx) => {
|
|
953
953
|
try {
|
|
954
954
|
const sel = globalThis.getSelection();
|
|
955
|
-
if (sel
|
|
955
|
+
if (sel?.rangeCount) {
|
|
956
956
|
let el = sel.getRangeAt(0).startContainer;
|
|
957
|
-
if (el
|
|
958
|
-
while (el
|
|
959
|
-
const size = el
|
|
957
|
+
if (el?.nodeType === 3) el = el.parentElement;
|
|
958
|
+
while (el?.nodeType === 1 && !el.style.fontSize) el = el.parentElement;
|
|
959
|
+
const size = el?.style.fontSize || "";
|
|
960
960
|
if (size) return size;
|
|
961
961
|
}
|
|
962
962
|
const editable = ctx?.layoutInfo?.editable;
|
|
@@ -1057,7 +1057,7 @@
|
|
|
1057
1057
|
getValue: () => {
|
|
1058
1058
|
try {
|
|
1059
1059
|
const sel = globalThis.getSelection();
|
|
1060
|
-
if (!sel
|
|
1060
|
+
if (!sel?.rangeCount) return "";
|
|
1061
1061
|
const BLOCKS = new Set([
|
|
1062
1062
|
"P",
|
|
1063
1063
|
"DIV",
|
|
@@ -1074,7 +1074,7 @@
|
|
|
1074
1074
|
"TH"
|
|
1075
1075
|
]);
|
|
1076
1076
|
let el = sel.getRangeAt(0).startContainer;
|
|
1077
|
-
if (el
|
|
1077
|
+
if (el?.nodeType === 3) el = el.parentElement;
|
|
1078
1078
|
while (el && !BLOCKS.has(
|
|
1079
1079
|
/** @type {Element} */
|
|
1080
1080
|
el.tagName
|
|
@@ -4602,7 +4602,7 @@
|
|
|
4602
4602
|
icon.remove();
|
|
4603
4603
|
textNode.remove();
|
|
4604
4604
|
const nr = document.createRange();
|
|
4605
|
-
if (prevNode
|
|
4605
|
+
if (prevNode?.nodeType === Node.TEXT_NODE) nr.setStart(prevNode, prevNode.textContent.length);
|
|
4606
4606
|
else if (prevNode) nr.setStartAfter(prevNode);
|
|
4607
4607
|
else if (parent) nr.setStart(parent, 0);
|
|
4608
4608
|
nr.collapse(true);
|
|
@@ -4674,7 +4674,7 @@
|
|
|
4674
4674
|
if (isFAIcon(next)) {
|
|
4675
4675
|
const after = next.nextSibling;
|
|
4676
4676
|
event.preventDefault();
|
|
4677
|
-
if (after
|
|
4677
|
+
if (after?.nodeType === Node.TEXT_NODE) {
|
|
4678
4678
|
const offset = (after.textContent || "").startsWith("") ? 1 : 0;
|
|
4679
4679
|
return moveCaret((nr) => nr.setStart(after, Math.min(offset, after.textContent.length)));
|
|
4680
4680
|
}
|
|
@@ -4684,7 +4684,7 @@
|
|
|
4684
4684
|
const icon = next.nextSibling;
|
|
4685
4685
|
const after = icon.nextSibling;
|
|
4686
4686
|
event.preventDefault();
|
|
4687
|
-
if (after
|
|
4687
|
+
if (after?.nodeType === Node.TEXT_NODE) {
|
|
4688
4688
|
const offset = (after.textContent || "").startsWith("") ? 1 : 0;
|
|
4689
4689
|
return moveCaret((nr) => nr.setStart(after, Math.min(offset, after.textContent.length)));
|
|
4690
4690
|
}
|
|
@@ -4786,11 +4786,11 @@
|
|
|
4786
4786
|
newLi.appendChild(cb);
|
|
4787
4787
|
if (afterFrag.textContent.replace(/[\u00a0\u200B]/g, "").length > 0) newLi.appendChild(afterFrag);
|
|
4788
4788
|
let cursorNode = newLi.childNodes[1];
|
|
4789
|
-
if (
|
|
4789
|
+
if (cursorNode?.nodeType !== Node.TEXT_NODE) {
|
|
4790
4790
|
cursorNode = document.createTextNode("");
|
|
4791
4791
|
newLi.appendChild(cursorNode);
|
|
4792
4792
|
}
|
|
4793
|
-
checkLi.
|
|
4793
|
+
checkLi.after(newLi);
|
|
4794
4794
|
const nr = document.createRange();
|
|
4795
4795
|
nr.setStart(cursorNode, 0);
|
|
4796
4796
|
nr.collapse(true);
|
|
@@ -5072,7 +5072,7 @@
|
|
|
5072
5072
|
* @returns {string|null}
|
|
5073
5073
|
*/
|
|
5074
5074
|
function detectLang(code) {
|
|
5075
|
-
if (!code
|
|
5075
|
+
if (!code?.trim()) return null;
|
|
5076
5076
|
const s = code.trim();
|
|
5077
5077
|
if (/(:\s*(string|number|boolean|void|never|any|unknown)\b|interface\s+\w+\s*\{|type\s+\w+\s*[=<(]|<\w+>\s*[;,)]|readonly\s+\w|enum\s+\w+\s*\{|\?\s*:\s*\w|as\s+\w+\s*[;,)\]])/.test(s)) return "typescript";
|
|
5078
5078
|
if (/\bprintln!\s*\(|\bprint!\s*\(|\bfn\s+\w+\s*(<[^>]*>)?\s*\(|\blet\s+mut\s|\bpub\s+fn\s|\buse\s+std::|\bimpl\s+\w+|\bOption<|\bResult<\w+/.test(s)) return "rust";
|
|
@@ -5146,7 +5146,7 @@
|
|
|
5146
5146
|
};
|
|
5147
5147
|
const fixChecklistCursor = (event) => {
|
|
5148
5148
|
const sel = globalThis.getSelection();
|
|
5149
|
-
if (!sel
|
|
5149
|
+
if (!sel?.rangeCount) return;
|
|
5150
5150
|
const r = sel.getRangeAt(0);
|
|
5151
5151
|
if (!r.collapsed) return;
|
|
5152
5152
|
const sc = r.startContainer;
|
|
@@ -5156,7 +5156,7 @@
|
|
|
5156
5156
|
if (!li) return;
|
|
5157
5157
|
const cb = li.querySelector("input[type=\"checkbox\"]");
|
|
5158
5158
|
if (!cb) return;
|
|
5159
|
-
if (event
|
|
5159
|
+
if (event?.type === "mouseup") {
|
|
5160
5160
|
let caret = null;
|
|
5161
5161
|
if (document.caretRangeFromPoint) caret = document.caretRangeFromPoint(event.clientX, event.clientY);
|
|
5162
5162
|
else if (document.caretPositionFromPoint) {
|
|
@@ -5200,7 +5200,7 @@
|
|
|
5200
5200
|
let _compositionSupSub = null;
|
|
5201
5201
|
const onCompositionStart = () => {
|
|
5202
5202
|
const sel = globalThis.getSelection();
|
|
5203
|
-
if (!sel
|
|
5203
|
+
if (!sel?.rangeCount) {
|
|
5204
5204
|
_compositionSupSub = null;
|
|
5205
5205
|
return;
|
|
5206
5206
|
}
|
|
@@ -5218,7 +5218,7 @@
|
|
|
5218
5218
|
_compositionSupSub = null;
|
|
5219
5219
|
if (!tag) return;
|
|
5220
5220
|
const sel = globalThis.getSelection();
|
|
5221
|
-
if (!sel
|
|
5221
|
+
if (!sel?.rangeCount) return;
|
|
5222
5222
|
let node = sel.getRangeAt(0).startContainer;
|
|
5223
5223
|
if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;
|
|
5224
5224
|
const el = node;
|
|
@@ -6012,7 +6012,7 @@
|
|
|
6012
6012
|
let savedRange = null;
|
|
6013
6013
|
const saveSelection = () => {
|
|
6014
6014
|
const sel = globalThis.getSelection();
|
|
6015
|
-
savedRange = sel
|
|
6015
|
+
savedRange = sel?.rangeCount ? sel.getRangeAt(0).cloneRange() : null;
|
|
6016
6016
|
};
|
|
6017
6017
|
const restoreSelection = () => {
|
|
6018
6018
|
if (!savedRange) return;
|
|
@@ -6130,7 +6130,7 @@
|
|
|
6130
6130
|
select.appendChild(placeholder);
|
|
6131
6131
|
items.forEach((item) => {
|
|
6132
6132
|
const value = typeof item === "object" ? item.value : item;
|
|
6133
|
-
const label = typeof item === "object" ? def.name === "paragraphStyle" ?
|
|
6133
|
+
const label = typeof item === "object" ? def.name === "paragraphStyle" ? this.context.locale.toolbar.paragraphItems?.[item.value] || item.label : item.label : item;
|
|
6134
6134
|
const isHeader = typeof item === "object" && !!item.disabled;
|
|
6135
6135
|
const attrs = { value };
|
|
6136
6136
|
if (isHeader) attrs.disabled = "";
|
|
@@ -6142,7 +6142,7 @@
|
|
|
6142
6142
|
let _savedRange = null;
|
|
6143
6143
|
const dMousedown = on(select, "mousedown", () => {
|
|
6144
6144
|
const sel = globalThis.getSelection();
|
|
6145
|
-
_savedRange = sel
|
|
6145
|
+
_savedRange = sel?.rangeCount ? sel.getRangeAt(0).cloneRange() : null;
|
|
6146
6146
|
});
|
|
6147
6147
|
const disposer = on(select, "change", (e) => {
|
|
6148
6148
|
const value = e.target.value;
|
|
@@ -7017,7 +7017,7 @@
|
|
|
7017
7017
|
if (this._dialog) {
|
|
7018
7018
|
this._dialog.style.display = "flex";
|
|
7019
7019
|
this._removeTrap = trapFocus(this._dialog, () => this._close());
|
|
7020
|
-
setTimeout(() => this._firstInput
|
|
7020
|
+
setTimeout(() => this._firstInput?.focus(), 50);
|
|
7021
7021
|
}
|
|
7022
7022
|
}
|
|
7023
7023
|
_close() {
|
|
@@ -7669,7 +7669,7 @@
|
|
|
7669
7669
|
const containerRect = offsetParent.getBoundingClientRect();
|
|
7670
7670
|
const rect = this._activeImg.getBoundingClientRect();
|
|
7671
7671
|
const p = this._lastOverlayPos;
|
|
7672
|
-
if (p
|
|
7672
|
+
if (p?.l === rect.left && p.t === rect.top && p.w === rect.width && p.h === rect.height) return;
|
|
7673
7673
|
this._lastOverlayPos = {
|
|
7674
7674
|
l: rect.left,
|
|
7675
7675
|
t: rect.top,
|
|
@@ -8714,7 +8714,7 @@
|
|
|
8714
8714
|
vIdx += c.colSpan || 1;
|
|
8715
8715
|
if (vIdx > visualIdx) {
|
|
8716
8716
|
const next = c.nextElementSibling;
|
|
8717
|
-
return next
|
|
8717
|
+
return next?.tagName === "TD" || next?.tagName === "TH" ? next : null;
|
|
8718
8718
|
}
|
|
8719
8719
|
}
|
|
8720
8720
|
return null;
|
|
@@ -9004,9 +9004,9 @@
|
|
|
9004
9004
|
this._disposers = [];
|
|
9005
9005
|
if (this._el && this._el.parentNode) this._el.remove();
|
|
9006
9006
|
this._el = null;
|
|
9007
|
-
if (this._sizePopover
|
|
9007
|
+
if (this._sizePopover?.parentNode) this._sizePopover.remove();
|
|
9008
9008
|
this._sizePopover = null;
|
|
9009
|
-
if (this._shadePopover
|
|
9009
|
+
if (this._shadePopover?.parentNode) this._shadePopover.remove();
|
|
9010
9010
|
this._shadePopover = null;
|
|
9011
9011
|
}
|
|
9012
9012
|
_buildTooltip() {
|
|
@@ -9153,7 +9153,7 @@
|
|
|
9153
9153
|
}
|
|
9154
9154
|
_getCell() {
|
|
9155
9155
|
const sel = globalThis.getSelection();
|
|
9156
|
-
if (sel
|
|
9156
|
+
if (sel?.rangeCount) {
|
|
9157
9157
|
let container = sel.getRangeAt(0).commonAncestorContainer;
|
|
9158
9158
|
if (container.nodeType === 3) container = container.parentElement;
|
|
9159
9159
|
const cellFromSel = container?.closest("td, th");
|
|
@@ -9190,7 +9190,7 @@
|
|
|
9190
9190
|
if (!startCell) return [];
|
|
9191
9191
|
if (!endCell || startCell === endCell) return [startCell];
|
|
9192
9192
|
const table = startCell.closest("table");
|
|
9193
|
-
if (!table
|
|
9193
|
+
if (!table?.contains(endCell)) return [startCell];
|
|
9194
9194
|
const { gridMap, cellPos } = buildGridMap(table);
|
|
9195
9195
|
const sp = cellPos.get(startCell);
|
|
9196
9196
|
const ep = cellPos.get(endCell);
|
|
@@ -9270,8 +9270,8 @@
|
|
|
9270
9270
|
for (let i = 0; i < colCount; i++) {
|
|
9271
9271
|
const td = createElement("td", {}, ["\xA0"]);
|
|
9272
9272
|
const ref = refCells[i];
|
|
9273
|
-
if (ref
|
|
9274
|
-
if (ref
|
|
9273
|
+
if (ref?.style.width) td.style.width = ref.style.width;
|
|
9274
|
+
if (ref?.style.minWidth) td.style.minWidth = ref.style.minWidth;
|
|
9275
9275
|
newRow.appendChild(td);
|
|
9276
9276
|
}
|
|
9277
9277
|
if (position === "above") refRow.parentElement?.insertBefore(newRow, refRow);
|
|
@@ -13069,7 +13069,7 @@
|
|
|
13069
13069
|
}
|
|
13070
13070
|
range.insertNode(iconEl);
|
|
13071
13071
|
let caretTextNode = iconEl.nextSibling;
|
|
13072
|
-
if (
|
|
13072
|
+
if (caretTextNode?.nodeType !== Node.TEXT_NODE) {
|
|
13073
13073
|
caretTextNode = document.createTextNode("");
|
|
13074
13074
|
iconEl.parentNode.insertBefore(caretTextNode, iconEl.nextSibling);
|
|
13075
13075
|
} else if (!caretTextNode.textContent) caretTextNode.textContent = "";
|
|
@@ -14592,7 +14592,7 @@
|
|
|
14592
14592
|
const startY = e.clientY;
|
|
14593
14593
|
const orig = { ...this._box };
|
|
14594
14594
|
const r = this._imgRect;
|
|
14595
|
-
const lockAR = this._arCheck
|
|
14595
|
+
const lockAR = this._arCheck?.checked;
|
|
14596
14596
|
const aspect = orig.w / (orig.h || 1);
|
|
14597
14597
|
const onMove = (me) => {
|
|
14598
14598
|
const dx = me.clientX - startX;
|
|
@@ -15418,14 +15418,14 @@
|
|
|
15418
15418
|
if (!this._btnCache) return;
|
|
15419
15419
|
this._btnCache.forEach((btn) => {
|
|
15420
15420
|
const activeFn = _ACTIVE[btn.dataset.name];
|
|
15421
|
-
btn.classList.toggle("an-active", !!
|
|
15421
|
+
btn.classList.toggle("an-active", !!activeFn?.());
|
|
15422
15422
|
});
|
|
15423
15423
|
}
|
|
15424
15424
|
/** Read the current selection's color and update the color-strip indicators. */
|
|
15425
15425
|
_syncColorStrips() {
|
|
15426
15426
|
if (!this._el) return;
|
|
15427
15427
|
const sel = globalThis.getSelection();
|
|
15428
|
-
if (!sel
|
|
15428
|
+
if (!sel?.rangeCount) return;
|
|
15429
15429
|
let node = sel.getRangeAt(0).startContainer;
|
|
15430
15430
|
if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;
|
|
15431
15431
|
if (!node) return;
|
|
@@ -15653,7 +15653,7 @@
|
|
|
15653
15653
|
}
|
|
15654
15654
|
} catch (_) {}
|
|
15655
15655
|
const sel = globalThis.getSelection();
|
|
15656
|
-
if (!sel
|
|
15656
|
+
if (!sel?.rangeCount) return;
|
|
15657
15657
|
const rects = sel.getRangeAt(0).getClientRects();
|
|
15658
15658
|
if (rects.length > 0) this._caretRect = rects[rects.length - 1];
|
|
15659
15659
|
}
|
|
@@ -16277,7 +16277,7 @@
|
|
|
16277
16277
|
return this;
|
|
16278
16278
|
},
|
|
16279
16279
|
/** Library version */
|
|
16280
|
-
version: "1.6.
|
|
16280
|
+
version: "1.6.5"
|
|
16281
16281
|
};
|
|
16282
16282
|
/**
|
|
16283
16283
|
* @param {string|Element|NodeList|Element[]} selector
|