Skip to content

Commit 0e381c6

Browse files
authored
Roam: ENG-798 Node Tags breaks Color Highlighter (#402)
* use getDiscourseNodes * Eng-737 use node color to style node tags (#424) * modify dom only for node tags * add background color to a nodetag * use it as color not background color * remove unused refresh * Roam: ENG-693 handle node tags with # in front and update placeholder to use # (#420) * use text not tag * Move the new block as first child of the current block (#422)
1 parent 27d9beb commit 0e381c6

File tree

5 files changed

+57
-24
lines changed

5 files changed

+57
-24
lines changed

apps/roam/src/components/CreateNodeDialog.tsx

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import getDiscourseNodes, {
1111
} from "~/utils/getDiscourseNodes";
1212
import { getNewDiscourseNodeText } from "~/utils/formatUtils";
1313
import MenuItemSelect from "roamjs-components/components/MenuItemSelect";
14+
import createBlock from "roamjs-components/writes/createBlock";
1415

1516
export type CreateNodeDialogProps = {
1617
onClose: () => void;
@@ -48,6 +49,20 @@ const CreateNodeDialog = ({
4849
if (!title.trim()) return;
4950
setLoading(true);
5051

52+
const query = `[:find ?parentUid ?order
53+
:keys parentUid order
54+
:in $ ?block-uid
55+
:where
56+
[?e :block/uid ?block-uid]
57+
[?e :block/order ?order]
58+
[?p :block/children ?e]
59+
[?p :block/uid ?parentUid]
60+
]`;
61+
62+
const blockData = (
63+
await window.roamAlphaAPI.data.async.q(query, sourceBlockUid)
64+
)?.[0] as unknown as { parentUid: string; order: number };
65+
5166
const formattedTitle = await getNewDiscourseNodeText({
5267
text: title.trim(),
5368
nodeType: selectedType.type,
@@ -71,7 +86,16 @@ const CreateNodeDialog = ({
7186
// the correct reference. The reference format should be determined by the
7287
// node's specification.
7388
const pageRef = `[[${formattedTitle}]]`;
74-
await updateBlock({ uid: sourceBlockUid, text: pageRef });
89+
const newBlockUid = await createBlock({
90+
node: { text: pageRef },
91+
parentUid: blockData.parentUid,
92+
order: blockData.order,
93+
});
94+
95+
await window.roamAlphaAPI.moveBlock({
96+
block: { uid: sourceBlockUid },
97+
location: { "parent-uid": newBlockUid, order: 0 },
98+
});
7599

76100
const newCursorPosition = pageRef.length;
77101
const windowId =

apps/roam/src/components/DiscourseNodeMenu.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ const NodeMenu = ({
113113
setTimeout(() => {
114114
const currentText = textarea.value;
115115
const cursorPos = textarea.selectionStart;
116-
const textToInsert = `#${tag} `;
116+
const textToInsert = `#${tag.replace(/^#/, "")} `;
117117

118118
const newText = `${currentText.substring(
119119
0,
@@ -249,9 +249,13 @@ const NodeMenu = ({
249249
<MenuItem
250250
key={item.text}
251251
data-node={item.type}
252-
data-tag={item.tag}
252+
data-tag={item.tag?.replace(/^#/, "")}
253253
text={
254-
showNodeTypes ? item.text : item.tag ? `#${item.tag}` : ""
254+
showNodeTypes
255+
? item.text
256+
: item.tag
257+
? `#${item.tag.replace(/^#/, "")}`
258+
: ""
255259
}
256260
active={i === activeIndex}
257261
onMouseEnter={() => setActiveIndex(i)}

apps/roam/src/components/settings/NodeConfig.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ const NodeConfig = ({
285285
onChange={handleTagChange}
286286
onBlur={handleTagBlur}
287287
error={tagError}
288-
placeholder={`${node.text}`}
288+
placeholder={`#${node.text.toLowerCase()}`}
289289
/>
290290
</div>
291291
}

apps/roam/src/utils/initializeObserversAndListeners.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import {
4444
findBlockElementFromSelection,
4545
} from "~/utils/renderTextSelectionPopup";
4646
import { renderNodeTagPopupButton } from "./renderNodeTagPopup";
47+
import { formatHexColor } from "~/components/settings/DiscourseNodeCanvasSettings";
4748

4849
const debounce = (fn: () => void, delay = 250) => {
4950
let timeout: number;
@@ -102,7 +103,18 @@ export const initObservers = async ({
102103
className: "rm-page-ref--tag",
103104
tag: "SPAN",
104105
callback: (s: HTMLSpanElement) => {
105-
renderNodeTagPopupButton(s, onloadArgs.extensionAPI);
106+
const tag = s.getAttribute("data-tag");
107+
if (tag) {
108+
for (const node of getDiscourseNodes()) {
109+
if (tag.toLowerCase() === node.tag?.toLowerCase()) {
110+
renderNodeTagPopupButton(s, node, onloadArgs.extensionAPI);
111+
if (node.canvasSettings?.color) {
112+
s.style.color = formatHexColor(node.canvasSettings.color);
113+
}
114+
break;
115+
}
116+
}
117+
}
106118
},
107119
});
108120

apps/roam/src/utils/renderNodeTagPopup.tsx

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@ import { renderCreateNodeDialog } from "~/components/CreateNodeDialog";
55
import { OnloadArgs } from "roamjs-components/types";
66
import getUids from "roamjs-components/dom/getUids";
77
import getTextByBlockUid from "roamjs-components/queries/getTextByBlockUid";
8-
import getDiscourseNodes from "./getDiscourseNodes";
8+
import { type DiscourseNode } from "./getDiscourseNodes";
99

1010
export const renderNodeTagPopupButton = (
1111
parent: HTMLSpanElement,
12+
matchedNode: DiscourseNode,
1213
extensionAPI: OnloadArgs["extensionAPI"],
1314
) => {
1415
if (parent.dataset.attributeButtonRendered === "true") return;
1516

17+
const rect = parent.getBoundingClientRect();
1618
parent.dataset.attributeButtonRendered = "true";
1719
const wrapper = document.createElement("span");
1820
wrapper.style.position = "relative";
@@ -24,26 +26,14 @@ export const renderNodeTagPopupButton = (
2426
reactRoot.style.position = "absolute";
2527
reactRoot.style.top = "0";
2628
reactRoot.style.left = "0";
27-
reactRoot.style.width = "100%";
28-
reactRoot.style.height = "100%";
29+
reactRoot.style.width = `${rect.width}px`;
30+
reactRoot.style.height = `${rect.height}px`;
2931
reactRoot.style.pointerEvents = "none";
3032
reactRoot.style.zIndex = "10";
3133

3234
wrapper.appendChild(reactRoot);
3335

3436
const textContent = parent.textContent?.trim() || "";
35-
const tagAttr = parent.getAttribute("data-tag") || textContent;
36-
const tag = tagAttr.replace(/^#/, "").toLowerCase();
37-
const discourseNodes = getDiscourseNodes();
38-
const discourseTagSet = new Set(
39-
discourseNodes.map((n) => n.tag?.toLowerCase()).filter(Boolean),
40-
);
41-
if (!discourseTagSet.has(tag)) return;
42-
43-
const matchedNode = discourseNodes.find((n) => n.tag?.toLowerCase() === tag);
44-
45-
if (!matchedNode) return;
46-
4737
const blockInputElement = parent.closest(".rm-block__input");
4838
const blockUid = blockInputElement
4939
? getUids(blockInputElement as HTMLDivElement).blockUid
@@ -74,8 +64,11 @@ export const renderNodeTagPopupButton = (
7464
<span
7565
style={{
7666
display: "block",
77-
width: "100%",
78-
height: "100%",
67+
top: "0",
68+
left: "0",
69+
width: `${rect.width}px`,
70+
height: `${rect.height}px`,
71+
position: "absolute",
7972
pointerEvents: "auto",
8073
}}
8174
/>
@@ -84,7 +77,7 @@ export const renderNodeTagPopupButton = (
8477
position={Position.TOP}
8578
modifiers={{
8679
offset: {
87-
offset: "0, 10",
80+
offset: `${rect.width / 2}px, 10`,
8881
},
8982
arrow: {
9083
enabled: false,

0 commit comments

Comments
 (0)