fix: embed link mode loss citation items data

This commit is contained in:
windingwind 2023-12-02 20:39:25 +08:00
parent 85339a0b31
commit eb5c5d9dc3
3 changed files with 65 additions and 21 deletions

View File

@ -5,7 +5,7 @@ import {
} from "../../utils/link";
import { getString } from "../../utils/locale";
import { getLinesInNote } from "../../utils/note";
import { formatPath, jointPath } from "../../utils/str";
import { formatPath, jointPath, tryDecodeParse } from "../../utils/str";
export { exportNotes };
@ -214,6 +214,8 @@ async function toFreeMind(noteItem: Zotero.Item) {
async function embedLinkedNotes(noteItem: Zotero.Item): Promise<string> {
const parser = ztoolkit.getDOMParser();
const globalCitationData = getNoteCitationData(noteItem as Zotero.Item);
const newLines: string[] = [];
const noteLines = getLinesInNote(noteItem);
for (const i in noteLines) {
@ -230,7 +232,49 @@ async function embedLinkedNotes(noteItem: Zotero.Item): Promise<string> {
[linkParam.link, noteItem],
);
newLines.push(html);
const citationData = getNoteCitationData(
linkParam.noteItem as Zotero.Item,
);
globalCitationData.items.push(...citationData.items);
}
}
return newLines.join("\n");
// Clean up globalCitationItems
const seenCitationItemIDs = [] as string[];
const finalCitationItems = [];
for (const citationItem of globalCitationData.items) {
const currentID = citationItem.uris[0];
if (!(currentID in seenCitationItemIDs)) {
finalCitationItems.push(citationItem);
seenCitationItemIDs.push(currentID);
}
}
return `<div data-schema-version="${
globalCitationData.schemaVersion
}" data-citation-items="${encodeURIComponent(
JSON.stringify(finalCitationItems),
)}">${newLines.join("\n")}</div>`;
}
function getNoteCitationData(noteItem: Zotero.Item) {
const parser = new DOMParser();
const doc = parser.parseFromString(noteItem.getNote(), "text/html");
const citationItems = tryDecodeParse(
doc
.querySelector("div[data-citation-items]")
?.getAttribute("data-citation-items") || "[]",
) as unknown as Array<{
uris: string[];
itemData: Record<string, any>;
schemaVersion: string;
}>;
const citationData = {
items: citationItems,
schemaVersion:
doc
.querySelector("div[data-schema-version]")
?.getAttribute("data-schema-version") || "",
};
return citationData;
}

View File

@ -1,6 +1,6 @@
import { showHintWithLink } from "../../utils/hint";
import { renderNoteHTML } from "../../utils/note";
import { randomString } from "../../utils/str";
import { htmlEscape, randomString, tryDecodeParse } from "../../utils/str";
import { waitUtilAsync } from "../../utils/wait";
import { config } from "../../../package.json";
@ -76,10 +76,10 @@ function parseDocxCitationFields(html: string) {
}
]
*/
const globalCitationItems = tryParse(
const globalCitationItems = tryDecodeParse(
doc
.querySelector("div[data-citation-items]")
?.getAttribute("data-citation-items") || "{}",
?.getAttribute("data-citation-items") || "[]",
);
const citationElements = Array.from(
doc.querySelectorAll(".citation[data-citation]"),
@ -95,7 +95,7 @@ function parseDocxCitationFields(html: string) {
"properties": {}
}
*/
const citation = tryParse(elem.getAttribute("data-citation") || "{}");
const citation = tryDecodeParse(elem.getAttribute("data-citation") || "{}");
const citationItems = [];
for (const citationItem of citation.citationItems) {
const item = globalCitationItems.find(
@ -205,21 +205,6 @@ function getCitationID(citationCache: CitationCache) {
return citationID;
}
function tryParse(s: string) {
try {
return JSON.parse(decodeURIComponent(s));
} catch (e) {
return null;
}
}
function htmlEscape(doc: Document, str: string) {
const div = doc.createElement("div");
const text = doc.createTextNode(str);
div.appendChild(text);
return div.innerHTML.replace(/"/g, "&quot;").replace(/'/g, "&#39;");
}
function generateDocxField(fieldCode: string, text: string) {
return `<!--[if supportFields]>
<span style='mso-element:field-begin'></span>

View File

@ -99,3 +99,18 @@ export function jointPath(...paths: string[]) {
return "";
}
}
export function tryDecodeParse(s: string) {
try {
return JSON.parse(decodeURIComponent(s));
} catch (e) {
return null;
}
}
export function htmlEscape(doc: Document, str: string) {
const div = doc.createElement("div");
const text = doc.createTextNode(str);
div.appendChild(text);
return div.innerHTML.replace(/"/g, "&quot;").replace(/'/g, "&#39;");
}