Skip to content

Commit

Permalink
correctly render links and images in HoverPane and AnnotCard
Browse files Browse the repository at this point in the history
  • Loading branch information
HuntFeng committed Sep 2, 2023
1 parent 917b96c commit e8eebb7
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 26 deletions.
40 changes: 36 additions & 4 deletions src/components/note/HoverPane.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,31 @@
</template>
<script setup lang="ts">
import Vditor from "vditor/dist/method.min";
import { onMounted, ref, watchEffect } from "vue";
import { onMounted, PropType, ref, watchEffect } from "vue";
import { useStateStore } from "src/stores/appState";
const stateStore = useStateStore();
const props = defineProps({
content: { type: String },
data: {
type: Object as PropType<{ linkBase: string; content: string }>,
required: true,
},
});
const emit = defineEmits(["clickLink"]);
const card = ref();
const mdContentDiv = ref();
watchEffect(() => {
if (props.content && mdContentDiv.value)
Vditor.preview(mdContentDiv.value, props.content, {
if (props.data.content && mdContentDiv.value)
Vditor.preview(mdContentDiv.value, props.data.content, {
theme: stateStore.settings.theme === "dark" ? "dark" : "classic",
mode: stateStore.settings.theme,
hljs: {
lineNumber: true,
style: stateStore.settings.theme === "dark" ? "native" : "emacs",
},
after: changeLinks,
});
});
Expand All @@ -42,6 +47,33 @@ onMounted(async () => {
};
});
function changeLinks() {
if (!mdContentDiv.value) return;
let linkNodes = mdContentDiv.value.querySelectorAll(
"a"
) as NodeListOf<HTMLAnchorElement>;
for (let linkNode of linkNodes) {
linkNode.onclick = (e: MouseEvent) => {
// do not open link winthin app
e.preventDefault();
let link = linkNode.href
.replace("http://localhost:9300/", "") // in dev mode
.replace(/^file:.*app\.asar\//, ""); // in production mode
emit("clickLink", e, link);
};
}
let imageNodes = mdContentDiv.value.querySelectorAll(
"img"
) as NodeListOf<HTMLImageElement>;
for (let imageNode of imageNodes) {
imageNode.src = imageNode.src
.replace("http://localhost:9300", props.data.linkBase) // in dev mode
.replace(/^file:.*app\.asar/, props.data.linkBase); // in production mode
}
}
defineExpose({ card });
</script>
<style lang="scss">
Expand Down
44 changes: 31 additions & 13 deletions src/components/note/NoteEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
></div>
<HoverPane
:content="hoverContent"
:data="hoverData"
@clickLink="(e:MouseEvent, link:string) => clickLink(e,link)"
ref="hoverPane"
/>
</template>
Expand Down Expand Up @@ -53,6 +55,8 @@ const showEditor = ref(false);
const linkBase = ref("");
const hoverPane = ref();
const hoverContent = ref("");
// tells HoverPane the hovered project path prefix and the content to show
const hoverData = ref({ linkBase: "", content: "" });
watch(
() => stateStore.settings.theme,
Expand Down Expand Up @@ -149,13 +153,12 @@ function initEditor() {
},
],
},
after: () => {
if (showEditor.value) {
setContent();
setTheme(stateStore.settings.theme);
changeLinks();
addImgResizer();
}
after: async () => {
if (!showEditor.value) return;
await setContent();
setTheme(stateStore.settings.theme);
changeLinks();
addImgResizer();
},
blur: () => {
saveContent();
Expand Down Expand Up @@ -262,24 +265,28 @@ async function saveLinks() {
*****************************************/
function _changeLinks() {
if (!vditorDiv.value) return;
console.log("change link", currentNote.value.label);
let linkNodes = vditorDiv.value.querySelectorAll(
"[data-type='a']"
) as NodeListOf<HTMLElement>;
console.log("linkNodes", linkNodes);
for (let linkNode of linkNodes) {
linkNode.onclick = (e) => clickLink(e, linkNode);
console.log("linkNode", linkNode);
let link = (
linkNode.querySelector("span.vditor-ir__marker--link") as HTMLSpanElement
).innerText;
linkNode.onclick = (e) => clickLink(e, link);
linkNode.onmouseover = () => hoverLink(linkNode);
}
}
const changeLinks = debounce(_changeLinks, 50) as () => void;
async function clickLink(e: MouseEvent, linkNode: HTMLElement) {
async function clickLink(e: MouseEvent, link: string) {
if (!vditor.value) return;
e.stopImmediatePropagation(); // stop propagating the click event
vditor.value.blur(); // save the content before jumping
let link = (
linkNode.querySelector("span.vditor-ir__marker--link") as HTMLElement
).innerText;
try {
// valid external url, open it externally
new URL(link);
Expand All @@ -304,7 +311,7 @@ async function clickLink(e: MouseEvent, linkNode: HTMLElement) {
}
async function hoverLink(linkNode: HTMLElement) {
if (!hoverPane.value) return;
if (!hoverPane.value || !currentNote.value) return;
let link = (
linkNode.querySelector("span.vditor-ir__marker--link") as HTMLElement
).innerText;
Expand All @@ -323,7 +330,16 @@ async function hoverLink(linkNode: HTMLElement) {
`Abstract: ${item.abstract}`,
];
hoverContent.value = lines.join("\n");
hoverData.value.linkBase = linkBase.value.replace(
currentNote.value.projectId,
item._id
);
hoverData.value.content = lines.join("\n");
} else if (item.dataType === "note") {
hoverData.value.linkBase = linkBase.value.replace(
currentNote.value.projectId,
item.projectId
);
if (item.type === "excalidraw") {
let lines = [
"# Excalidraw note",
Expand All @@ -334,9 +350,11 @@ async function hoverLink(linkNode: HTMLElement) {
)}`,
];
hoverContent.value = lines.join("\n");
hoverData.value.content = lines.join("\n");
} else {
let content = await loadNote(item._id);
hoverContent.value = content;
hoverData.value.content = content;
}
}
Expand Down
70 changes: 61 additions & 9 deletions src/components/pdfreader/AnnotCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,12 @@ import { Annotation } from "src/backend/pdfannotation/annotations";
import AnnotMenu from "./AnnotMenu.vue";
import { copyToClipboard, colors } from "quasar";
import { AnnotationData } from "src/backend/database";
import { AnnotationData, Note, NoteType, Project } from "src/backend/database";
import PDFApplication from "src/backend/pdfreader";
import { KEY_pdfApp } from "./injectKeys";
import Vditor from "vditor/dist/method.min";
import { useStateStore } from "src/stores/appState";
import { getItem } from "src/backend/project/graph";
const { luminosity } = colors;
const stateStore = useStateStore();
Expand Down Expand Up @@ -136,23 +137,74 @@ const deleteAnnot = () => {
pdfApp.annotStore?.delete(props.annot.data._id);
};
// function changeLinks() {
// if (!mdContentDiv.value) return;
// let linkNodes = mdContentDiv.value.querySelectorAll(
// "a"
// ) as NodeListOf<HTMLAnchorElement>;
// for (let linkNode of linkNodes) {
// linkNode.onclick = (e) => {
// e.preventDefault();
// try {
// // valid external url, open it externally
// new URL(linkNode.href);
// window.browser.openURL(linkNode.href);
// } catch (error) {
// console.log(error);
// }
// };
// }
// }
function changeLinks() {
if (!mdContentDiv.value) return;
let linkNodes = mdContentDiv.value.querySelectorAll(
"a"
) as NodeListOf<HTMLAnchorElement>;
for (let linkNode of linkNodes) {
console.log(linkNode);
linkNode.onclick = (e) => {
linkNode.onclick = (e: MouseEvent) => {
// do not open link winthin app
e.preventDefault();
try {
// valid external url, open it externally
new URL(linkNode.href);
window.browser.openURL(linkNode.href);
} catch (error) {
console.log(error);
let link = linkNode.href
.replace("http://localhost:9300/", "") // in dev mode
.replace(/^file:.*app\.asar\//, ""); // in production mode
for (let linkNode of linkNodes) {
linkNode.onclick = async (e) => {
e.preventDefault();
try {
// valid external url, open it externally
new URL(link);
window.browser.openURL(link);
} catch (error) {
// we just want the document, both getProject or getNote are good
try {
let item = (await getItem(link)) as Note | Project;
let id = item._id;
let label = item.label;
let type = "";
if (item.dataType === "project") type = "ReaderPage";
else if ((item as Project | Note).dataType === "note") {
if (item.type === NoteType.EXCALIDRAW) type = "ExcalidrawPage";
else type = "NotePage";
}
stateStore.openPage({ id, type, label });
} catch (error) {
console.log(error);
}
}
};
}
};
}
let imageNodes = mdContentDiv.value.querySelectorAll(
"img"
) as NodeListOf<HTMLImageElement>;
for (let imageNode of imageNodes) {
imageNode.src = imageNode.src
.replace("http://localhost:9300", props.data.linkBase) // in dev mode
.replace(/^file:.*app.sar/, props.data.linkBase); // in production mode
}
}
</script>
3 changes: 3 additions & 0 deletions todo.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
- [x] openProjectIds are not saved properly, the projectStore.openedProject is updated after the saving.
- [x] when opening a note, also open its project
- [x] drag multiple documents at the same time
- [x] correctly render image and link in hoverPane
- [x] ChangeLinks get empty links before content is set
- [x] correctly render link in AnnotCard

### TODO

Expand Down

0 comments on commit e8eebb7

Please sign in to comment.