generated at
scrapbox-line-accessor
行情報を取り出しやすくするScrapbox拡張API
/takker/scrapbox-line-info-2をベースに一部改変している

何やっているのかよくわからない所あったらコメントしてくださいtakker

依存

script.js
import {char as c} from '/api/code/programming-notes/scrapbox-char-accessor/script.js'; import {scrapboxDOM} from '/api/code/programming-notes/scrapbox-dom-accessor/script.js';

本体
classでwrapして、便利な関数を提供するイメージ
URL (Web API)とかと同じ
script.js
class Line { constructor({lineDOM}) { if (!lineDOM?.classList?.contains?.('line') || lineDOM?.tagName !== 'DIV') throw Error(`${lineDOM} is not div.line`); this.lineDOM = lineDOM; }

情報の取得
行番号を取得する
script.js
get index() { return [...scrapboxDOM.lines.children].indexOf(this.DOM); }
行IDを取得する
script.js
get id() { return this.DOM.id; }
行内の文字列を取得する
記法込みの文字列を取得するために、 textContent ではなくscrapbox.Page.linesを用いる
script.js
get text() { return scrapbox.Page.lines[this.index]?.text; }
行のインデントの数を取得する
span.indent-mark span[class^="c-"] の数で判断する
script.js
get indent() { return this.DOM.querySelectorAll('span.indent-mark span[class^="c-"]').length; }
行の折返し数を取得する
あらゆる場合を考慮した/takker/scrapboxの行の折返しの数を取得する方法が見つからないので削除した
文字情報の取得
任意の位置の文字
script.js
char(index) { return c(this.id, index); }
行頭文字/行末文字
script.js
get headChar() { return this.char(0); } get lastChar() { const index = this.text.length - 1; // this.textが空行のときは span.c-0 を取得する return this.char(index < 0 ? 0 : index); }
空白を除いた行頭文字/行末文字
script.js
get headNonBlankChar() { //this._log('enter "headNonBlankCharDOM".'); const text = this.text; if (/^\s+$/.test(text)) return this.lastChar; if (!/^\s+/.test(text)) return this.headChar; const spaceNum = text.match(/^\s+/)?.[0].length; return this.char(spaceNum); } get lastNonBlankChar() { //this._log('enter "lastNonBlankCharDOM".'); const text = this.text; if (/^\s+$/.test(text)) return this.headChar; if (!/\s+$/.test(text)) return this.lastChar; const spaceNum = text.match(/\s+$/)?.[0].length; return this.char(this.text.length - 1 - spaceNum); }
行の取得
前の行
script.js
get prev() { const lineDOM = this.prevDOM; return lineDOM ? new Line({lineDOM}) : undefined; }
次の行
script.js
get next() { const lineDOM = this.nextDOM; return lineDOM ? new Line({lineDOM}) : undefined; }
位置の確認
先頭行かどうか
script.js
get isHead() { return scrapbox.Page.lines[0].id === this.id; }
EOFかどうか
script.js
get isLast() { return scrapbox.Page.lines.pop().id === this.id; }

DOMの取得
現在行
script.js
get DOM() { return this.lineDOM; }
前の行
script.js
get prevDOM() { this.DOM.previousElementSibling ?? undefined; }
次の行
script.js
get nextDOM() { this.DOM.nextElementSibling ?? undefined; }

Debug用
script.js
_log(msg, ...objects){ if (objects.length > 0) { console.log(`[scrapbox-line-info-2] ${msg}`, ...objects); return; } console.log(`[scrapbox-line-info-2] ${msg}`); } }

外部に公開する
以下のいずれかから、行情報を取得するinstanceを生成する
div.line そのもの
内部では div.line を使う
行ID
行番号
内部で何を保持しているか知らなくても、外部から使えるようにする
script.js
export const line = (value) => { // undefinedであればそのまま返す if (value === undefined || value === null) return undefined; let id = undefined; let lineDOM = null; switch(typeof value) { // 行番号が渡されたとき case 'number': id = `L${scrapbox.Page.lines[value]?.id}`; if (id === undefined) { console.error(`${value} is out of range`); return undefined; } // そのまま次のcaseを実行する // 行IDが渡されたとき case 'string': id =id ?? (/^L/.test(value) ? value : `L${value}`); lineDOM = document.getElementById(id); if (!lineDOM) { console.error(`${id} is an invalid line id.`); return undefined; } // そのまま次のcaseを実行する // 行のDOMが渡されたとき default: return new Line({lineDOM: lineDOM ?? value}); } };