Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,23 @@
This extension supports the following configuration options, to be specified in the `TODO Triggers Home` settings panel within Roam Depot:

- `Append Text` - (Optional) The text to add to the end of a block when an item flips from TODO to DONE. It supports the following place holders:
- `/Current Time` - inserts the current time

- `/Current Time` - inserts the current time
- `/Today` **(deprecated)** - inserts the current day

- `/Today` **(deprecated)** - inserts the the current day

- `{now}`- inserts the current day. Use `{now:skip dnp}` to skip adding the current day when the TODO is on a daily note page.
- `{now}`- inserts the current day. Use `{now:skip dnp}` to skip adding the current day when the TODO is on a daily note page.

- `On Todo` - (Optional) The text to add to the end of a block, when a block first becomes a TODO. It supports the following place holders:
- `/Current Time` - inserts the current time

- `/Current Time` - inserts the current time

- `/Today` **(deprecated)** - inserts the the current day
- `/Today` **(deprecated)** - inserts the current day

- `{now}`- inserts the current day. Use `{now:skip dnp}` to skip adding the current day when the TODO is on a daily note page.
- `{now}`- inserts the current day. Use `{now:skip dnp}` to skip adding the current day when the TODO is on a daily note page.

- `Replace Tags` - (Optional) The set of pairs that you would want to be replaced upon switching between todo and done. Multiple pairs are deliminited by `|` and each pair is delimited by `,`. For example, `Replace Tags:: #toRead, #Read | #toWrite, #Written`
- There are a couple of placeholders this option supports. `{date}` maps to any date tag and `{today}` maps to today. So you could configure `Replace Tags:: {date}, {today}` to replace a date tag with today's date.

- There are a couple of placeholders this option supports. `{date}` maps to any date tag and `{today}` maps to today. So you could configure `Replace Tags:: {date}, {today}` to replace a date tag with today's date.
- `Ignore Tags` - (Optional) Comma- or pipe-separated list of tags that should skip TODO/DONE triggers for the block (for example, `#no-trigger, #skip`).

- `Strikethrough` - (Optional) Set to `True` to strikethrough blocks with `{{[[DONE]]}}`.

