from various sources mostly from this forum (sorry, i cannot give credit to whom i am most indebted) i created a non-quickadd pure templater script anyone can use to add properties on demand into a file that already has yaml and some props
i am using metadatacache way to add tags only on desktop as dataview is not working for my vault on mobile so if you want to remove the if (!app.isMobile) {
condition, some ai robot can help
obviously install and enable dataview on desktop for this to work for you
tags are chosen for default but you can delete back and add your own prop name
currently only tags and topic properties allow multiple values so if the user needs a different property, replace the topic word in the script with any other to be able to add multiple values to that one
you can ask ai to make a script based on this to add other props with multi values of course…
otherwise the rule is: one new prop > one value taken only
if you add e.g. ‘chickencrossedtheRoad’ > ‘false’ or ‘true’, correct boolean values will be added without quotes
<%*
(async () => {
// Prompt user for property name
const propertyName = await tp.system.prompt("Enter the property name (tags, topic or any other property, including a new one):", "tags", "tags");
if (!propertyName) {
console.log("No property name provided. Exiting script.");
return;
}
console.log("Property name provided:", propertyName);
let propertyValues = [];
if (propertyName === "topic") {
let isAddingTopic = true;
while (isAddingTopic) {
const topic = await tp.system.prompt("Add topic until ESC or close box on mobile to finish (if you add links, no need to add double quotes).");
if (topic === null || topic === "") {
isAddingTopic = false;
} else {
propertyValues.push(topic);
}
}
} else if (propertyName === "tags") {
let selectedTags = [];
if (!app.isMobile) {
// Fetch existing tags
const dv = app.plugins.plugins.dataview.api;
const cachedTags = Object.entries(app.metadataCache.getTags())
.sort((a, b) => b[1] - a[1]); // Sorted by frequency
let selectMore = true;
while (selectMore) {
let choice = await tp.system.suggester((t) => t[0] + " (" + t[1] + ")", cachedTags, false, "[Select some tags. (ESC or click out of box on mobile when finished)]");
if (!choice || !choice[0]) {
selectMore = false;
} else {
selectedTags.push(choice[0]);
}
}
console.log("Selected tags:", selectedTags);
}
let isAddingTags = true;
while (isAddingTags) {
const userTags = await tp.system.prompt("Add more tags until ESC.");
if (userTags === null || userTags === "") {
isAddingTags = false;
} else {
// Split the userTags string into an array of tags, trim each tag, prepend #, and push to selectedTags
userTags.split(',').forEach(tag => {
const trimmedTag = tag.trim();
if (trimmedTag) { // Check if the tag is not empty after trimming
selectedTags.push('#' + trimmedTag); // Prepend # here
}
});
}
}
propertyValues = selectedTags;
} else {
// Prompt user for a single value
const propertyValue = await tp.system.prompt(`Enter the value for ${propertyName}:`);
if (!propertyValue) {
console.log("No property value provided. Exiting script.");
return;
}
console.log("Property value provided:", propertyValue);
propertyValues.push(propertyValue);
}
// Update front matter using Obsidian API
await app.fileManager.processFrontMatter(tp.config.target_file, frontmatter => {
if (!frontmatter[propertyName]) {
frontmatter[propertyName] = propertyValues.length === 1 ? propertyValues[0] : propertyValues;
} else {
if (Array.isArray(frontmatter[propertyName])) {
frontmatter[propertyName] = [...new Set([...frontmatter[propertyName], ...propertyValues])];
} else {
frontmatter[propertyName] = propertyValues.length === 1 ? propertyValues[0] : propertyValues;
}
}
console.log("Frontmatter updated");
});
// Wait for the update to complete
await new Promise(resolve => setTimeout(resolve, 250));
// Remove double quotes from around boolean values (true and false)
const currentFile = app.workspace.getActiveFile();
let fileContent = await app.vault.read(currentFile);
// Match YAML block and replace double quotes around true and false
fileContent = fileContent.replace(/^---([\s\S]*?)---/gm, (match, p1) => {
return match.replace(/"true"|'true'|"false"|'false'/g, match => match.replace(/["']/g, ''));
});
await app.vault.modify(currentFile, fileContent);
})();
-%>
tags values are added hashes because 1. the metadatacache selection adds them 2. you can use your files anywhere else to search your tags
related thread:
so needed plugins:
- templater
- dataview
copy contents to file and add that filename to templater to use the script
fire script on active note