|
module.exports = async function generateMonthly(params) { |
|
const SOURCE_DIR_ROOT = '1x Dated/11 Daily'; |
|
const SOURCE_MONTH_PATTERN = /\d{4}-\d{2}$/; |
|
const TARGET_DIR_ROOT = '1x Dated/12 Monthly'; |
|
const NUM_OF_LAST_MONTHS = 6; |
|
const MONTHLY_TEMPLATE = '0x Meta/08 Templates/dated_monthly.md'; |
|
|
|
const {app, quickAddApi: {suggester}} = params; |
|
if (!(await app.vault.adapter.exists(MONTHLY_TEMPLATE))) { |
|
new Notice(`Cannot load template: ${MONTHLY_TEMPLATE}`); |
|
return; |
|
} |
|
const templateContent = await app.vault.adapter.read(MONTHLY_TEMPLATE); |
|
|
|
const months = (await app.vault.adapter.list(SOURCE_DIR_ROOT)).folders.slice(-NUM_OF_LAST_MONTHS).reverse(); |
|
const dailyDir = await suggester(months, months); |
|
if (!dailyDir) return; |
|
|
|
const targetFileNamePrefix = dailyDir.match(SOURCE_MONTH_PATTERN)[0]; |
|
const targetDirName = `${TARGET_DIR_ROOT}/${targetFileNamePrefix}`; |
|
if (await app.vault.adapter.exists(targetDirName)) { |
|
new Notice(`Monthly folder already exists: ${targetDirName}`); |
|
return; |
|
} |
|
const markdowns = this.app.vault.getMarkdownFiles(); |
|
const dailies = markdowns.filter(f => f.path.startsWith(dailyDir)).sort((a, b) => a.name.localeCompare(b.name)); |
|
|
|
const dataPerDay = await Promise.all(dailies.map(async (dailyFile) => { |
|
const data = {}; |
|
const currentFileCache = app.metadataCache.getFileCache(dailyFile); |
|
const headings = currentFileCache.headings?.filter(h => h.level === 2); |
|
if (!headings) return data; |
|
const fileContent = await app.vault.read(dailyFile); |
|
headings.forEach((heading, index) => { |
|
const nextPos = headings?.[index+1]?.position.start.offset; |
|
const text = fileContent.slice(heading.position.end.offset, nextPos).trim(); |
|
if (text) { |
|
const sanitizedHeading = heading.heading.trim().replace(/[\\,#%&\{\}\/*<>$\'\":@]*/g, ''); |
|
data[sanitizedHeading] = `![[${dailyFile.basename}#${sanitizedHeading}]]`; |
|
} |
|
}); |
|
return data; |
|
})); |
|
const dataPerHeading = {}; |
|
dataPerDay.forEach(d => { |
|
for([heading, content] of Object.entries(d)) { |
|
let prefix = ''; |
|
if (heading in dataPerHeading) { |
|
prefix = dataPerHeading[heading] + '\n\n'; |
|
} |
|
dataPerHeading[heading] = prefix + content; |
|
} |
|
}); |
|
|
|
for([header, content] of Object.entries(dataPerHeading)) { |
|
const title = `${targetFileNamePrefix} ${header}`; |
|
const filePath = `${targetDirName}/${title}.md`; |
|
const fullContent = templateContent.replace(NAME_VALUE_REGEX, content); |
|
await app.vault.createFolder(targetDirName); |
|
const createdFile = await app.vault.create(filePath, fullContent); |
|
await replaceTemplaterTemplatesInCreatedFile(app, createdFile); |
|
console.log(`Created monthly file: ${filePath}`) |
|
} |
|
}; |
|
|
|
const NAME_VALUE_REGEX = new RegExp(/{{NAME}}|{{VALUE}}/); |
|
|
|
|
|
async function replaceTemplaterTemplatesInCreatedFile(app, file, force = false) { |
|
const templater = app.plugins.plugins["templater-obsidian"]; |
|
if (templater && (force || !templater?.settings["trigger_on_file_creation"])) { |
|
await templater.templater.overwrite_file_templates(file); |
|
} |
|
} |