(property: Partial<Property>, newValue: unknown, file: TFile)
| 575 | } |
| 576 | |
| 577 | public async updatePropertyInFile(property: Partial<Property>, newValue: unknown, file: TFile): Promise<void> { |
| 578 | if (!property.key) return; |
| 579 | |
| 580 | // Guard the direct frontmatter key before opening the file. Deeper path |
| 581 | // segments (a nested `parent.__proto__` write) are refused by |
| 582 | // `setYamlPath` itself; this catches the top-level `frontmatter[key] = ` |
| 583 | // sink. A reserved `tags`/`tag` key is impossible, so this is harmless |
| 584 | // for the tags branch. |
| 585 | if (property.type === MetaType.YAML) this.assertWritableKey(property.key); |
| 586 | |
| 587 | await this.enqueueFileWrite(file, async () => { |
| 588 | if (property.type === MetaType.YAML) { |
| 589 | await this.processFrontMatter(file, (frontmatter) => { |
| 590 | if (property.path && property.path.length > 1) { |
| 591 | setYamlPath(frontmatter, property.path, newValue, { |
| 592 | createParents: false, |
| 593 | createLeaf: false, |
| 594 | expectedValue: property.content, |
| 595 | validateExpectedValue: true, |
| 596 | }); |
| 597 | } else if (isTagsKey(property.key)) { |
| 598 | // Canonicalise `tags`: strip `#`, drop blanks, store a list. |
| 599 | // When the last tag is gone, remove the key (Decision E) |
| 600 | // rather than leave a dangling `tags:` / `tags: []`. |
| 601 | const tags = splitFrontmatterTags(newValue); |
| 602 | if (tags.length === 0) delete frontmatter[property.key!]; |
| 603 | else frontmatter[property.key!] = tags; |
| 604 | } else { |
| 605 | frontmatter[property.key!] = newValue; |
| 606 | } |
| 607 | }); |
| 608 | return; |
| 609 | } |
| 610 | |
| 611 | if (property.type === MetaType.Tag) { |
| 612 | await this.writeTagOccurrence(property, newValue, file); |
| 613 | return; |
| 614 | } |
| 615 | |
| 616 | if (property.type !== MetaType.Dataview || !property.key) return; |
| 617 | |
| 618 | const fileContent = await this.app.vault.read(file); |
| 619 | const newFileContent = this.parser.replaceInlineFieldValuesInContent(fileContent, [ |
| 620 | {key: property.key, value: String(newValue)}, |
| 621 | ]); |
| 622 | |
| 623 | await this.app.vault.modify(file, newFileContent); |
| 624 | }); |
| 625 | } |
| 626 | |
| 627 | /** |
| 628 | * Rewrite one body-tag occurrence in place, by its parsed span. The span is |
no test coverage detected