参考文献
This commit is contained in:
161
src/utils/autociteMainListOrder.js
Normal file
161
src/utils/autociteMainListOrder.js
Normal file
@@ -0,0 +1,161 @@
|
||||
/**
|
||||
* Main_List 全文首次出现顺序(与 Edit Content / 稿面 / 底部参考文献列表共用)。
|
||||
* 正文中 <mytable> 占位处需先插入对应表格段在 Main_List 中的表题/表体/表注引用,再计其后的 mycite。
|
||||
*/
|
||||
import { extractAutociteIdsFromHtmlString } from '@/utils/autociteHtml.js';
|
||||
|
||||
export function collectCiteStringsDeep(source, out, depth = 0) {
|
||||
if (!source || depth > 6) return;
|
||||
if (typeof source === 'string') {
|
||||
const s = source.trim();
|
||||
if (!s) return;
|
||||
const maybeCite = /<(?:mycite|autocite)\b/i.test(s) || /\[[\d\s,,\-–—]+\]/.test(s);
|
||||
if (maybeCite) out.push(s);
|
||||
return;
|
||||
}
|
||||
if (Array.isArray(source)) {
|
||||
source.forEach((item) => collectCiteStringsDeep(item, out, depth + 1));
|
||||
return;
|
||||
}
|
||||
if (typeof source === 'object') {
|
||||
Object.keys(source).forEach((k) => {
|
||||
const v = source[k];
|
||||
collectCiteStringsDeep(v, out, depth + 1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function collectCiteHtmlSourcesForMainListItem(p, draftAmId, draftHtml) {
|
||||
if (draftAmId != null && p && p.am_id == draftAmId && draftHtml != null) {
|
||||
return [draftHtml];
|
||||
}
|
||||
const out = [];
|
||||
const typ = p != null && p.type != null ? Number(p.type) : NaN;
|
||||
if (typ === 2 && p.table) {
|
||||
const t = p.table;
|
||||
if (typeof t.title === 'string' && t.title.trim()) out.push(t.title);
|
||||
if (typeof t.html_data === 'string' && t.html_data.trim()) {
|
||||
out.push(t.html_data);
|
||||
} else {
|
||||
const pushRows = (rows) => {
|
||||
if (!Array.isArray(rows)) return;
|
||||
rows.forEach((row) => {
|
||||
if (!Array.isArray(row)) return;
|
||||
row.forEach((cell) => {
|
||||
if (cell && typeof cell.text === 'string' && cell.text) out.push(cell.text);
|
||||
});
|
||||
});
|
||||
};
|
||||
pushRows(t.tableHeader);
|
||||
pushRows(t.tableContent);
|
||||
}
|
||||
if (typeof t.note === 'string' && t.note.trim()) out.push(t.note);
|
||||
collectCiteStringsDeep(t, out);
|
||||
return out;
|
||||
}
|
||||
if (typ === 1 && p.image) {
|
||||
const img = p.image;
|
||||
if (typeof img.title === 'string' && img.title.trim()) out.push(img.title);
|
||||
if (typeof img.note === 'string' && img.note.trim()) out.push(img.note);
|
||||
if (out.length === 0) {
|
||||
if (p && typeof p.content === 'string' && p.content.trim()) out.push(p.content);
|
||||
if (p && typeof p.text === 'string' && p.text.trim()) out.push(p.text);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
if (p && typeof p.text === 'string' && p.text.trim()) out.push(p.text);
|
||||
if (p && typeof p.content === 'string' && p.content.trim()) out.push(p.content);
|
||||
return out;
|
||||
}
|
||||
|
||||
export function findMainListTableByLinkId(mainList, rawId) {
|
||||
if (rawId == null || String(rawId).trim() === '') return null;
|
||||
const sid = String(rawId).trim();
|
||||
const list = Array.isArray(mainList) ? mainList : [];
|
||||
return (
|
||||
list.find((p) => {
|
||||
if (!p || Number(p.type) !== 2) return false;
|
||||
if (String(p.amt_id) === sid) return true;
|
||||
if (String(p.am_id) === sid) return true;
|
||||
if (p.p_main_table_id != null && String(p.p_main_table_id) === sid) return true;
|
||||
if (p.table && p.table.amt_id != null && String(p.table.amt_id) === sid) return true;
|
||||
if (p.table && p.table.am_id != null && String(p.table.am_id) === sid) return true;
|
||||
if (p.table && p.table.p_main_table_id != null && String(p.table.p_main_table_id) === sid)
|
||||
return true;
|
||||
if (p.table && p.table.table_id != null && String(p.table.table_id) === sid) return true;
|
||||
return false;
|
||||
}) || null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {object} [options]
|
||||
* @param {number|string|null} [options.tableDraftAmId] 正在编辑的表格段 am_id(Edit Table 抽屉)
|
||||
* @param {string|null} [options.tableDraftHtml] 与该表对应的 Title+表体+Note 合并稿;正文里 mytable 展开到该表时用此稿替代 Main_List 已存内容,使「全文 mytable 之前」的序号与抽屉内一致
|
||||
*/
|
||||
export function extractAutociteOrderFromDraftHtmlWithInlineTables(html, mainList, options = {}) {
|
||||
const order = [];
|
||||
const pushUnique = (id) => {
|
||||
if (id && !order.includes(id)) order.push(id);
|
||||
};
|
||||
const pushFromRaw = (raw) => {
|
||||
extractAutociteIdsFromHtmlString(raw).forEach((id) => pushUnique(id));
|
||||
};
|
||||
if (!html || typeof html !== 'string') return order;
|
||||
|
||||
const re = /<mytable\b[^>]*>[\s\S]*?<\/mytable>/gi;
|
||||
let last = 0;
|
||||
let m;
|
||||
while ((m = re.exec(html)) !== null) {
|
||||
const before = html.slice(last, m.index);
|
||||
if (before) pushFromRaw(before);
|
||||
|
||||
const openEnd = html.indexOf('>', m.index) + 1;
|
||||
const openTag = html.slice(m.index, openEnd);
|
||||
const dm = openTag.match(/\bdata-id\s*=\s*["']([^"']*)["']/i);
|
||||
const tid = dm ? String(dm[1]).trim() : '';
|
||||
const tableP = findMainListTableByLinkId(mainList, tid);
|
||||
if (tableP) {
|
||||
const useDraft =
|
||||
options.tableDraftAmId != null &&
|
||||
options.tableDraftHtml != null &&
|
||||
String(tableP.am_id) === String(options.tableDraftAmId);
|
||||
const sources = useDraft
|
||||
? [options.tableDraftHtml]
|
||||
: collectCiteHtmlSourcesForMainListItem(tableP, null, null);
|
||||
sources.forEach((raw) => pushFromRaw(raw));
|
||||
}
|
||||
|
||||
last = m.index + m[0].length;
|
||||
}
|
||||
const after = html.slice(last);
|
||||
if (after) pushFromRaw(after);
|
||||
|
||||
return order;
|
||||
}
|
||||
|
||||
export function extractAutociteOrderFromMainList(mainList, draftAmId, draftHtml, options = {}) {
|
||||
const list = Array.isArray(mainList) ? mainList : [];
|
||||
const order = [];
|
||||
list.forEach((p) => {
|
||||
if (draftAmId != null && p && p.am_id == draftAmId && draftHtml != null) {
|
||||
extractAutociteOrderFromDraftHtmlWithInlineTables(draftHtml, list, options).forEach((id) => {
|
||||
if (!order.includes(id)) order.push(id);
|
||||
});
|
||||
return;
|
||||
}
|
||||
const candidates = collectCiteHtmlSourcesForMainListItem(p, draftAmId, draftHtml);
|
||||
candidates.forEach((raw) => {
|
||||
if (typeof raw === 'string' && /<mytable\b/i.test(raw)) {
|
||||
extractAutociteOrderFromDraftHtmlWithInlineTables(raw, list, options).forEach((id) => {
|
||||
if (!order.includes(id)) order.push(id);
|
||||
});
|
||||
} else {
|
||||
extractAutociteIdsFromHtmlString(raw).forEach((id) => {
|
||||
if (!order.includes(id)) order.push(id);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
return order;
|
||||
}
|
||||
Reference in New Issue
Block a user