Expand Down
94 changes: 70 additions & 24 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ export default runExtension(async ({ extensionAPI }) => {
"The set of pairs that you would want to be replaced upon switching between todo and done",
action: { type: "input", placeholder: "#toRead, #Read" },
},
{
id: "ignore-tags",
name: "Ignore Tags",
description:
"Comma- or pipe-separated list of tags that should skip TODO/DONE triggers",
action: { type: "input", placeholder: "#no-trigger, #skip" },
},
{
id: "strikethrough",
name: "Strikethrough",
Expand Down Expand Up @@ -101,7 +108,24 @@ export default runExtension(async ({ extensionAPI }) => {
"roam-block",
];

const shouldIgnoreBlock = (value: string) => {
const ignoreTags = extensionAPI.settings.get("ignore-tags") as string;
if (!ignoreTags) {
return false;
}
return ignoreTags
.split(/[,|]/)
.map((tag) =>
tag.trim().replace(/^#/, "").replace(/^\[\[/, "").replace(/\]\]$/, ""),
)
.filter((tag) => !!tag)
.some((tag) => createTagRegex(tag).test(value));
};

const onTodo = (blockUid: string, oldValue: string) => {
if (shouldIgnoreBlock(oldValue)) {
return;
}
const text = extensionAPI.settings.get("append-text") as string;
let value = oldValue;
if (text) {
Expand All @@ -117,7 +141,7 @@ export default runExtension(async ({ extensionAPI }) => {
.replace("/Today", `\\[\\[${DAILY_NOTE_PAGE_REGEX.source}\\]\\]`)
.replace(
/{now(?::([^}]+))?}/,
`\\[\\[${DAILY_NOTE_PAGE_REGEX.source}\\]\\]`
`\\[\\[${DAILY_NOTE_PAGE_REGEX.source}\\]\\]`,
)}`;
value = value.replace(new RegExp(formattedText), "");
}
Expand All @@ -132,17 +156,17 @@ export default runExtension(async ({ extensionAPI }) => {
.trim()
.replace(/^#/, "")
.replace(/^\[\[/, "")
.replace(/\]\]$/, "")
.replace(/\]\]$/, ""),
)
.reverse()
.reverse(),
);
if (formattedPairs.filter((p) => p.length === 1).length < 2) {
formattedPairs.forEach(([before, after]) => {
if (after) {
value = value
.replace(
`#${before}`,
`#${/\s/.test(after) ? `[[${after}]]` : after}`
`#${/\s/.test(after) ? `[[${after}]]` : after}`,
)
.replace(new RegExp(`\\[\\[${before}\\]\\]`), `[[${after}]]`);
} else {
Expand All @@ -159,7 +183,7 @@ export default runExtension(async ({ extensionAPI }) => {
.replace("/Current Time", format(today, "HH:mm"))
.replace(
"/Today",
`[[${window.roamAlphaAPI.util.dateToPageTitle(today)}]]`
`[[${window.roamAlphaAPI.util.dateToPageTitle(today)}]]`,
)
.replace(/{now(?::([^}]+))?}/, (_: string, group: string) => {
const date = window.roamAlphaAPI.util.dateToPageTitle(today);
Expand Down Expand Up @@ -189,6 +213,9 @@ export default runExtension(async ({ extensionAPI }) => {
};

const onDone = (blockUid: string, oldValue: string) => {
if (shouldIgnoreBlock(oldValue)) {
return { explode: false };
}
const text = extensionAPI.settings.get("append-text") as string;
let value = oldValue;
if (text) {
Expand All @@ -197,7 +224,7 @@ export default runExtension(async ({ extensionAPI }) => {
.replace("/Current Time", format(today, "HH:mm"))
.replace(
"/Today",
`[[${window.roamAlphaAPI.util.dateToPageTitle(today)}]]`
`[[${window.roamAlphaAPI.util.dateToPageTitle(today)}]]`,
)
.replace(/{now(?::([^}]+))?}/, (_: string, group: string) => {
const date = window.roamAlphaAPI.util.dateToPageTitle(today);
Expand All @@ -223,22 +250,22 @@ export default runExtension(async ({ extensionAPI }) => {
.trim()
.replace(/^#/, "")
.replace(/^\[\[/, "")
.replace(/\]\]$/, "")
.replace(/\]\]$/, ""),
)
.map((pp) =>
pp === "{date}"
? DAILY_NOTE_PAGE_REGEX.source
: pp === "{today}"
? window.roamAlphaAPI.util.dateToPageTitle(new Date())
: pp
)
? window.roamAlphaAPI.util.dateToPageTitle(new Date())
: pp,
),
);
formattedPairs.forEach(([before, after]) => {
if (after) {
value = value
.replace(
`#${before}`,
`#${/\s/.test(after) ? `[[${after}]]` : after}`
`#${/\s/.test(after) ? `[[${after}]]` : after}`,
)
.replace(new RegExp(`\\[\\[${before}\\]\\]`), `[[${after}]]`);
} else {
Expand All @@ -258,7 +285,7 @@ export default runExtension(async ({ extensionAPI }) => {
const sendToBlock = extensionAPI.settings.get("send-to-block") as string;
if (sendToBlock) {
const uid = extractRef(
getPageUidByPageTitle(extractTag(sendToBlock)) || sendToBlock
getPageUidByPageTitle(extractTag(sendToBlock)) || sendToBlock,
);
if (uid) {
const bottom = getChildrenLengthByParentUid(uid);
Expand Down Expand Up @@ -303,7 +330,7 @@ export default runExtension(async ({ extensionAPI }) => {
const target = e.target as HTMLElement;
if (
target.parentElement?.getElementsByClassName(
"bp3-text-overflow-ellipsis"
"bp3-text-overflow-ellipsis",
)[0]?.innerHTML === "TODO"
) {
const textarea = target
Expand Down Expand Up @@ -334,7 +361,7 @@ export default runExtension(async ({ extensionAPI }) => {
}
Array.from(document.getElementsByClassName("block-highlight-blue"))
.map(
(d) => d.getElementsByClassName("roam-block")[0] as HTMLDivElement
(d) => d.getElementsByClassName("roam-block")[0] as HTMLDivElement,
)
.map((d) => getUids(d).blockUid)
.map((blockUid) => ({
Expand All @@ -353,8 +380,8 @@ export default runExtension(async ({ extensionAPI }) => {
if (target.tagName === "TEXTAREA") {
const todoItem = Array.from(
target.parentElement?.querySelectorAll<HTMLDivElement>(
".bp3-text-overflow-ellipsis"
) || []
".bp3-text-overflow-ellipsis",
) || [],
).find((t) => t.innerText === "TODO");
if (
todoItem &&
Expand Down Expand Up @@ -395,28 +422,47 @@ export default runExtension(async ({ extensionAPI }) => {
if (input.checked && !input.disabled) {
const zoom = l.closest(".rm-zoom-item-content") as HTMLSpanElement;
if (zoom) {
styleBlock(
zoom.firstElementChild?.firstElementChild as HTMLDivElement
);
const blockUid = getBlockUidFromTarget(input);
const zoomElement = zoom.firstElementChild
?.firstElementChild as HTMLDivElement;
if (blockUid && shouldIgnoreBlock(getTextByBlockUid(blockUid))) {
unstyleBlock(zoomElement);
} else {
styleBlock(zoomElement);
}
return;
}
const block = CLASSNAMES_TO_CHECK.map(
(c) => l.closest(`.${c}`) as HTMLElement
(c) => l.closest(`.${c}`) as HTMLElement,
).find((d) => !!d);
if (block) {
const blockUid = getBlockUidFromTarget(input);
if (blockUid && shouldIgnoreBlock(getTextByBlockUid(blockUid))) {
unstyleBlock(block);
return;
}
}
if (block) {
styleBlock(block);
}
} else {
const zoom = l.closest(".rm-zoom-item-content") as HTMLSpanElement;
if (zoom) {
unstyleBlock(
zoom.firstElementChild?.firstElementChild as HTMLDivElement
zoom.firstElementChild?.firstElementChild as HTMLDivElement,
);
return;
}
const block = CLASSNAMES_TO_CHECK.map(
(c) => l.closest(`.${c}`) as HTMLElement
(c) => l.closest(`.${c}`) as HTMLElement,
).find((d) => !!d);
if (block) {
const blockUid = getBlockUidFromTarget(input);
if (blockUid && shouldIgnoreBlock(getTextByBlockUid(blockUid))) {
unstyleBlock(block);
return;
}
}
if (block) {
unstyleBlock(block);
}
Expand All @@ -430,8 +476,8 @@ export default runExtension(async ({ extensionAPI }) => {
addDeferTODOsCommand();
toggleTodont(
(extensionAPI.settings.get(
"todont-mode"
) as (typeof TODONT_MODES)[number]) || "off"
"todont-mode",
) as (typeof TODONT_MODES)[number]) || "off",
);

return {
Expand Down