scrapbox-access-nodes@0.1.0
分ける必要がなさそう
今までのinterfaceがclass baseで使いづらかったので、function baseに書き直している
いろんなDOM objectやpropertyにアクセスできるようにする
2021-06-20
Interface
引数には色んなものを入れられる
objectへのアクセス
getLineId()
行IDを取得する
script.jsexport function getLineId(value) {
switch(typeof value) {
// 行番号のとき
case 'number':
return scrapbox.Page.lines[value]?.id;
// 行IDのとき
case 'string':
return value.startsWith('L') ? value.slice(1) : value;
// DOMのとき
case 'object': {
if (!(value instanceof HTMLElement)) return undefined;
if (value.classList.contains('line')) return value.id.slice(1); // 行のDOMだったとき
const line = value.closest('.line');
if (line) return line.id; // 行の子要素だったとき
return undefined;
}
default:
return undefined;
}
}
getLineNo()
行番号を取得する
取得できないときは -1
を返す
script.jsexport function getLineNo(value) {
switch(typeof value) {
// 行番号のとき
case 'number':
return value;
// 行ID or DOMのとき
case 'string':
case 'object':
default:
const id = getLineId(value);
return id ? scrapbox.Page.lines.findIndex(line => line.id === id) : -1;
}
}
getLine()
行IDやインデントはここから取得する
script.jsexport function getLine(value) {
switch(typeof value) {
case 'number':
return scrapbox.Page.lines[value];
case 'string':
case 'object':
default:
const id = getLineId(value);
return id ? scrapbox.Page.lines.find(line => line.id === id) : undefined;
}
}
getLineDOM()
行のDOMを取得する
script.jsexport function getLineDOM(value) {
const id = getLineId(value);
return document.getElementById(`L${id}`);
}
getText()
テキストを取得する
script.jsexport function getText(value) {
switch(typeof value) {
case 'number':
case 'string':
// 行として扱う
return getLine(value).text;
case 'object':
if (!(value instanceof HTMLElement)) return undefined;
// 行のDOMだったとき
if (value.classList.contains('line')) return getLine(value).text;
// リンクのDOMだったとき
// []や#つきで返す
if (value.classList.contains('page-link'))
return value.textContent.startsWith('[') || value.textContent.startsWith('#') ?
value.textContent :
`[${value.textContent}]`;
// 文字のDOMだったとき
if (value.classList.contains('char-index')) return value.textContent;
return undefined;
}
}
getLink()
与えられたDOMを含むリンクを取得する
script.jsexport function getLink(charDOM, options) {
const {external = false} = options ?? {};
const selector = external ? '.link' : '.page-link';
return charDOM.closest(selector);
}
getFormula()
与えられたDOMを含む数式を取得する
script.jsexport function getFormula(charDOM) {
return charDOM.closest('.formula');
}
getNextLine()
前の行
script.jsexport function getNextLine(value) {
const index = getLineNo(value);
return scrapbox.Page.lines[index + 1];
}
getPrevLine()
次の行
script.jsexport function getPrevLine(value) {
const index = getLineNo(value);
return scrapbox.Page.lines[index - 1];
}
getHeadLineDOM()
先頭行のDOM
script.jsexport function getHeadLineDOM() {
return document.getElementById(`L${scrapbox.Page.lines[0].id}`);
}
getTailLineDOM()
最後尾の行のDOM
script.jsexport function getTailLineDOM() {
return document.getElementById(`L${scrapbox.Page.lines[scrapbox.Page.lines.length - 1].id}`);
}
getIndentCount()
インデントの数
script.jsexport function getIndentCount(value) {
return getText(value)?.match(/^(\s*)/)?.[1]?.length ?? 0;
}
getIndentLineCount()
その行にぶら下がっている行の数を取得する
script.jsexport function getIndentLineCount(value) {
const index = getLineNo(value);
const base = getIndentCount(index);
let count = 0;
while (getIndentCount(index + count + 1) > base) {
count++;
}
return count;
}
getIndex()
文字のDOMの文字番号を返す
script.jsexport function getIndex(dom) {
if (dom === undefined || dom === null) return;
if (!dom?.classList?.contains?.('char-index')) throw Error('A char DOM is required.');
const index = dom.className.match(/c-(\d+)/)?.[1];
return index ? parseInt(index) : undefined;
}
getHeadCharDOM()
DOM中の最初の文字のDOMを返す
DOMのみ渡せる
script.jsexport function getHeadCharDOM(dom) {
if (dom === undefined || dom === null) return;
if (!(dom instanceof HTMLElement)) throw Error ('The argument must be an instance of HTMLElement');
return dom.getElementsByClassName('char-index')[0];
}
getTailCharDOM()
最後の文字番号を取得する
script.jsexport function getTailCharDOM(dom) {
if (dom === undefined || dom === null) return;
if (!(dom instanceof HTMLElement)) throw Error ('The argument must be an instance of HTMLElement');
return [...dom.getElementsByClassName('char-index')].pop();
}
getCharDOM(line, pos)
2つの変数から文字のDOMを特定する
script.jsexport function getCharDOM(line, pos) {
if (typeof pos !== 'number') throw Error('The index of char must be a number.');
const lineDOM = getLineDOM(line);
return lineDOM?.getElementsByClassName(`c-${pos}`)?.[0];
}
getDOMFromPoint()
座標から文字と行のDOMを取得する
script.jsexport function getDOMFromPoint(x, y) {
const targets = document.elementsFromPoint(x, y);
const char = targets.find(target => target.classList.contains('char-index'));
const line = targets.find(target => target.classList.contains('line'));
return {char, line};
}
nextChar()
前の文字
prevChar()
次の文字
判定
isHeadLine()
先頭行 (=タイトル行)かどうか
isTailLine()
最後尾の行かどうか
isHead(dom, {withoutSpace: false})
先頭の文字かどうか
非空白文字を含むかどうかを選択できる
isTail(dom, {withoutSpace: false})
末尾の文字かどうか
非空白文字を含むかどうかを選択できる
isEmptyChar()
空文字かどうか
別のページに作るやつ
座標から文字を取得する系
getCursorPos()
.cursor
の前後の文字を取得する
getSelection()
.selections
の先頭と末尾に対応する行番号と列番号を取得する