for-custom-new-page
gitに移動したあとのコードで使っている
2023-02-09
06:47:50 切り出したタスクはindentを下げて書き込む
本当はyyyy-MM-ddにぶら下げたいところだけど、makeUpdaterでfrom ...が挿入されるしなあ 共通の処理にするのをやめて、もっと細かくカスタマイズできるようにしようかな
作業ログっぽい見た目にしたい
code:mod.ts
import { getEachLatestDate } from "../getEachLatestDate/mod.ts";
import type {
NewPageHook,
Updater
} from "../custom-new-page/mod.ts";
import { parse, toString, isTask } from "../takker99%2Ftakker-scheduler/deps.ts";
import type { Interval } from "../takker99%2Ftakker-scheduler/deps.ts";
import { getIndentCount, toTitleLc } from "../scrapbox-userscript-std/text.ts";
import { lightFormat } from "../date-fns/mod.ts";
import { parse as parseTaskLink } from "../takker99%2Ftakker-scheduler/workflow.ts";
code:mod.ts
const foodType = {
"あさごはん": "#log-breakfast",
"ひるごはん": "#log-lunch",
"よるごはん": "#log-dinner",
} as Record<string, #${string}>;
/** task lineの配下に書いたものを新しいページに切り出す
*
* 食べたもの記録のときは若干Templateを変える
*/
export const taskLineHook: NewPageHook = (
text, { title, projectTo, mode },
) => {
const parsed = parse(taskLine);
// task lineでない場合は対象外
if (!parsed) return;
// 箇条書きが無い時は何も切り出さない
if (lines.length === 0) return { text, pages: [] };
const { title: taskName, base, record, ...rest } = parsed;
const newTitle = makeTaskTitle(taskName, base, record);
const newTaskLine = toString({
title: [${newTitle}],
base,
record,
...rest,
});
// 余計なインデントを削る
const minIndentNum = Math.min(...lines.map((line) => getIndentCount(line)));
const newLines = [
// タスク名にリンクが入っていたときはそれを使う
// ただし、ページタイトルと同名のときは挿入しない
...(/[\\]/.test(taskName) && taskName !== [${newTitle}] ? taskName : []), ...((title in foodType) ? [
...lines.map(
(line) => line.slice(minIndentNum)
),
"",
'#log-eatenfood'
] : [
...lines.map(
(line) => ${line.slice(minIndentNum)}
),
"",
]
),
];
return {
text: newTaskLine,
pages: [{
project: projectTo,
title: newTitle,
mode,
}],
};
};
taskLineHook.hookName = "task-hook";
切り出したページのタイトル
タスクリンクもしくはyyyy-MM-ddで終わるタイトルの場合はそれをそのまま使う code:mod.ts
const makeTaskTitle = (title: string, base: Date, record: Interval) => {
const date = lightFormat(record.start ?? base, 'yyyy-MM-dd');
if (title in foodType) {
return ${date} ${title};
}
// タスクリンクの場合は、それをそのまま使う
if (parseTaskLink(title.slice(1, -1))) {
return title.slice(1, -1);
}
const first = title.replace(/[\\]/g, '').trim(); return ${first}${first.endsWith(date) ? "" : ${date}};
};
/^takker-/にマッチするprojectでは日付タグを末尾に挿入する 切り出し範囲の行の更新日時を日付タグにして挿入する
code:mod.ts
export const newPageHook: NewPageHook = (
text, { title: titleFrom, projectTo, mode, lines: metaLines },
) => {
// 複数行の切り出しのみ対象
if (lines.length === 0) return;
const title = rawTitle.replace(/[\\]/g, "").trim(); // 余計なインデントを削る
const minIndentNum = Math.min(...lines.map((line) => getIndentCount(line)));
// 行の更新日時と現在日時から日付タグを作る
// "takker"で始まるproject以外ではoffにする
const dates = projectTo.startsWith("takker") ? getEachLatestDate([
new Date(),
...metaLines.map(({ updated }) => new Date(updated * 1000)),
])
.sort((a, b) => b.getTime() - a.getTime())
: [];
const newLines = [
"",
// タイトルにリンクが入っていたときはそれを使う
...lines.map((line) => line.slice(minIndentNum)),
];
return {
text: ${" ".repeat(getIndentCount(rawTitle))}[${title}],
pages: [{
project: projectTo,
title,
lines: makeUpdater(titleFrom, newLines, dates),
mode,
}],
};
};
newPageHook.hookName = "new-page-hook";
code:mod.ts
export const splittedLinkHook: NewPageHook = (
text, { projectTo, mode },
) => {
// リンクを含む単一行のみ対象
if (text.includes("\n") || !/\^\+\]/.test(text)) return;
const indent, str = text.match(/^(\s*)(.*)$/)?.slice?.(1) ?? text;
const linksLcInText = [...str.matchAll(/\[(^\])\]/g)] .map((match) => toTitleLc(match1)); const title = str.replaceAll(""").replaceAll("", "");
return {
text: ${indent}[${title}],
pages: [{
project: projectTo,
title,
lines: (prev, { links }) =>{
// すでに同じリンクが書き込まれているときは何もしない
const linksLc = links.map((link) => toTitleLc(link));
if (linksLcInText.every(
(linkLc) => linksLc.includes(linkLc)
)) return;
return [
...prev.map((line) => line.text),
str,
];
},
mode,
}],
};
};
splittedLinkHook.hookName = "splitted-link-hook";
utilities
以下のルールに沿って書き込む
切り出し先ページに日付タグが挿入されている場合は、その前に切り出した文章を挿入する
切り出し先ページにすでにある日付タグは挿入しない
code:mod.ts
const makeUpdater = (titleFrom: string, lines: Iterable<string>, dates: Date[]): Updater =>
(prev, { links }) => {
const linksLc = links.map((link) => toTitleLc(link));
const fromLine = linksLc.includes(toTitleLc(titleFrom)) ?
[] :
[from [${titleFrom}]];
const dateTags = dates.flatMap(
(date) => {
const yyyyMMdd = lightFormat(date, "yyyy-MM-dd");
if (linksLc.includes(yyyyMMdd)) return [];
const HHmmss = lightFormat(date, "HH:mm:ss");
return [#${yyyyMMdd} ${HHmmss}];
}
);
const prevLines = prev.map((line) => line.text);
/** the index where the first dateTag starts */
const index = prevLines.findIndex(
(line) => /^#\d{4}-\d{2}-\d{2}/.test(line)
);
const insertBefore = index < 0 ? prevLines.length : index;
return [
...prevLines.slice(0, insertBefore),
...fromLine,
...lines,
"",
...dateTags,
...prevLines.slice(insertBefore),
];
};