Hey everyone,
With the upcoming bases (currently in Insider builds), Dataview inline properties (like [key:: value]
) aren’t directly supported.
I’ve been using dataview inline properties for my movies, books, and games notes, and I needed a way to transition them to the new frontmattere properties seamlessly. I didn’t find a tool that worked well for this, so I created a templater script.
What This Script Does
This script finds those inline properties in your notes inside a folder, moves them to the note’s frontmatter, and then replaces the old inline property in your note’s main content with a simple Dataview call like `= this.property`.
Avertissement !
Always back up your vault first! This should be an automatism whenever you’re modifying a bunch of notes at once.
This script is pretty basic. It assumes your inline properties follow that standard [property:: value]
format, always starting on a new line. If your syntax is a bit different, you might need to tweak the regex part of the script. It’s not magic, so some edge cases might slip through.
How to use it
- Create a new Templater note in your templates folder (e.g.,
Move Inline Props.md
). - Copy and paste the script below into it.
- Important: At the very top of the script, change
folderPath
to your specific folder, and updatepropertiesToConvert
with your exact property names.. - Run the script: Go to the Command Palette (
Ctrl/Cmd + P
), find “Templater: Replaces template in the active file”.
The script
<%*
// IMPORTANT: ALWAYS BACK UP YOUR VAULT BEFORE RUNNING ANY SCRIPT THAT MODIFIES NOTES IN BULK!
// --- CONFIGURATION ---
const folderPath = "films"; // <-- CHANGE THIS: Example: "movies", "Resources/books"
const propertiesToConvert = [ // <-- CHANGE THIS: List your inline properties here
"publié",
"status",
"score"
];
// --- END CONFIGURATION ---
// Utility to safely handle special characters in property names for search
function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
// A tiny pause to help Obsidian catch up
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
await Promise.all(
app.vault.getMarkdownFiles()
.filter(file => file.path.startsWith(folderPath))
.map(async file => {
try {
console.log(`Starting on: ${file.path}`);
let currentContent = await app.vault.read(file);
let propertiesFound = {};
let didFindAnyProperty = false;
// 1. Find and collect the inline properties
for (const prop of propertiesToConvert) {
// This regex looks for [prop:: value] at the start of a line or after a newline
const regex = new RegExp(`(?<=\\n|^)\\[${escapeRegExp(prop)}::\\s*(.*?)\\]`, 'g');
let match;
while ((match = regex.exec(currentContent)) !== null) {
const value = match[1].trim();
propertiesFound[prop] = value;
didFindAnyProperty = true;
console.log(` Found "${prop}" with value "${value}"`);
}
}
if (didFindAnyProperty) {
console.log(` Ready to add to frontmatter:`, propertiesFound);
// 2. Add properties to the Frontmatter
await app.fileManager.processFrontMatter(file, (frontmatter) => {
for (const key in propertiesFound) {
if (propertiesFound.hasOwnProperty(key)) {
frontmatter[key] = propertiesFound[key];
console.log(` Added/Updated frontmatter: ${key} = "${propertiesFound[key]}"`);
}
}
});
// re-read the file after frontmatter change
await delay(50);
let contentAfterFrontmatterUpdate = await app.vault.read(file);
// 3. Replace inline properties in the note's body
let finalNoteContent = contentAfterFrontmatterUpdate;
let bodyContentModified = false;
for (const prop of propertiesToConvert) {
const replaceRegex = new RegExp(`(?<=\\n|^)\\[${escapeRegExp(prop)}::\\s*.*?\\]`, 'g');
if (finalNoteContent.match(replaceRegex)) {
finalNoteContent = finalNoteContent.replace(replaceRegex, `\`= this.${prop}\``);
bodyContentModified = true;
console.log(` Replaced inline "${prop}" in body.`);
}
}
// 4. Save the updated note content
if (bodyContentModified || finalNoteContent !== contentAfterFrontmatterUpdate) {
await app.vault.modify(file, finalNoteContent);
console.log(`Successfully updated: ${file.path}`);
} else {
console.log(`No body changes needed for: ${file.path}`);
}
} else {
console.log(`No inline properties found in: ${file.path}. Skipping.`);
}
} catch (err) {
console.error(`Failed to process ${file.path}\n\n${err}`);
}
})
);
new Notice("Inline property conversion finished! Check your console for details.", 5000);
%>