diff --git a/.changeset/tricky-chefs-cry.md b/.changeset/tricky-chefs-cry.md new file mode 100644 index 0000000..4a76aa6 --- /dev/null +++ b/.changeset/tricky-chefs-cry.md @@ -0,0 +1,5 @@ +--- +'anki-templates': patch +--- + +feat(tf): optimize experience of `items` in mobile (优化移动端`items` 字段体验) diff --git a/README.md b/README.md index cc57907..49a5b35 100644 --- a/README.md +++ b/README.md @@ -39,9 +39,9 @@ Note: When all options are empty, the template will behave as a basic Q&A templa Notes for `items` -- All sub-questions should be in an unordered list format -- Each sub-question must begin with "T:" or "F:", indicating whether the sub-question is true or false -- Pay special attention to ensuring "T/F" is followed by an English half-width colon +- All sub-questions should meet the format constriant +- Each sub-question must begin with a line "T===" or "F===", indicating whether the sub-question is true or false +- Pay special attention to ensuring "T/F" is followed by three or more equal signs | Field name | Description | | ---------- | ------------------------------------------------------------------------------------------------------------- | diff --git a/release.json b/release.json index 051f821..5f5a10a 100644 --- a/release.json +++ b/release.json @@ -44,7 +44,7 @@ { "fields": { "question": "This is the stem of the question. It supports various content formats in Anki, including bold, formulas, etc.", - "items": "", + "items": "T===
All sub-questions should meet the format constriant

T===
Each sub-question must begin with a line \"T===\" or \"F===\", indicating whether the sub-question is true or false

T===
Pay special attention to ensuring \"T/F\" is followed by three or more equal signs", "note": "note" } } diff --git a/src/utils/extract-tf-items.ts b/src/utils/extract-tf-items.ts index 4d5459e..5f301f0 100644 --- a/src/utils/extract-tf-items.ts +++ b/src/utils/extract-tf-items.ts @@ -1,3 +1,7 @@ +function isBrNode(node?: Node | null): node is HTMLBRElement { + return node?.nodeType === Node.ELEMENT_NODE && node.nodeName === 'BR'; +} + export interface TfItem { node: HTMLDivElement; answer: boolean; @@ -7,6 +11,40 @@ export function extractTfItems(field: HTMLElement): TfItem[] { if (!field) { return []; } + const textContent = field.textContent?.trim(); + if (!textContent) { + return []; + } + if (!/^[TF]={3,}/.test(textContent)) { + return extractTfItemsLegacy(field); + } + + const items: TfItem[] = []; + const childNodes = Array.from(field.childNodes); + for (const node of childNodes) { + const childText = node.textContent || ''; + const match = childText.match(/^(T|F)={3,}/); + const last = items[items.length - 1]; + if (match) { + items.push({ + answer: match[1] === 'T', + node: document.createElement('div'), + }); + if (last) { + while (isBrNode(last.node.lastChild)) { + last.node.lastChild.remove(); + } + } + } else { + if (last && !(last.node.childNodes.length === 0 && isBrNode(node))) { + last.node.appendChild(node); + } + } + } + return items; +} + +export function extractTfItemsLegacy(field: HTMLElement): TfItem[] { const itemNodes = field.querySelector('ul')?.querySelectorAll(':scope > li'); if (!itemNodes?.length) { return [];