generated at
scrapbox-line-accessor
行情報を取り出しやすくするScrapbox拡張API
scrapbox-line-info-2をベースに一部改変している
ここで扱っている行情報クラスをscrapbox line objectと呼ぶことにする

2021-06-08
2021-02-20
02:31:56 /programming-notes/scrapbox-line-accessorの変更を反映した
コードを少し整えた
2021-01-19
13:53:06 インデントブロックの行数を取得する処理を追加した
2021-01-17
12:38:34 折返し取得関数を削除した
12:01:11 行の折返し数の取得計算を間違えていたので直した

依存

script.js
import {char as c} from '/api/code/takker/scrapbox-char-accessor/script.js'; import {scrapboxDOM} from '/api/code/takker/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.lineDOM); }
行IDを取得する
script.js
get id() { return this.lineDOM.id; }
行内の文字列を取得する
記法込みの文字列を取得するために、 textContent ではなくscrapbox.Page.linesを用いる
script.js
get text() { return scrapbox.Page.lines[this.index]?.text; }
行のインデントの数を取得する
span.indent-mark span.char-index の数で判断する
script.js
get indent() { return this.lineDOM.querySelectorAll('span.indent-mark span.char-index').length; }
インデントブロックの行数を取得する
インデントブロックがなかったら 0 になる
script.js
get indentBlockLength() { const presentIndentLevel = this.indent; const lineNo = this.index; const nextTheSameIndentLineNo = scrapbox.Page.lines.findIndex((line, i) => { const indentLevel = line.text.replace(/^(\s*).*$/,'$1').length; return i > lineNo && indentLevel <= presentIndentLevel; }); return nextTheSameIndentLineNo !== -1 ? nextTheSameIndentLineNo - 1 - lineNo : scrapbox.Page.lines.length - 1 - lineNo; // 見つからなければ、最後の行までインデントブロックだと判断する }
行の折返し数を取得する
折返しがなければ0を返す
あらゆる場合を考慮したscrapboxの行の折返しの数を取得する方法が見つからないので削除した
script.js_disabled
get breakNum() { return Math.ceil(this.lineDOM.getBoundingClientRect().height / parseInt(window.getComputedStyle(this.lineDOM).lineHeight)) - 1; }
文字情報の取得
任意の位置の文字
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() { return this.lineDOM.previousElementSibling ?? undefined; }
次の行
script.js
get nextDOM() { return this.lineDOM.nextElementSibling ?? undefined; }

Debug用
script.js
_log(msg, ...objects){ if (typeof msg !== 'object') { console.log(`[scrapbox-line-info-2] ${msg}`, ...objects); return; } console.log(`[scrapbox-line-info-2] `, msg, ...objects); } }

外部に公開する
以下のいずれかから、行情報を取得する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}); } };

#2021-06-08 21:55:24
#2021-02-20 02:31:46
#2021-02-08 08:38:20
#2021-01-21 14:02:08
#2021-01-19 13:53:17
#2021-01-17 10:59:43
#2021-01-16 19:28:05
#2021-01-15 17:57:23