Created
September 2, 2023 02:46
-
-
Save AmericanBagel/7392bb863cbc3d6ddf860aa9e8b1f620 to your computer and use it in GitHub Desktop.
Obsidian QuickAdd Script - Convert Dataview Inline YAML to YAML
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module.exports = { | |
settings: { | |
name: 'Convert Dataview Inline YAML to YAML', | |
author: 'AmericanBagel', | |
options: { | |
'Excluded Files': { | |
type: 'text', | |
defaultValue: '.git', | |
placeholder: 'A ":" seperated list of strings or regex', | |
}, | |
}, | |
}, | |
entry: async (params, settings) => { | |
const { | |
quickAddApi: { inputPrompt, suggester }, | |
} = params; | |
const metaedit = app.plugins.plugins['metaedit'].api; | |
const vault = app.vault; | |
const fs = app.vault.adapter; | |
function clearFormattingCharacters(string) { | |
return string.replace(/[*_~]/g, ''); | |
} | |
function getDataviewInlineYamlLines(string) { | |
const lines = string.split('\n'); | |
const matches = []; | |
lines.forEach((line) => { | |
// (?!`(\$=|=).*`) to exclude inline dataview code | |
if ( | |
line.match( | |
/^[*_~]{0,3}[a-zA-Z-_]+[*_~]{0,3}::.*$(?!`(\$=|=).*`)/g | |
) | |
&& line.match(/^[*_~]{0,3}[a-zA-Z-_]+[*_~]{0,3}:: (?!`(\$=|=).*`)/gm) | |
) { | |
matches.push(line); | |
} | |
}); | |
return matches; | |
} | |
function removeDataviewInlineYamlLines(string) { | |
const lines = string.split('\n'); | |
let output = []; | |
lines.forEach((line) => { | |
// (?!`(\$=|=).*`) to exclude inline dataview code | |
if ( | |
!line.match( | |
/^[*_~]{0,3}[a-zA-Z-_]+[*_~]{0,3}::.*$/g | |
) | |
) { | |
output.push(line); | |
} | |
}); | |
output = output.join('\n'); | |
output = output.replace(/%%\s%%/g, ''); | |
return output; | |
} | |
function convertToKebabCase(string) { | |
return string | |
.replace(/([a-z])([A-Z])/g, '$1-$2') | |
.replace(/[\s_]+/g, '-') | |
.toLowerCase(); | |
} | |
function parseAndAddProperty(obj, line) { | |
const arr = line.split(':: '); | |
obj[convertToKebabCase(clearFormattingCharacters(arr[0]))] = arr[1]; | |
} | |
function isTag(string) { | |
// if (string.match(/(#[^\s]+)+/g)) | |
if (string.startsWith('#')) { | |
return true; | |
} | |
} | |
function isLink(string) { | |
if (string.match(/(\[\[[^\s]+\]\])[ ]*/g)) { | |
return true; | |
} | |
} | |
function getLinkFrontmatter(key, value) { | |
console.log(value); | |
console.log(typeof value); | |
// This regex makes it only split when outside double brackets | |
return listToFrontmatter(key, value.match(/(\[\[[^\]]*\]\]|\S)+/g)); | |
} | |
function getTagFrontmatter(key, value) { | |
console.log(value); | |
console.log(typeof value); | |
return listToFrontmatter( | |
key, | |
value.split(' ').map((tag) => tag.replace(/^#/g, '')) | |
); | |
} | |
function listToFrontmatter(key, _value) { | |
console.log('listToFrontmatter'); | |
console.log('_value: ' + _value); | |
let value = _value; | |
if (typeof _value === 'string') { | |
value = _value.replace(/[ \t]+$/g, '').split(' '); | |
} | |
console.log(value); | |
let out = `${key}:\n`; | |
for (element of value) { | |
out += ` - "${element}"\n`; | |
} | |
return out; | |
} | |
function propertyToFrontmatter(key, value) { | |
return `${key}: ${value}\n`; | |
} | |
async function convertNote(note) { | |
let contents = await vault.read(note); | |
const inlineLines = getDataviewInlineYamlLines(contents); | |
inlineLines.forEach( | |
(line) => (line = clearFormattingCharacters(line)) | |
); | |
if (inlineLines.length > 0) { | |
const inlineProperties = {}; | |
inlineLines.forEach((line) => | |
parseAndAddProperty(inlineProperties, line) | |
); | |
let frontmatter = ''; | |
for (const [key, value] of Object.entries(inlineProperties)) { | |
if (isLink(value)) { | |
console.log('isLink'); | |
frontmatter += getLinkFrontmatter(key, value); | |
} else if (isTag(value)) { | |
console.log('isTag'); | |
frontmatter += getTagFrontmatter(key, value); | |
} else { | |
frontmatter += propertyToFrontmatter(key, value); | |
} | |
} | |
contents = removeDataviewInlineYamlLines(contents); | |
let sections = contents.split('---\n'); | |
if (sections.length === 1) { | |
contents = `---\n${frontmatter}---\n\n` + contents; | |
} else { | |
sections[1] = | |
sections[1].replace(/(?<=\n|^)\s/g, '') + frontmatter; | |
contents = sections.join('---\n'); | |
} | |
await fs.write(note.path, contents); | |
} | |
} | |
// Start | |
const excluded = settings['Excluded Files']?.split(':'); | |
let files = await app.vault.getMarkdownFiles(); | |
console.log(files); | |
files = files.filter((file) => { | |
// Check if any excluded substring is present in the file name | |
return !excluded.some((substring) => file.path.includes(substring)); | |
}); | |
const shouldContinue = await params.quickAddApi.yesNoPrompt( | |
'Are you sure you want to continue?', | |
'This will format ALL notes in your vault that are not excluded by the settings. This will effect ' + | |
files.length + | |
' files.' | |
); | |
files.forEach(async (file) => { | |
convertNote(file); | |
}); | |
}, | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module.exports = { | |
settings: { | |
name: 'Convert Dataview Inline YAML to YAML', | |
author: 'AmericanBagel', | |
options: { | |
'Excluded Files': { | |
type: 'text', | |
defaultValue: '.git', | |
placeholder: 'A ":" seperated list of strings or regex', | |
}, | |
}, | |
}, | |
entry: async (params, settings) => { | |
const { | |
quickAddApi: { inputPrompt, suggester }, | |
} = params; | |
const metaedit = app.plugins.plugins['metaedit'].api; | |
const vault = app.vault; | |
const fs = app.vault.adapter; | |
function clearFormattingCharacters(string) { | |
return string.replace(/[*_~]/g, ''); | |
} | |
function getDataviewInlineYamlLines(string) { | |
const lines = string.split('\n'); | |
const matches = []; | |
lines.forEach((line) => { | |
// (?!`(\$=|=).*`) to exclude inline dataview code | |
if ( | |
line.match( | |
/^[*_~]{0,3}[a-zA-Z-_]+[*_~]{0,3}::.*$(?!`(\$=|=).*`)/g | |
) | |
&& line.match(/^[*_~]{0,3}[a-zA-Z-_]+[*_~]{0,3}:: (?!`(\$=|=).*`)/gm) | |
) { | |
matches.push(line); | |
} | |
}); | |
return matches; | |
} | |
function removeDataviewInlineYamlLines(string) { | |
const lines = string.split('\n'); | |
let output = []; | |
lines.forEach((line) => { | |
// (?!`(\$=|=).*`) to exclude inline dataview code | |
if ( | |
!line.match( | |
/^[*_~]{0,3}[a-zA-Z-_]+[*_~]{0,3}::.*$/g | |
) | |
) { | |
output.push(line); | |
} | |
}); | |
output = output.join('\n'); | |
output = output.replace(/%%\s%%/g, ''); | |
return output; | |
} | |
function convertToKebabCase(string) { | |
return string | |
.replace(/([a-z])([A-Z])/g, '$1-$2') | |
.replace(/[\s_]+/g, '-') | |
.toLowerCase(); | |
} | |
function parseAndAddProperty(obj, line) { | |
const arr = line.split(':: '); | |
obj[convertToKebabCase(clearFormattingCharacters(arr[0]))] = arr[1]; | |
} | |
function isTag(string) { | |
// if (string.match(/(#[^\s]+)+/g)) | |
if (string.startsWith('#')) { | |
return true; | |
} | |
} | |
function isLink(string) { | |
if (string.match(/(\[\[[^\s]+\]\])[ ]*/g)) { | |
return true; | |
} | |
} | |
function getLinkFrontmatter(key, value) { | |
console.log(value); | |
console.log(typeof value); | |
// This regex makes it only split when outside double brackets | |
return listToFrontmatter(key, value.match(/(\[\[[^\]]*\]\]|\S)+/g)); | |
} | |
function getTagFrontmatter(key, value) { | |
console.log(value); | |
console.log(typeof value); | |
return listToFrontmatter( | |
key, | |
value.split(' ').map((tag) => tag.replace(/^#/g, '')) | |
); | |
} | |
function listToFrontmatter(key, _value) { | |
console.log('listToFrontmatter'); | |
console.log('_value: ' + _value); | |
let value = _value; | |
if (typeof _value === 'string') { | |
value = _value.replace(/[ \t]+$/g, '').split(' '); | |
} | |
console.log(value); | |
let out = `${key}:\n`; | |
for (element of value) { | |
out += ` - "${element}"\n`; | |
} | |
return out; | |
} | |
function propertyToFrontmatter(key, value) { | |
return `${key}: ${value}\n`; | |
} | |
async function convertNote(note) { | |
let contents = await vault.read(note); | |
const inlineLines = getDataviewInlineYamlLines(contents); | |
inlineLines.forEach( | |
(line) => (line = clearFormattingCharacters(line)) | |
); | |
if (inlineLines.length > 0) { | |
const inlineProperties = {}; | |
inlineLines.forEach((line) => | |
parseAndAddProperty(inlineProperties, line) | |
); | |
let frontmatter = ''; | |
for (const [key, value] of Object.entries(inlineProperties)) { | |
if (isLink(value)) { | |
console.log('isLink'); | |
frontmatter += getLinkFrontmatter(key, value); | |
} else if (isTag(value)) { | |
console.log('isTag'); | |
frontmatter += getTagFrontmatter(key, value); | |
} else { | |
frontmatter += propertyToFrontmatter(key, value); | |
} | |
} | |
contents = removeDataviewInlineYamlLines(contents); | |
let sections = contents.split('---\n'); | |
if (sections.length === 1) { | |
contents = `---\n${frontmatter}---\n\n` + contents; | |
} else { | |
sections[1] = | |
sections[1].replace(/(?<=\n|^)\s/g, '') + frontmatter; | |
contents = sections.join('---\n'); | |
} | |
await fs.write(note.path, contents); | |
} | |
} | |
// Start | |
const excluded = settings['Excluded Files']?.split(':'); | |
let files = await app.vault.getMarkdownFiles(); | |
console.log(files); | |
files = files.filter((file) => { | |
// Check if any excluded substring is present in the file name | |
return !excluded.some((substring) => file.path.includes(substring)); | |
}); | |
const shouldContinue = await params.quickAddApi.yesNoPrompt( | |
'Are you sure you want to continue?', | |
'This will format ALL notes in your vault that are not excluded by the settings. This will effect ' + | |
files.length + | |
' files.' | |
); | |
files.forEach(async (file) => { | |
convertNote(file); | |
}); | |
}, | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment