Digested-Tile 2024-09-13
Authors:: Unknown License:: Unspecified Digest Root:: 97d8600101ee #MarkdownTile
Doc Seal 0.9 - Digest & Seal - Current Document.md
<%*
// Doc Seal 0.9 for Obsidian Templater
// Version 0.9.7
/* * *Preserve Specs for Tile and Blockchain formats* * *
Tile Spec:
- Structure `###### #Digested-Tile #ds/{deformat-digest}/{YYYY-MM-DD}\nAuthors:: {authors}\nLicense:: {license}\nDigest Root:: {digestRootHash}\n###### #MarkdownTile\n{tile}\n###### #DeformattedTile\n{deformatted-tile}\n###### #EOT\n---\n`
- Location: `x/ds/tiles/{deformat-digest}.md`
- Upsert Logic: Skip (with Notice message) if `#ds/{deformat-digest}/{YYYY-MM-DD}` exists, append otherwise
Blockchain Spec:
- Structure: `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${YYYY-MM-DDTHH:mm}\n${digestTags.join(' ')}\n#ds/block/{currentBlockchainEntryDigest}`
- Location: `x/ds/blockchains/wwbc-{YY-MM}.md`
- Blockchain Logic: {previousBlockchainEntryDigest} is a hash of {YY-MM} for initial block or the BlockchainEntryDigest of the previous entry; if there are no "wwbc-....md" files yet, use the hash of the YY-MM, if there are not blocks in this months file yet, use the last #ds/block from the previous month, otherwise, use the last #ds/block in the current month's file
Script Spec:
- use Obsidian Templater scripting language for the script
- use tp.user.updateFrontMatter to update frontmatter
- 15s Notice messages about updates, 3 messages: status, tiles, and blockchain
- tp.user scripts: computeSHA256(content, length = 12); splitIntoTiles(content); ensureDirectoryExists(path); upsertToFile(filePath, header, content); updateFrontMatter(file, updates); getPreviousBlockchainEntryDigest(app, computeSHA256);
- inline helper functions: createDigestTag(hash, date); createDigestRootHash(digestTags);
*/
function createDigestTag(hash, date) {
return `#ds/${hash}/${date}`;
}
function createDigestRootHash(digestTags) {
return tp.user.computeSHA256(digestTags.join(' '), 12);
}
// Main function
async function dsTaggerChain() {
const version = "0.9.7";
const startTime = Date.now();
const currentDate = new Date().toISOString().split('T')[0];
const currentTimestamp = new Date().toISOString();
console.log(`[${currentDate}] DS Tagger Chain v${version} started`);
// Configuration
const tileDirectoryPath = "x/ds/tiles";
const blockchainDirectoryPath = "x/ds/blockchains";
try {
// Ensure directories exist
await tp.user.ensureDirectoryExists(tileDirectoryPath);
await tp.user.ensureDirectoryExists(blockchainDirectoryPath);
let content = tp.file.content;
const fileName = tp.file.title;
const currentFile = tp.file.find_tfile(fileName);
if (typeof content !== 'string') {
throw new Error('Received non-string content');
}
const authors = tp.frontmatter.authors || 'Unknown';
const license = tp.frontmatter.license || 'Unspecified';
console.log(`[${currentDate}] Authors extracted: ${authors}`);
console.log(`[${currentDate}] License extracted: ${license}`);
console.log(`[${currentDate}] File content length: ${content.length} characters`);
const { frontmatter, tiles } = tp.user.splitIntoTiles(content);
console.log(`[${currentDate}] Number of tiles: ${tiles.length}`);
let processedTiles = [];
let digestedTiles = 0;
let nonDigestedTiles = 0;
let updatedTiles = 0;
let digestTags = [];
let tileFilesUpdated = {};
for (let i = 0; i < tiles.length; i++) {
let tile = tiles[i];
const tileHash = tp.user.computeSHA256(tile);
console.log(`\n[${currentDate}] Processing tile ${i + 1} (${tileHash})`);
let existingDigestMatch = tile.match(/\s*(#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2})/);
let existingDigest = existingDigestMatch ? existingDigestMatch[1] : null;
console.log(`Existing Digest Tag: ${existingDigest || 'None'}`);
let cleanTile = tile.replace(/\s*#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2}/, '').trim();
let { deformattedContent, charactersRemoved } = tp.user.deformatTile(cleanTile);
let digest = tp.user.computeSHA256(deformattedContent);
let digestTag = createDigestTag(digest, currentDate);
console.log(`New Digest Tag: ${digestTag}`);
if (existingDigest && existingDigest.includes(digest)) {
console.log(`Content unchanged for tile ${tileHash}. Keeping existing Digest Tag.`);
digestTag = existingDigest;
nonDigestedTiles++;
// new Notice(`Skipping unchanged tile: ${digestTag}`, 15000);
} else {
console.log(`Content changed or new for tile ${tileHash}. Updating Digest Tag.`);
if (existingDigest) {
updatedTiles++;
} else {
digestedTiles++;
}
}
let processedTile = `${cleanTile} ${digestTag}`;
processedTiles.push(processedTile);
digestTags.push(digestTag);
console.log(`Tile ${tileHash} stats: Characters removed: ${charactersRemoved}`);
const tileFilePath = `${tileDirectoryPath}/${digest}.md`;
const digestRootHash = createDigestRootHash(digestTags);
const tileFileContent = `###### #Digested-Tile ${digestTag}
Authors:: ${authors}
License:: ${license}
Digest Root:: ${digestRootHash}
###### #MarkdownTile
${cleanTile}
###### #DeformattedTile
${deformattedContent}
###### #EOT
---`;
const { status: tileUpdateStatus, file: tileFile } = await tp.user.upsertToFile(tileFilePath, `###### #Digested-Tile ${digestTag}`, tileFileContent);
tileFilesUpdated[tileFilePath] = tileUpdateStatus;
// Update tile file frontmatter
if (tileFile) {
await tp.user.updateFrontMatter(tileFile, {
aliases: [digestTag],
authors: authors,
license: license,
'digest-root': digestRootHash
});
}
}
let result = frontmatter + '\n' + processedTiles.join('\n\n');
const yearMonth = currentDate.slice(2, 7);
let digestRootHash = createDigestRootHash(digestTags);
console.log(`\n[${currentDate}] Digest Root hash created: ${digestRootHash}`);
// Modify the current file content
await app.vault.modify(currentFile, result);
// Update current file frontmatter using tp.user.updateFrontMatter after modifying content
await tp.user.updateFrontMatter(currentFile, {
aliases: [`#ds/root/${digestRootHash}`],
'blockchain_last_digest_root': `#ds/root/${digestRootHash}`,
'blockchain_digest_timestamp': currentTimestamp,
'blockchain_file': `[[wwbc-${yearMonth}]]`
});
// Update blockchain file
const blockchainFilePath = `${blockchainDirectoryPath}/wwbc-${yearMonth}.md`;
const previousBlockchainEntryDigest = await tp.user.getPreviousBlockchainEntryDigest(app, blockchainDirectoryPath, tp.user.computeSHA256);
console.log(`Previous blockchain entry digest: ${previousBlockchainEntryDigest}`);
// Create the blockchain content without the final hash
const blockchainContentWithoutHash = `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}
${digestTags.join(' ')}`.trim();
// Generate the hash for the blockchain entry
const blockchainEntryHash = tp.user.computeSHA256(blockchainContentWithoutHash);
// Create the final blockchain content
const blockchainFileContent = `${blockchainContentWithoutHash}
#ds/block/${blockchainEntryHash}`;
const { status: blockchainUpdateStatus, file: blockchainFile } = await tp.user.upsertToFile(blockchainFilePath, `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}`, blockchainFileContent);
if (blockchainFile) {
await tp.user.updateFrontMatter(blockchainFile, {
cssclasses: [`locked`]
});
}
if (blockchainUpdateStatus === 'updated') {
console.log(`Updated blockchain file: ${blockchainFilePath}`);
} else {
console.log(`Blockchain file already up to date: ${blockchainFilePath}`);
}
const endTime = Date.now();
const runtime = ((endTime - startTime) / 1000).toFixed(2);
console.log(`\n[${currentDate}] DS Tagger Chain process completed successfully`);
const statusMessage = `DS Tagger Chain v${version} completed:
Runtime: ${runtime}s
#ds/root/${digestRootHash}
Tiles processed: ${tiles.length}
Tiles digested: ${digestedTiles}
Tiles not digested: ${nonDigestedTiles}
Tiles updated: ${updatedTiles}
Date: ${currentDate}`;
const tileFilesMessage = `Tile files updated (BUGY):
${Object.entries(tileFilesUpdated).map(([file, status]) => `${file}: ${status}`).join('\n')}`;
const blockchainEntryMessage = `Blockchain entry (${blockchainUpdateStatus}):
${blockchainFileContent}`;
console.log(statusMessage);
console.log(tileFilesMessage);
console.log(blockchainEntryMessage);
new Notice(statusMessage, 15000);
new Notice(tileFilesMessage, 15000);
new Notice(blockchainEntryMessage, 15000);
} catch (error) {
console.error(`[${currentDate}] An error occurred:`, error);
new Notice(`Error in DS Tagger Chain v${version}: ${error.message}. Check console for details.`, 15000);
}
}
// Run the script and output the result
await dsTaggerChain();
%>DeformattedTile
Doc Seal 0.9 - Digest & Seal - Current Document.md
<%*
// Doc Seal 0.9 for Obsidian Templater
// Version 0.9.7
/* * *Preserve Specs for Tile and Blockchain formats* * *
Tile Spec:
- Structure `###### #Digested-Tile #ds/{deformat-digest}/{YYYY-MM-DD}\nAuthors:: {authors}\nLicense:: {license}\nDigest Root:: {digestRootHash}\n###### #MarkdownTile\n{tile}\n###### #DeformattedTile\n{deformatted-tile}\n###### #EOT\n---\n`
- Location: `x/ds/tiles/{deformat-digest}.md`
- Upsert Logic: Skip (with Notice message) if `#ds/{deformat-digest}/{YYYY-MM-DD}` exists, append otherwise
Blockchain Spec:
- Structure: `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${YYYY-MM-DDTHH:mm}\n${digestTags.join(' ')}\n#ds/block/{currentBlockchainEntryDigest}`
- Location: `x/ds/blockchains/wwbc-{YY-MM}.md`
- Blockchain Logic: {previousBlockchainEntryDigest} is a hash of {YY-MM} for initial block or the BlockchainEntryDigest of the previous entry; if there are no "wwbc-....md" files yet, use the hash of the YY-MM, if there are not blocks in this months file yet, use the last #ds/block from the previous month, otherwise, use the last #ds/block in the current month's file
Script Spec:
- use Obsidian Templater scripting language for the script
- use tp.user.updateFrontMatter to update frontmatter
- 15s Notice messages about updates, 3 messages: status, tiles, and blockchain
- tp.user scripts: computeSHA256(content, length = 12); splitIntoTiles(content); ensureDirectoryExists(path); upsertToFile(filePath, header, content); updateFrontMatter(file, updates); getPreviousBlockchainEntryDigest(app, computeSHA256);
- inline helper functions: createDigestTag(hash, date); createDigestRootHash(digestTags);
*/
function createDigestTag(hash, date) {
return `#ds/${hash}/${date}`;
}
function createDigestRootHash(digestTags) {
return tp.user.computeSHA256(digestTags.join(' '), 12);
}
// Main function
async function dsTaggerChain() {
const version = "0.9.7";
const startTime = Date.now();
const currentDate = new Date().toISOString().split('T')[0];
const currentTimestamp = new Date().toISOString();
console.log(`[${currentDate}] DS Tagger Chain v${version} started`);
// Configuration
const tileDirectoryPath = "x/ds/tiles";
const blockchainDirectoryPath = "x/ds/blockchains";
try {
// Ensure directories exist
await tp.user.ensureDirectoryExists(tileDirectoryPath);
await tp.user.ensureDirectoryExists(blockchainDirectoryPath);
let content = tp.file.content;
const fileName = tp.file.title;
const currentFile = tp.file.find_tfile(fileName);
if (typeof content !== 'string') {
throw new Error('Received non-string content');
}
const authors = tp.frontmatter.authors || 'Unknown';
const license = tp.frontmatter.license || 'Unspecified';
console.log(`[${currentDate}] Authors extracted: ${authors}`);
console.log(`[${currentDate}] License extracted: ${license}`);
console.log(`[${currentDate}] File content length: ${content.length} characters`);
const { frontmatter, tiles } = tp.user.splitIntoTiles(content);
console.log(`[${currentDate}] Number of tiles: ${tiles.length}`);
let processedTiles = [];
let digestedTiles = 0;
let nonDigestedTiles = 0;
let updatedTiles = 0;
let digestTags = [];
let tileFilesUpdated = {};
for (let i = 0; i < tiles.length; i++) {
let tile = tiles[i];
const tileHash = tp.user.computeSHA256(tile);
console.log(`\n[${currentDate}] Processing tile ${i + 1} (${tileHash})`);
let existingDigestMatch = tile.match(/\s*(#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2})/);
let existingDigest = existingDigestMatch ? existingDigestMatch[1] : null;
console.log(`Existing Digest Tag: ${existingDigest || 'None'}`);
let cleanTile = tile.replace(/\s*#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2}/, '').trim();
let { deformattedContent, charactersRemoved } = tp.user.deformatTile(cleanTile);
let digest = tp.user.computeSHA256(deformattedContent);
let digestTag = createDigestTag(digest, currentDate);
console.log(`New Digest Tag: ${digestTag}`);
if (existingDigest && existingDigest.includes(digest)) {
console.log(`Content unchanged for tile ${tileHash}. Keeping existing Digest Tag.`);
digestTag = existingDigest;
nonDigestedTiles++;
// new Notice(`Skipping unchanged tile: ${digestTag}`, 15000);
} else {
console.log(`Content changed or new for tile ${tileHash}. Updating Digest Tag.`);
if (existingDigest) {
updatedTiles++;
} else {
digestedTiles++;
}
}
let processedTile = `${cleanTile} ${digestTag}`;
processedTiles.push(processedTile);
digestTags.push(digestTag);
console.log(`Tile ${tileHash} stats: Characters removed: ${charactersRemoved}`);
const tileFilePath = `${tileDirectoryPath}/${digest}.md`;
const digestRootHash = createDigestRootHash(digestTags);
const tileFileContent = `###### #Digested-Tile ${digestTag}
Authors:: ${authors}
License:: ${license}
Digest Root:: ${digestRootHash}
#MarkdownTile
${cleanTile}
#DeformattedTile
${deformattedContent}
#EOT
---`;
const { status: tileUpdateStatus, file: tileFile } = await tp.user.upsertToFile(tileFilePath, `###### #Digested-Tile ${digestTag}`, tileFileContent);
tileFilesUpdated[tileFilePath] = tileUpdateStatus;
// Update tile file frontmatter
if (tileFile) {
await tp.user.updateFrontMatter(tileFile, {
aliases: [digestTag],
authors: authors,
license: license,
'digest-root': digestRootHash
});
}
}
let result = frontmatter + '\n' + processedTiles.join('\n\n');
const yearMonth = currentDate.slice(2, 7);
let digestRootHash = createDigestRootHash(digestTags);
console.log(`\n[${currentDate}] Digest Root hash created: ${digestRootHash}`);
// Modify the current file content
await app.vault.modify(currentFile, result);
// Update current file frontmatter using tp.user.updateFrontMatter after modifying content
await tp.user.updateFrontMatter(currentFile, {
aliases: [`#ds/root/${digestRootHash}`],
'blockchain_last_digest_root': `#ds/root/${digestRootHash}`,
'blockchain_digest_timestamp': currentTimestamp,
'blockchain_file': `[[wwbc-${yearMonth}]]`
});
// Update blockchain file
const blockchainFilePath = `${blockchainDirectoryPath}/wwbc-${yearMonth}.md`;
const previousBlockchainEntryDigest = await tp.user.getPreviousBlockchainEntryDigest(app, blockchainDirectoryPath, tp.user.computeSHA256);
console.log(`Previous blockchain entry digest: ${previousBlockchainEntryDigest}`);
// Create the blockchain content without the final hash
const blockchainContentWithoutHash = `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}
${digestTags.join(' ')}`.trim();
// Generate the hash for the blockchain entry
const blockchainEntryHash = tp.user.computeSHA256(blockchainContentWithoutHash);
// Create the final blockchain content
const blockchainFileContent = `${blockchainContentWithoutHash}
#ds/block/${blockchainEntryHash}`;
const { status: blockchainUpdateStatus, file: blockchainFile } = await tp.user.upsertToFile(blockchainFilePath, `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}`, blockchainFileContent);
if (blockchainFile) {
await tp.user.updateFrontMatter(blockchainFile, {
cssclasses: [`locked`]
});
}
if (blockchainUpdateStatus === 'updated') {
console.log(`Updated blockchain file: ${blockchainFilePath}`);
} else {
console.log(`Blockchain file already up to date: ${blockchainFilePath}`);
}
const endTime = Date.now();
const runtime = ((endTime - startTime) / 1000).toFixed(2);
console.log(`\n[${currentDate}] DS Tagger Chain process completed successfully`);
const statusMessage = `DS Tagger Chain v${version} completed:
Runtime: ${runtime}s
#ds/root/${digestRootHash}
Tiles processed: ${tiles.length}
Tiles digested: ${digestedTiles}
Tiles not digested: ${nonDigestedTiles}
Tiles updated: ${updatedTiles}
Date: ${currentDate}`;
const tileFilesMessage = `Tile files updated (BUGY):
${Object.entries(tileFilesUpdated).map(([file, status]) => `${file}: ${status}`).join('\n')}`;
const blockchainEntryMessage = `Blockchain entry (${blockchainUpdateStatus}):
${blockchainFileContent}`;
console.log(statusMessage);
console.log(tileFilesMessage);
console.log(blockchainEntryMessage);
new Notice(statusMessage, 15000);
new Notice(tileFilesMessage, 15000);
new Notice(blockchainEntryMessage, 15000);
} catch (error) {
console.error(`[${currentDate}] An error occurred:`, error);
new Notice(`Error in DS Tagger Chain v${version}: ${error.message}. Check console for details.`, 15000);
}
}
// Run the script and output the result
await dsTaggerChain();
%>EOT
DeformattedTile Doc Seal 0.9 - Digest & Seal - Current Document.md
<%*
// Doc Seal 0.9 for Obsidian Templater
// Version 0.9.7
/* * *Preserve Specs for Tile and Blockchain formats* * *
Tile Spec:
- Structure `###### #Digested-Tile #ds/{deformat-digest}/{YYYY-MM-DD}\nAuthors:: {authors}\nLicense:: {license}\nDigest Root:: {digestRootHash}\n###### #MarkdownTile\n{tile}\n###### #DeformattedTile\n{deformatted-tile}\n###### #EOT\n---\n`
- Location: `x/ds/tiles/{deformat-digest}.md`
- Upsert Logic: Skip (with Notice message) if `#ds/{deformat-digest}/{YYYY-MM-DD}` exists, append otherwise
Blockchain Spec:
- Structure: `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${YYYY-MM-DDTHH:mm}\n${digestTags.join(' ')}\n#ds/block/{currentBlockchainEntryDigest}`
- Location: `x/ds/blockchains/wwbc-{YY-MM}.md`
- Blockchain Logic: {previousBlockchainEntryDigest} is a hash of {YY-MM} for initial block or the BlockchainEntryDigest of the previous entry; if there are no "wwbc-....md" files yet, use the hash of the YY-MM, if there are not blocks in this months file yet, use the last #ds/block from the previous month, otherwise, use the last #ds/block in the current month's file
Script Spec:
- use Obsidian Templater scripting language for the script
- use tp.user.updateFrontMatter to update frontmatter
- 15s Notice messages about updates, 3 messages: status, tiles, and blockchain
- tp.user scripts: computeSHA256(content, length = 12); splitIntoTiles(content); ensureDirectoryExists(path); upsertToFile(filePath, header, content); updateFrontMatter(file, updates); getPreviousBlockchainEntryDigest(app, computeSHA256);
- inline helper functions: createDigestTag(hash, date); createDigestRootHash(digestTags);
*/
function createDigestTag(hash, date) {
return `#ds/${hash}/${date}`;
}
function createDigestRootHash(digestTags) {
return tp.user.computeSHA256(digestTags.join(' '), 12);
}
// Main function
async function dsTaggerChain() {
const version = "0.9.7";
const startTime = Date.now();
const currentDate = new Date().toISOString().split('T')[0];
const currentTimestamp = new Date().toISOString();
console.log(`[${currentDate}] DS Tagger Chain v${version} started`);
// Configuration
const tileDirectoryPath = "x/ds/tiles";
const blockchainDirectoryPath = "x/ds/blockchains";
try {
// Ensure directories exist
await tp.user.ensureDirectoryExists(tileDirectoryPath);
await tp.user.ensureDirectoryExists(blockchainDirectoryPath);
let content = tp.file.content;
const fileName = tp.file.title;
const currentFile = tp.file.find_tfile(fileName);
if (typeof content !== 'string') {
throw new Error('Received non-string content');
}
const authors = tp.frontmatter.authors || 'Unknown';
const license = tp.frontmatter.license || 'Unspecified';
console.log(`[${currentDate}] Authors extracted: ${authors}`);
console.log(`[${currentDate}] License extracted: ${license}`);
console.log(`[${currentDate}] File content length: ${content.length} characters`);
const { frontmatter, tiles } = tp.user.splitIntoTiles(content);
console.log(`[${currentDate}] Number of tiles: ${tiles.length}`);
let processedTiles = [];
let digestedTiles = 0;
let nonDigestedTiles = 0;
let updatedTiles = 0;
let digestTags = [];
let tileFilesUpdated = {};
for (let i = 0; i < tiles.length; i++) {
let tile = tiles[i];
const tileHash = tp.user.computeSHA256(tile);
console.log(`\n[${currentDate}] Processing tile ${i + 1} (${tileHash})`);
let existingDigestMatch = tile.match(/\s*(#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2})/);
let existingDigest = existingDigestMatch ? existingDigestMatch[1] : null;
console.log(`Existing Digest Tag: ${existingDigest || 'None'}`);
let cleanTile = tile.replace(/\s*#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2}/, '').trim();
let { deformattedContent, charactersRemoved } = tp.user.deformatTile(cleanTile);
let digest = tp.user.computeSHA256(deformattedContent);
let digestTag = createDigestTag(digest, currentDate);
console.log(`New Digest Tag: ${digestTag}`);
if (existingDigest && existingDigest.includes(digest)) {
console.log(`Content unchanged for tile ${tileHash}. Keeping existing Digest Tag.`);
digestTag = existingDigest;
nonDigestedTiles++;
// new Notice(`Skipping unchanged tile: ${digestTag}`, 15000);
} else {
console.log(`Content changed or new for tile ${tileHash}. Updating Digest Tag.`);
if (existingDigest) {
updatedTiles++;
} else {
digestedTiles++;
}
}
let processedTile = `${cleanTile} ${digestTag}`;
processedTiles.push(processedTile);
digestTags.push(digestTag);
console.log(`Tile ${tileHash} stats: Characters removed: ${charactersRemoved}`);
const tileFilePath = `${tileDirectoryPath}/${digest}.md`;
const digestRootHash = createDigestRootHash(digestTags);
const tileFileContent = `###### #Digested-Tile ${digestTag}
Authors:: ${authors}
License:: ${license}
Digest Root:: ${digestRootHash}
#MarkdownTile
${cleanTile}
#DeformattedTile
${deformattedContent}
#EOT
---`;
const { status: tileUpdateStatus, file: tileFile } = await tp.user.upsertToFile(tileFilePath, `###### #Digested-Tile ${digestTag}`, tileFileContent);
tileFilesUpdated[tileFilePath] = tileUpdateStatus;
// Update tile file frontmatter
if (tileFile) {
await tp.user.updateFrontMatter(tileFile, {
aliases: [digestTag],
authors: authors,
license: license,
'digest-root': digestRootHash
});
}
}
let result = frontmatter + '\n' + processedTiles.join('\n\n');
const yearMonth = currentDate.slice(2, 7);
let digestRootHash = createDigestRootHash(digestTags);
console.log(`\n[${currentDate}] Digest Root hash created: ${digestRootHash}`);
// Modify the current file content
await app.vault.modify(currentFile, result);
// Update current file frontmatter using tp.user.updateFrontMatter after modifying content
await tp.user.updateFrontMatter(currentFile, {
aliases: [`#ds/root/${digestRootHash}`],
'blockchain_last_digest_root': `#ds/root/${digestRootHash}`,
'blockchain_digest_timestamp': currentTimestamp,
'blockchain_file': `[[wwbc-${yearMonth}]]`
});
// Update blockchain file
const blockchainFilePath = `${blockchainDirectoryPath}/wwbc-${yearMonth}.md`;
const previousBlockchainEntryDigest = await tp.user.getPreviousBlockchainEntryDigest(app, blockchainDirectoryPath, tp.user.computeSHA256);
console.log(`Previous blockchain entry digest: ${previousBlockchainEntryDigest}`);
// Create the blockchain content without the final hash
const blockchainContentWithoutHash = `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}
${digestTags.join(' ')}`.trim();
// Generate the hash for the blockchain entry
const blockchainEntryHash = tp.user.computeSHA256(blockchainContentWithoutHash);
// Create the final blockchain content
const blockchainFileContent = `${blockchainContentWithoutHash}
#ds/block/${blockchainEntryHash}`;
const { status: blockchainUpdateStatus, file: blockchainFile } = await tp.user.upsertToFile(blockchainFilePath, `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}`, blockchainFileContent);
if (blockchainFile) {
await tp.user.updateFrontMatter(blockchainFile, {
cssclasses: [`locked`]
});
}
if (blockchainUpdateStatus === 'updated') {
console.log(`Updated blockchain file: ${blockchainFilePath}`);
} else {
console.log(`Blockchain file already up to date: ${blockchainFilePath}`);
}
const endTime = Date.now();
const runtime = ((endTime - startTime) / 1000).toFixed(2);
console.log(`\n[${currentDate}] DS Tagger Chain process completed successfully`);
const statusMessage = `DS Tagger Chain v${version} completed:
Runtime: ${runtime}s
#ds/root/${digestRootHash}
Tiles processed: ${tiles.length}
Tiles digested: ${digestedTiles}
Tiles not digested: ${nonDigestedTiles}
Tiles updated: ${updatedTiles}
Date: ${currentDate}`;
const tileFilesMessage = `Tile files updated (BUGY):
${Object.entries(tileFilesUpdated).map(([file, status]) => `${file}: ${status}`).join('\n')}`;
const blockchainEntryMessage = `Blockchain entry (${blockchainUpdateStatus}):
${blockchainFileContent}`;
console.log(statusMessage);
console.log(tileFilesMessage);
console.log(blockchainEntryMessage);
new Notice(statusMessage, 15000);
new Notice(tileFilesMessage, 15000);
new Notice(blockchainEntryMessage, 15000);
} catch (error) {
console.error(`[${currentDate}] An error occurred:`, error);
new Notice(`Error in DS Tagger Chain v${version}: ${error.message}. Check console for details.`, 15000);
}
}
// Run the script and output the result
await dsTaggerChain();
%>DeformattedTile Doc Seal 0.9 - Digest & Seal - Current Document.md
<%*
// Doc Seal 0.9 for Obsidian Templater
// Version 0.9.7
/* * *Preserve Specs for Tile and Blockchain formats* * *
Tile Spec:
- Structure `###### #Digested-Tile #ds/{deformat-digest}/{YYYY-MM-DD}\nAuthors:: {authors}\nLicense:: {license}\nDigest Root:: {digestRootHash}\n###### #MarkdownTile\n{tile}\n###### #DeformattedTile\n{deformatted-tile}\n###### #EOT\n---\n`
- Location: `x/ds/tiles/{deformat-digest}.md`
- Upsert Logic: Skip (with Notice message) if `#ds/{deformat-digest}/{YYYY-MM-DD}` exists, append otherwise
Blockchain Spec:
- Structure: `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${YYYY-MM-DDTHH:mm}\n${digestTags.join(' ')}\n#ds/block/{currentBlockchainEntryDigest}`
- Location: `x/ds/blockchains/wwbc-{YY-MM}.md`
- Blockchain Logic: {previousBlockchainEntryDigest} is a hash of {YY-MM} for initial block or the BlockchainEntryDigest of the previous entry; if there are no "wwbc-....md" files yet, use the hash of the YY-MM, if there are not blocks in this months file yet, use the last #ds/block from the previous month, otherwise, use the last #ds/block in the current month's file
Script Spec:
- use Obsidian Templater scripting language for the script
- use tp.user.updateFrontMatter to update frontmatter
- 15s Notice messages about updates, 3 messages: status, tiles, and blockchain
- tp.user scripts: computeSHA256(content, length = 12); splitIntoTiles(content); ensureDirectoryExists(path); upsertToFile(filePath, header, content); updateFrontMatter(file, updates); getPreviousBlockchainEntryDigest(app, computeSHA256);
- inline helper functions: createDigestTag(hash, date); createDigestRootHash(digestTags);
*/
function createDigestTag(hash, date) {
return `#ds/${hash}/${date}`;
}
function createDigestRootHash(digestTags) {
return tp.user.computeSHA256(digestTags.join(' '), 12);
}
// Main function
async function dsTaggerChain() {
const version = "0.9.7";
const startTime = Date.now();
const currentDate = new Date().toISOString().split('T')[0];
const currentTimestamp = new Date().toISOString();
console.log(`[${currentDate}] DS Tagger Chain v${version} started`);
// Configuration
const tileDirectoryPath = "x/ds/tiles";
const blockchainDirectoryPath = "x/ds/blockchains";
try {
// Ensure directories exist
await tp.user.ensureDirectoryExists(tileDirectoryPath);
await tp.user.ensureDirectoryExists(blockchainDirectoryPath);
let content = tp.file.content;
const fileName = tp.file.title;
const currentFile = tp.file.find_tfile(fileName);
if (typeof content !== 'string') {
throw new Error('Received non-string content');
}
const authors = tp.frontmatter.authors || 'Unknown';
const license = tp.frontmatter.license || 'Unspecified';
console.log(`[${currentDate}] Authors extracted: ${authors}`);
console.log(`[${currentDate}] License extracted: ${license}`);
console.log(`[${currentDate}] File content length: ${content.length} characters`);
const { frontmatter, tiles } = tp.user.splitIntoTiles(content);
console.log(`[${currentDate}] Number of tiles: ${tiles.length}`);
let processedTiles = [];
let digestedTiles = 0;
let nonDigestedTiles = 0;
let updatedTiles = 0;
let digestTags = [];
let tileFilesUpdated = {};
for (let i = 0; i < tiles.length; i++) {
let tile = tiles[i];
const tileHash = tp.user.computeSHA256(tile);
console.log(`\n[${currentDate}] Processing tile ${i + 1} (${tileHash})`);
let existingDigestMatch = tile.match(/\s*(#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2})/);
let existingDigest = existingDigestMatch ? existingDigestMatch[1] : null;
console.log(`Existing Digest Tag: ${existingDigest || 'None'}`);
let cleanTile = tile.replace(/\s*#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2}/, '').trim();
let { deformattedContent, charactersRemoved } = tp.user.deformatTile(cleanTile);
let digest = tp.user.computeSHA256(deformattedContent);
let digestTag = createDigestTag(digest, currentDate);
console.log(`New Digest Tag: ${digestTag}`);
if (existingDigest && existingDigest.includes(digest)) {
console.log(`Content unchanged for tile ${tileHash}. Keeping existing Digest Tag.`);
digestTag = existingDigest;
nonDigestedTiles++;
// new Notice(`Skipping unchanged tile: ${digestTag}`, 15000);
} else {
console.log(`Content changed or new for tile ${tileHash}. Updating Digest Tag.`);
if (existingDigest) {
updatedTiles++;
} else {
digestedTiles++;
}
}
let processedTile = `${cleanTile} ${digestTag}`;
processedTiles.push(processedTile);
digestTags.push(digestTag);
console.log(`Tile ${tileHash} stats: Characters removed: ${charactersRemoved}`);
const tileFilePath = `${tileDirectoryPath}/${digest}.md`;
const digestRootHash = createDigestRootHash(digestTags);
const tileFileContent = `###### #Digested-Tile ${digestTag}
Authors:: ${authors}
License:: ${license}
Digest Root:: ${digestRootHash}
#MarkdownTile
${cleanTile}
#DeformattedTile
${deformattedContent}
#EOT
---`;
const { status: tileUpdateStatus, file: tileFile } = await tp.user.upsertToFile(tileFilePath, `###### #Digested-Tile ${digestTag}`, tileFileContent);
tileFilesUpdated[tileFilePath] = tileUpdateStatus;
// Update tile file frontmatter
if (tileFile) {
await tp.user.updateFrontMatter(tileFile, {
aliases: [digestTag],
authors: authors,
license: license,
'digest-root': digestRootHash
});
}
}
let result = frontmatter + '\n' + processedTiles.join('\n\n');
const yearMonth = currentDate.slice(2, 7);
let digestRootHash = createDigestRootHash(digestTags);
console.log(`\n[${currentDate}] Digest Root hash created: ${digestRootHash}`);
// Modify the current file content
await app.vault.modify(currentFile, result);
// Update current file frontmatter using tp.user.updateFrontMatter after modifying content
await tp.user.updateFrontMatter(currentFile, {
aliases: [`#ds/root/${digestRootHash}`],
'blockchain_last_digest_root': `#ds/root/${digestRootHash}`,
'blockchain_digest_timestamp': currentTimestamp,
'blockchain_file': `[[wwbc-${yearMonth}]]`
});
// Update blockchain file
const blockchainFilePath = `${blockchainDirectoryPath}/wwbc-${yearMonth}.md`;
const previousBlockchainEntryDigest = await tp.user.getPreviousBlockchainEntryDigest(app, blockchainDirectoryPath, tp.user.computeSHA256);
console.log(`Previous blockchain entry digest: ${previousBlockchainEntryDigest}`);
// Create the blockchain content without the final hash
const blockchainContentWithoutHash = `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}
${digestTags.join(' ')}`.trim();
// Generate the hash for the blockchain entry
const blockchainEntryHash = tp.user.computeSHA256(blockchainContentWithoutHash);
// Create the final blockchain content
const blockchainFileContent = `${blockchainContentWithoutHash}
#ds/block/${blockchainEntryHash}`;
const { status: blockchainUpdateStatus, file: blockchainFile } = await tp.user.upsertToFile(blockchainFilePath, `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}`, blockchainFileContent);
if (blockchainFile) {
await tp.user.updateFrontMatter(blockchainFile, {
cssclasses: [`locked`]
});
}
if (blockchainUpdateStatus === 'updated') {
console.log(`Updated blockchain file: ${blockchainFilePath}`);
} else {
console.log(`Blockchain file already up to date: ${blockchainFilePath}`);
}
const endTime = Date.now();
const runtime = ((endTime - startTime) / 1000).toFixed(2);
console.log(`\n[${currentDate}] DS Tagger Chain process completed successfully`);
const statusMessage = `DS Tagger Chain v${version} completed:
Runtime: ${runtime}s
#ds/root/${digestRootHash}
Tiles processed: ${tiles.length}
Tiles digested: ${digestedTiles}
Tiles not digested: ${nonDigestedTiles}
Tiles updated: ${updatedTiles}
Date: ${currentDate}`;
const tileFilesMessage = `Tile files updated (BUGY):
${Object.entries(tileFilesUpdated).map(([file, status]) => `${file}: ${status}`).join('\n')}`;
const blockchainEntryMessage = `Blockchain entry (${blockchainUpdateStatus}):
${blockchainFileContent}`;
console.log(statusMessage);
console.log(tileFilesMessage);
console.log(blockchainEntryMessage);
new Notice(statusMessage, 15000);
new Notice(tileFilesMessage, 15000);
new Notice(blockchainEntryMessage, 15000);
} catch (error) {
console.error(`[${currentDate}] An error occurred:`, error);
new Notice(`Error in DS Tagger Chain v${version}: ${error.message}. Check console for details.`, 15000);
}
}
// Run the script and output the result
await dsTaggerChain();
%>EOT
EOT
DeformattedTile Doc Seal 0.9 - Digest & Seal - Current Document.md
<%*
// Doc Seal 0.9 for Obsidian Templater
// Version 0.9.7
/* * *Preserve Specs for Tile and Blockchain formats* * *
Tile Spec:
- Structure `###### #Digested-Tile #ds/{deformat-digest}/{YYYY-MM-DD}\nAuthors:: {authors}\nLicense:: {license}\nDigest Root:: {digestRootHash}\n###### #MarkdownTile\n{tile}\n###### #DeformattedTile\n{deformatted-tile}\n###### #EOT\n---\n`
- Location: `x/ds/tiles/{deformat-digest}.md`
- Upsert Logic: Skip (with Notice message) if `#ds/{deformat-digest}/{YYYY-MM-DD}` exists, append otherwise
Blockchain Spec:
- Structure: `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${YYYY-MM-DDTHH:mm}\n${digestTags.join(' ')}\n#ds/block/{currentBlockchainEntryDigest}`
- Location: `x/ds/blockchains/wwbc-{YY-MM}.md`
- Blockchain Logic: {previousBlockchainEntryDigest} is a hash of {YY-MM} for initial block or the BlockchainEntryDigest of the previous entry; if there are no "wwbc-....md" files yet, use the hash of the YY-MM, if there are not blocks in this months file yet, use the last #ds/block from the previous month, otherwise, use the last #ds/block in the current month's file
Script Spec:
- use Obsidian Templater scripting language for the script
- use tp.user.updateFrontMatter to update frontmatter
- 15s Notice messages about updates, 3 messages: status, tiles, and blockchain
- tp.user scripts: computeSHA256(content, length = 12); splitIntoTiles(content); ensureDirectoryExists(path); upsertToFile(filePath, header, content); updateFrontMatter(file, updates); getPreviousBlockchainEntryDigest(app, computeSHA256);
- inline helper functions: createDigestTag(hash, date); createDigestRootHash(digestTags);
*/
function createDigestTag(hash, date) {
return `#ds/${hash}/${date}`;
}
function createDigestRootHash(digestTags) {
return tp.user.computeSHA256(digestTags.join(' '), 12);
}
// Main function
async function dsTaggerChain() {
const version = "0.9.7";
const startTime = Date.now();
const currentDate = new Date().toISOString().split('T')[0];
const currentTimestamp = new Date().toISOString();
console.log(`[${currentDate}] DS Tagger Chain v${version} started`);
// Configuration
const tileDirectoryPath = "x/ds/tiles";
const blockchainDirectoryPath = "x/ds/blockchains";
try {
// Ensure directories exist
await tp.user.ensureDirectoryExists(tileDirectoryPath);
await tp.user.ensureDirectoryExists(blockchainDirectoryPath);
let content = tp.file.content;
const fileName = tp.file.title;
const currentFile = tp.file.find_tfile(fileName);
if (typeof content !== 'string') {
throw new Error('Received non-string content');
}
const authors = tp.frontmatter.authors || 'Unknown';
const license = tp.frontmatter.license || 'Unspecified';
console.log(`[${currentDate}] Authors extracted: ${authors}`);
console.log(`[${currentDate}] License extracted: ${license}`);
console.log(`[${currentDate}] File content length: ${content.length} characters`);
const { frontmatter, tiles } = tp.user.splitIntoTiles(content);
console.log(`[${currentDate}] Number of tiles: ${tiles.length}`);
let processedTiles = [];
let digestedTiles = 0;
let nonDigestedTiles = 0;
let updatedTiles = 0;
let digestTags = [];
let tileFilesUpdated = {};
for (let i = 0; i < tiles.length; i++) {
let tile = tiles[i];
const tileHash = tp.user.computeSHA256(tile);
console.log(`\n[${currentDate}] Processing tile ${i + 1} (${tileHash})`);
let existingDigestMatch = tile.match(/\s*(#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2})/);
let existingDigest = existingDigestMatch ? existingDigestMatch[1] : null;
console.log(`Existing Digest Tag: ${existingDigest || 'None'}`);
let cleanTile = tile.replace(/\s*#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2}/, '').trim();
let { deformattedContent, charactersRemoved } = tp.user.deformatTile(cleanTile);
let digest = tp.user.computeSHA256(deformattedContent);
let digestTag = createDigestTag(digest, currentDate);
console.log(`New Digest Tag: ${digestTag}`);
if (existingDigest && existingDigest.includes(digest)) {
console.log(`Content unchanged for tile ${tileHash}. Keeping existing Digest Tag.`);
digestTag = existingDigest;
nonDigestedTiles++;
// new Notice(`Skipping unchanged tile: ${digestTag}`, 15000);
} else {
console.log(`Content changed or new for tile ${tileHash}. Updating Digest Tag.`);
if (existingDigest) {
updatedTiles++;
} else {
digestedTiles++;
}
}
let processedTile = `${cleanTile} ${digestTag}`;
processedTiles.push(processedTile);
digestTags.push(digestTag);
console.log(`Tile ${tileHash} stats: Characters removed: ${charactersRemoved}`);
const tileFilePath = `${tileDirectoryPath}/${digest}.md`;
const digestRootHash = createDigestRootHash(digestTags);
const tileFileContent = `###### #Digested-Tile ${digestTag}
Authors:: ${authors}
License:: ${license}
Digest Root:: ${digestRootHash}
#MarkdownTile
${cleanTile}
#DeformattedTile
${deformattedContent}
#EOT
---`;
const { status: tileUpdateStatus, file: tileFile } = await tp.user.upsertToFile(tileFilePath, `###### #Digested-Tile ${digestTag}`, tileFileContent);
tileFilesUpdated[tileFilePath] = tileUpdateStatus;
// Update tile file frontmatter
if (tileFile) {
await tp.user.updateFrontMatter(tileFile, {
aliases: [digestTag],
authors: authors,
license: license,
'digest-root': digestRootHash
});
}
}
let result = frontmatter + '\n' + processedTiles.join('\n\n');
const yearMonth = currentDate.slice(2, 7);
let digestRootHash = createDigestRootHash(digestTags);
console.log(`\n[${currentDate}] Digest Root hash created: ${digestRootHash}`);
// Modify the current file content
await app.vault.modify(currentFile, result);
// Update current file frontmatter using tp.user.updateFrontMatter after modifying content
await tp.user.updateFrontMatter(currentFile, {
aliases: [`#ds/root/${digestRootHash}`],
'blockchain_last_digest_root': `#ds/root/${digestRootHash}`,
'blockchain_digest_timestamp': currentTimestamp,
'blockchain_file': `[[wwbc-${yearMonth}]]`
});
// Update blockchain file
const blockchainFilePath = `${blockchainDirectoryPath}/wwbc-${yearMonth}.md`;
const previousBlockchainEntryDigest = await tp.user.getPreviousBlockchainEntryDigest(app, blockchainDirectoryPath, tp.user.computeSHA256);
console.log(`Previous blockchain entry digest: ${previousBlockchainEntryDigest}`);
// Create the blockchain content without the final hash
const blockchainContentWithoutHash = `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}
${digestTags.join(' ')}`.trim();
// Generate the hash for the blockchain entry
const blockchainEntryHash = tp.user.computeSHA256(blockchainContentWithoutHash);
// Create the final blockchain content
const blockchainFileContent = `${blockchainContentWithoutHash}
#ds/block/${blockchainEntryHash}`;
const { status: blockchainUpdateStatus, file: blockchainFile } = await tp.user.upsertToFile(blockchainFilePath, `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}`, blockchainFileContent);
if (blockchainFile) {
await tp.user.updateFrontMatter(blockchainFile, {
cssclasses: [`locked`]
});
}
if (blockchainUpdateStatus === 'updated') {
console.log(`Updated blockchain file: ${blockchainFilePath}`);
} else {
console.log(`Blockchain file already up to date: ${blockchainFilePath}`);
}
const endTime = Date.now();
const runtime = ((endTime - startTime) / 1000).toFixed(2);
console.log(`\n[${currentDate}] DS Tagger Chain process completed successfully`);
const statusMessage = `DS Tagger Chain v${version} completed:
Runtime: ${runtime}s
#ds/root/${digestRootHash}
Tiles processed: ${tiles.length}
Tiles digested: ${digestedTiles}
Tiles not digested: ${nonDigestedTiles}
Tiles updated: ${updatedTiles}
Date: ${currentDate}`;
const tileFilesMessage = `Tile files updated (BUGY):
${Object.entries(tileFilesUpdated).map(([file, status]) => `${file}: ${status}`).join('\n')}`;
const blockchainEntryMessage = `Blockchain entry (${blockchainUpdateStatus}):
${blockchainFileContent}`;
console.log(statusMessage);
console.log(tileFilesMessage);
console.log(blockchainEntryMessage);
new Notice(statusMessage, 15000);
new Notice(tileFilesMessage, 15000);
new Notice(blockchainEntryMessage, 15000);
} catch (error) {
console.error(`[${currentDate}] An error occurred:`, error);
new Notice(`Error in DS Tagger Chain v${version}: ${error.message}. Check console for details.`, 15000);
}
}
// Run the script and output the result
await dsTaggerChain();
%>DeformattedTile Doc Seal 0.9 - Digest & Seal - Current Document.md
<%*
// Doc Seal 0.9 for Obsidian Templater
// Version 0.9.7
/* * *Preserve Specs for Tile and Blockchain formats* * *
Tile Spec:
- Structure `###### #Digested-Tile #ds/{deformat-digest}/{YYYY-MM-DD}\nAuthors:: {authors}\nLicense:: {license}\nDigest Root:: {digestRootHash}\n###### #MarkdownTile\n{tile}\n###### #DeformattedTile\n{deformatted-tile}\n###### #EOT\n---\n`
- Location: `x/ds/tiles/{deformat-digest}.md`
- Upsert Logic: Skip (with Notice message) if `#ds/{deformat-digest}/{YYYY-MM-DD}` exists, append otherwise
Blockchain Spec:
- Structure: `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${YYYY-MM-DDTHH:mm}\n${digestTags.join(' ')}\n#ds/block/{currentBlockchainEntryDigest}`
- Location: `x/ds/blockchains/wwbc-{YY-MM}.md`
- Blockchain Logic: {previousBlockchainEntryDigest} is a hash of {YY-MM} for initial block or the BlockchainEntryDigest of the previous entry; if there are no "wwbc-....md" files yet, use the hash of the YY-MM, if there are not blocks in this months file yet, use the last #ds/block from the previous month, otherwise, use the last #ds/block in the current month's file
Script Spec:
- use Obsidian Templater scripting language for the script
- use tp.user.updateFrontMatter to update frontmatter
- 15s Notice messages about updates, 3 messages: status, tiles, and blockchain
- tp.user scripts: computeSHA256(content, length = 12); splitIntoTiles(content); ensureDirectoryExists(path); upsertToFile(filePath, header, content); updateFrontMatter(file, updates); getPreviousBlockchainEntryDigest(app, computeSHA256);
- inline helper functions: createDigestTag(hash, date); createDigestRootHash(digestTags);
*/
function createDigestTag(hash, date) {
return `#ds/${hash}/${date}`;
}
function createDigestRootHash(digestTags) {
return tp.user.computeSHA256(digestTags.join(' '), 12);
}
// Main function
async function dsTaggerChain() {
const version = "0.9.7";
const startTime = Date.now();
const currentDate = new Date().toISOString().split('T')[0];
const currentTimestamp = new Date().toISOString();
console.log(`[${currentDate}] DS Tagger Chain v${version} started`);
// Configuration
const tileDirectoryPath = "x/ds/tiles";
const blockchainDirectoryPath = "x/ds/blockchains";
try {
// Ensure directories exist
await tp.user.ensureDirectoryExists(tileDirectoryPath);
await tp.user.ensureDirectoryExists(blockchainDirectoryPath);
let content = tp.file.content;
const fileName = tp.file.title;
const currentFile = tp.file.find_tfile(fileName);
if (typeof content !== 'string') {
throw new Error('Received non-string content');
}
const authors = tp.frontmatter.authors || 'Unknown';
const license = tp.frontmatter.license || 'Unspecified';
console.log(`[${currentDate}] Authors extracted: ${authors}`);
console.log(`[${currentDate}] License extracted: ${license}`);
console.log(`[${currentDate}] File content length: ${content.length} characters`);
const { frontmatter, tiles } = tp.user.splitIntoTiles(content);
console.log(`[${currentDate}] Number of tiles: ${tiles.length}`);
let processedTiles = [];
let digestedTiles = 0;
let nonDigestedTiles = 0;
let updatedTiles = 0;
let digestTags = [];
let tileFilesUpdated = {};
for (let i = 0; i < tiles.length; i++) {
let tile = tiles[i];
const tileHash = tp.user.computeSHA256(tile);
console.log(`\n[${currentDate}] Processing tile ${i + 1} (${tileHash})`);
let existingDigestMatch = tile.match(/\s*(#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2})/);
let existingDigest = existingDigestMatch ? existingDigestMatch[1] : null;
console.log(`Existing Digest Tag: ${existingDigest || 'None'}`);
let cleanTile = tile.replace(/\s*#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2}/, '').trim();
let { deformattedContent, charactersRemoved } = tp.user.deformatTile(cleanTile);
let digest = tp.user.computeSHA256(deformattedContent);
let digestTag = createDigestTag(digest, currentDate);
console.log(`New Digest Tag: ${digestTag}`);
if (existingDigest && existingDigest.includes(digest)) {
console.log(`Content unchanged for tile ${tileHash}. Keeping existing Digest Tag.`);
digestTag = existingDigest;
nonDigestedTiles++;
// new Notice(`Skipping unchanged tile: ${digestTag}`, 15000);
} else {
console.log(`Content changed or new for tile ${tileHash}. Updating Digest Tag.`);
if (existingDigest) {
updatedTiles++;
} else {
digestedTiles++;
}
}
let processedTile = `${cleanTile} ${digestTag}`;
processedTiles.push(processedTile);
digestTags.push(digestTag);
console.log(`Tile ${tileHash} stats: Characters removed: ${charactersRemoved}`);
const tileFilePath = `${tileDirectoryPath}/${digest}.md`;
const digestRootHash = createDigestRootHash(digestTags);
const tileFileContent = `###### #Digested-Tile ${digestTag}
Authors:: ${authors}
License:: ${license}
Digest Root:: ${digestRootHash}
#MarkdownTile
${cleanTile}
#DeformattedTile
${deformattedContent}
#EOT
---`;
const { status: tileUpdateStatus, file: tileFile } = await tp.user.upsertToFile(tileFilePath, `###### #Digested-Tile ${digestTag}`, tileFileContent);
tileFilesUpdated[tileFilePath] = tileUpdateStatus;
// Update tile file frontmatter
if (tileFile) {
await tp.user.updateFrontMatter(tileFile, {
aliases: [digestTag],
authors: authors,
license: license,
'digest-root': digestRootHash
});
}
}
let result = frontmatter + '\n' + processedTiles.join('\n\n');
const yearMonth = currentDate.slice(2, 7);
let digestRootHash = createDigestRootHash(digestTags);
console.log(`\n[${currentDate}] Digest Root hash created: ${digestRootHash}`);
// Modify the current file content
await app.vault.modify(currentFile, result);
// Update current file frontmatter using tp.user.updateFrontMatter after modifying content
await tp.user.updateFrontMatter(currentFile, {
aliases: [`#ds/root/${digestRootHash}`],
'blockchain_last_digest_root': `#ds/root/${digestRootHash}`,
'blockchain_digest_timestamp': currentTimestamp,
'blockchain_file': `[[wwbc-${yearMonth}]]`
});
// Update blockchain file
const blockchainFilePath = `${blockchainDirectoryPath}/wwbc-${yearMonth}.md`;
const previousBlockchainEntryDigest = await tp.user.getPreviousBlockchainEntryDigest(app, blockchainDirectoryPath, tp.user.computeSHA256);
console.log(`Previous blockchain entry digest: ${previousBlockchainEntryDigest}`);
// Create the blockchain content without the final hash
const blockchainContentWithoutHash = `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}
${digestTags.join(' ')}`.trim();
// Generate the hash for the blockchain entry
const blockchainEntryHash = tp.user.computeSHA256(blockchainContentWithoutHash);
// Create the final blockchain content
const blockchainFileContent = `${blockchainContentWithoutHash}
#ds/block/${blockchainEntryHash}`;
const { status: blockchainUpdateStatus, file: blockchainFile } = await tp.user.upsertToFile(blockchainFilePath, `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}`, blockchainFileContent);
if (blockchainFile) {
await tp.user.updateFrontMatter(blockchainFile, {
cssclasses: [`locked`]
});
}
if (blockchainUpdateStatus === 'updated') {
console.log(`Updated blockchain file: ${blockchainFilePath}`);
} else {
console.log(`Blockchain file already up to date: ${blockchainFilePath}`);
}
const endTime = Date.now();
const runtime = ((endTime - startTime) / 1000).toFixed(2);
console.log(`\n[${currentDate}] DS Tagger Chain process completed successfully`);
const statusMessage = `DS Tagger Chain v${version} completed:
Runtime: ${runtime}s
#ds/root/${digestRootHash}
Tiles processed: ${tiles.length}
Tiles digested: ${digestedTiles}
Tiles not digested: ${nonDigestedTiles}
Tiles updated: ${updatedTiles}
Date: ${currentDate}`;
const tileFilesMessage = `Tile files updated (BUGY):
${Object.entries(tileFilesUpdated).map(([file, status]) => `${file}: ${status}`).join('\n')}`;
const blockchainEntryMessage = `Blockchain entry (${blockchainUpdateStatus}):
${blockchainFileContent}`;
console.log(statusMessage);
console.log(tileFilesMessage);
console.log(blockchainEntryMessage);
new Notice(statusMessage, 15000);
new Notice(tileFilesMessage, 15000);
new Notice(blockchainEntryMessage, 15000);
} catch (error) {
console.error(`[${currentDate}] An error occurred:`, error);
new Notice(`Error in DS Tagger Chain v${version}: ${error.message}. Check console for details.`, 15000);
}
}
// Run the script and output the result
await dsTaggerChain();
%>EOT
DeformattedTile Doc Seal 0.9 - Digest & Seal - Current Document.md
<%*
// Doc Seal 0.9 for Obsidian Templater
// Version 0.9.7
/* * *Preserve Specs for Tile and Blockchain formats* * *
Tile Spec:
- Structure `###### #Digested-Tile #ds/{deformat-digest}/{YYYY-MM-DD}\nAuthors:: {authors}\nLicense:: {license}\nDigest Root:: {digestRootHash}\n###### #MarkdownTile\n{tile}\n###### #DeformattedTile\n{deformatted-tile}\n###### #EOT\n---\n`
- Location: `x/ds/tiles/{deformat-digest}.md`
- Upsert Logic: Skip (with Notice message) if `#ds/{deformat-digest}/{YYYY-MM-DD}` exists, append otherwise
Blockchain Spec:
- Structure: `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${YYYY-MM-DDTHH:mm}\n${digestTags.join(' ')}\n#ds/block/{currentBlockchainEntryDigest}`
- Location: `x/ds/blockchains/wwbc-{YY-MM}.md`
- Blockchain Logic: {previousBlockchainEntryDigest} is a hash of {YY-MM} for initial block or the BlockchainEntryDigest of the previous entry; if there are no "wwbc-....md" files yet, use the hash of the YY-MM, if there are not blocks in this months file yet, use the last #ds/block from the previous month, otherwise, use the last #ds/block in the current month's file
Script Spec:
- use Obsidian Templater scripting language for the script
- use tp.user.updateFrontMatter to update frontmatter
- 15s Notice messages about updates, 3 messages: status, tiles, and blockchain
- tp.user scripts: computeSHA256(content, length = 12); splitIntoTiles(content); ensureDirectoryExists(path); upsertToFile(filePath, header, content); updateFrontMatter(file, updates); getPreviousBlockchainEntryDigest(app, computeSHA256);
- inline helper functions: createDigestTag(hash, date); createDigestRootHash(digestTags);
*/
function createDigestTag(hash, date) {
return `#ds/${hash}/${date}`;
}
function createDigestRootHash(digestTags) {
return tp.user.computeSHA256(digestTags.join(' '), 12);
}
// Main function
async function dsTaggerChain() {
const version = "0.9.7";
const startTime = Date.now();
const currentDate = new Date().toISOString().split('T')[0];
const currentTimestamp = new Date().toISOString();
console.log(`[${currentDate}] DS Tagger Chain v${version} started`);
// Configuration
const tileDirectoryPath = "x/ds/tiles";
const blockchainDirectoryPath = "x/ds/blockchains";
try {
// Ensure directories exist
await tp.user.ensureDirectoryExists(tileDirectoryPath);
await tp.user.ensureDirectoryExists(blockchainDirectoryPath);
let content = tp.file.content;
const fileName = tp.file.title;
const currentFile = tp.file.find_tfile(fileName);
if (typeof content !== 'string') {
throw new Error('Received non-string content');
}
const authors = tp.frontmatter.authors || 'Unknown';
const license = tp.frontmatter.license || 'Unspecified';
console.log(`[${currentDate}] Authors extracted: ${authors}`);
console.log(`[${currentDate}] License extracted: ${license}`);
console.log(`[${currentDate}] File content length: ${content.length} characters`);
const { frontmatter, tiles } = tp.user.splitIntoTiles(content);
console.log(`[${currentDate}] Number of tiles: ${tiles.length}`);
let processedTiles = [];
let digestedTiles = 0;
let nonDigestedTiles = 0;
let updatedTiles = 0;
let digestTags = [];
let tileFilesUpdated = {};
for (let i = 0; i < tiles.length; i++) {
let tile = tiles[i];
const tileHash = tp.user.computeSHA256(tile);
console.log(`\n[${currentDate}] Processing tile ${i + 1} (${tileHash})`);
let existingDigestMatch = tile.match(/\s*(#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2})/);
let existingDigest = existingDigestMatch ? existingDigestMatch[1] : null;
console.log(`Existing Digest Tag: ${existingDigest || 'None'}`);
let cleanTile = tile.replace(/\s*#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2}/, '').trim();
let { deformattedContent, charactersRemoved } = tp.user.deformatTile(cleanTile);
let digest = tp.user.computeSHA256(deformattedContent);
let digestTag = createDigestTag(digest, currentDate);
console.log(`New Digest Tag: ${digestTag}`);
if (existingDigest && existingDigest.includes(digest)) {
console.log(`Content unchanged for tile ${tileHash}. Keeping existing Digest Tag.`);
digestTag = existingDigest;
nonDigestedTiles++;
// new Notice(`Skipping unchanged tile: ${digestTag}`, 15000);
} else {
console.log(`Content changed or new for tile ${tileHash}. Updating Digest Tag.`);
if (existingDigest) {
updatedTiles++;
} else {
digestedTiles++;
}
}
let processedTile = `${cleanTile} ${digestTag}`;
processedTiles.push(processedTile);
digestTags.push(digestTag);
console.log(`Tile ${tileHash} stats: Characters removed: ${charactersRemoved}`);
const tileFilePath = `${tileDirectoryPath}/${digest}.md`;
const digestRootHash = createDigestRootHash(digestTags);
const tileFileContent = `###### #Digested-Tile ${digestTag}
Authors:: ${authors}
License:: ${license}
Digest Root:: ${digestRootHash}
#MarkdownTile
${cleanTile}
#DeformattedTile
${deformattedContent}
#EOT
---`;
const { status: tileUpdateStatus, file: tileFile } = await tp.user.upsertToFile(tileFilePath, `###### #Digested-Tile ${digestTag}`, tileFileContent);
tileFilesUpdated[tileFilePath] = tileUpdateStatus;
// Update tile file frontmatter
if (tileFile) {
await tp.user.updateFrontMatter(tileFile, {
aliases: [digestTag],
authors: authors,
license: license,
'digest-root': digestRootHash
});
}
}
let result = frontmatter + '\n' + processedTiles.join('\n\n');
const yearMonth = currentDate.slice(2, 7);
let digestRootHash = createDigestRootHash(digestTags);
console.log(`\n[${currentDate}] Digest Root hash created: ${digestRootHash}`);
// Modify the current file content
await app.vault.modify(currentFile, result);
// Update current file frontmatter using tp.user.updateFrontMatter after modifying content
await tp.user.updateFrontMatter(currentFile, {
aliases: [`#ds/root/${digestRootHash}`],
'blockchain_last_digest_root': `#ds/root/${digestRootHash}`,
'blockchain_digest_timestamp': currentTimestamp,
'blockchain_file': `[[wwbc-${yearMonth}]]`
});
// Update blockchain file
const blockchainFilePath = `${blockchainDirectoryPath}/wwbc-${yearMonth}.md`;
const previousBlockchainEntryDigest = await tp.user.getPreviousBlockchainEntryDigest(app, blockchainDirectoryPath, tp.user.computeSHA256);
console.log(`Previous blockchain entry digest: ${previousBlockchainEntryDigest}`);
// Create the blockchain content without the final hash
const blockchainContentWithoutHash = `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}
${digestTags.join(' ')}`.trim();
// Generate the hash for the blockchain entry
const blockchainEntryHash = tp.user.computeSHA256(blockchainContentWithoutHash);
// Create the final blockchain content
const blockchainFileContent = `${blockchainContentWithoutHash}
#ds/block/${blockchainEntryHash}`;
const { status: blockchainUpdateStatus, file: blockchainFile } = await tp.user.upsertToFile(blockchainFilePath, `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}`, blockchainFileContent);
if (blockchainFile) {
await tp.user.updateFrontMatter(blockchainFile, {
cssclasses: [`locked`]
});
}
if (blockchainUpdateStatus === 'updated') {
console.log(`Updated blockchain file: ${blockchainFilePath}`);
} else {
console.log(`Blockchain file already up to date: ${blockchainFilePath}`);
}
const endTime = Date.now();
const runtime = ((endTime - startTime) / 1000).toFixed(2);
console.log(`\n[${currentDate}] DS Tagger Chain process completed successfully`);
const statusMessage = `DS Tagger Chain v${version} completed:
Runtime: ${runtime}s
#ds/root/${digestRootHash}
Tiles processed: ${tiles.length}
Tiles digested: ${digestedTiles}
Tiles not digested: ${nonDigestedTiles}
Tiles updated: ${updatedTiles}
Date: ${currentDate}`;
const tileFilesMessage = `Tile files updated (BUGY):
${Object.entries(tileFilesUpdated).map(([file, status]) => `${file}: ${status}`).join('\n')}`;
const blockchainEntryMessage = `Blockchain entry (${blockchainUpdateStatus}):
${blockchainFileContent}`;
console.log(statusMessage);
console.log(tileFilesMessage);
console.log(blockchainEntryMessage);
new Notice(statusMessage, 15000);
new Notice(tileFilesMessage, 15000);
new Notice(blockchainEntryMessage, 15000);
} catch (error) {
console.error(`[${currentDate}] An error occurred:`, error);
new Notice(`Error in DS Tagger Chain v${version}: ${error.message}. Check console for details.`, 15000);
}
}
// Run the script and output the result
await dsTaggerChain();
%>DeformattedTile Doc Seal 0.9 - Digest & Seal - Current Document.md
<%*
// Doc Seal 0.9 for Obsidian Templater
// Version 0.9.7
/* * *Preserve Specs for Tile and Blockchain formats* * *
Tile Spec:
- Structure `###### #Digested-Tile #ds/{deformat-digest}/{YYYY-MM-DD}\nAuthors:: {authors}\nLicense:: {license}\nDigest Root:: {digestRootHash}\n###### #MarkdownTile\n{tile}\n###### #DeformattedTile\n{deformatted-tile}\n###### #EOT\n---\n`
- Location: `x/ds/tiles/{deformat-digest}.md`
- Upsert Logic: Skip (with Notice message) if `#ds/{deformat-digest}/{YYYY-MM-DD}` exists, append otherwise
Blockchain Spec:
- Structure: `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${YYYY-MM-DDTHH:mm}\n${digestTags.join(' ')}\n#ds/block/{currentBlockchainEntryDigest}`
- Location: `x/ds/blockchains/wwbc-{YY-MM}.md`
- Blockchain Logic: {previousBlockchainEntryDigest} is a hash of {YY-MM} for initial block or the BlockchainEntryDigest of the previous entry; if there are no "wwbc-....md" files yet, use the hash of the YY-MM, if there are not blocks in this months file yet, use the last #ds/block from the previous month, otherwise, use the last #ds/block in the current month's file
Script Spec:
- use Obsidian Templater scripting language for the script
- use tp.user.updateFrontMatter to update frontmatter
- 15s Notice messages about updates, 3 messages: status, tiles, and blockchain
- tp.user scripts: computeSHA256(content, length = 12); splitIntoTiles(content); ensureDirectoryExists(path); upsertToFile(filePath, header, content); updateFrontMatter(file, updates); getPreviousBlockchainEntryDigest(app, computeSHA256);
- inline helper functions: createDigestTag(hash, date); createDigestRootHash(digestTags);
*/
function createDigestTag(hash, date) {
return `#ds/${hash}/${date}`;
}
function createDigestRootHash(digestTags) {
return tp.user.computeSHA256(digestTags.join(' '), 12);
}
// Main function
async function dsTaggerChain() {
const version = "0.9.7";
const startTime = Date.now();
const currentDate = new Date().toISOString().split('T')[0];
const currentTimestamp = new Date().toISOString();
console.log(`[${currentDate}] DS Tagger Chain v${version} started`);
// Configuration
const tileDirectoryPath = "x/ds/tiles";
const blockchainDirectoryPath = "x/ds/blockchains";
try {
// Ensure directories exist
await tp.user.ensureDirectoryExists(tileDirectoryPath);
await tp.user.ensureDirectoryExists(blockchainDirectoryPath);
let content = tp.file.content;
const fileName = tp.file.title;
const currentFile = tp.file.find_tfile(fileName);
if (typeof content !== 'string') {
throw new Error('Received non-string content');
}
const authors = tp.frontmatter.authors || 'Unknown';
const license = tp.frontmatter.license || 'Unspecified';
console.log(`[${currentDate}] Authors extracted: ${authors}`);
console.log(`[${currentDate}] License extracted: ${license}`);
console.log(`[${currentDate}] File content length: ${content.length} characters`);
const { frontmatter, tiles } = tp.user.splitIntoTiles(content);
console.log(`[${currentDate}] Number of tiles: ${tiles.length}`);
let processedTiles = [];
let digestedTiles = 0;
let nonDigestedTiles = 0;
let updatedTiles = 0;
let digestTags = [];
let tileFilesUpdated = {};
for (let i = 0; i < tiles.length; i++) {
let tile = tiles[i];
const tileHash = tp.user.computeSHA256(tile);
console.log(`\n[${currentDate}] Processing tile ${i + 1} (${tileHash})`);
let existingDigestMatch = tile.match(/\s*(#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2})/);
let existingDigest = existingDigestMatch ? existingDigestMatch[1] : null;
console.log(`Existing Digest Tag: ${existingDigest || 'None'}`);
let cleanTile = tile.replace(/\s*#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2}/, '').trim();
let { deformattedContent, charactersRemoved } = tp.user.deformatTile(cleanTile);
let digest = tp.user.computeSHA256(deformattedContent);
let digestTag = createDigestTag(digest, currentDate);
console.log(`New Digest Tag: ${digestTag}`);
if (existingDigest && existingDigest.includes(digest)) {
console.log(`Content unchanged for tile ${tileHash}. Keeping existing Digest Tag.`);
digestTag = existingDigest;
nonDigestedTiles++;
// new Notice(`Skipping unchanged tile: ${digestTag}`, 15000);
} else {
console.log(`Content changed or new for tile ${tileHash}. Updating Digest Tag.`);
if (existingDigest) {
updatedTiles++;
} else {
digestedTiles++;
}
}
let processedTile = `${cleanTile} ${digestTag}`;
processedTiles.push(processedTile);
digestTags.push(digestTag);
console.log(`Tile ${tileHash} stats: Characters removed: ${charactersRemoved}`);
const tileFilePath = `${tileDirectoryPath}/${digest}.md`;
const digestRootHash = createDigestRootHash(digestTags);
const tileFileContent = `###### #Digested-Tile ${digestTag}
Authors:: ${authors}
License:: ${license}
Digest Root:: ${digestRootHash}
#MarkdownTile
${cleanTile}
#DeformattedTile
${deformattedContent}
#EOT
---`;
const { status: tileUpdateStatus, file: tileFile } = await tp.user.upsertToFile(tileFilePath, `###### #Digested-Tile ${digestTag}`, tileFileContent);
tileFilesUpdated[tileFilePath] = tileUpdateStatus;
// Update tile file frontmatter
if (tileFile) {
await tp.user.updateFrontMatter(tileFile, {
aliases: [digestTag],
authors: authors,
license: license,
'digest-root': digestRootHash
});
}
}
let result = frontmatter + '\n' + processedTiles.join('\n\n');
const yearMonth = currentDate.slice(2, 7);
let digestRootHash = createDigestRootHash(digestTags);
console.log(`\n[${currentDate}] Digest Root hash created: ${digestRootHash}`);
// Modify the current file content
await app.vault.modify(currentFile, result);
// Update current file frontmatter using tp.user.updateFrontMatter after modifying content
await tp.user.updateFrontMatter(currentFile, {
aliases: [`#ds/root/${digestRootHash}`],
'blockchain_last_digest_root': `#ds/root/${digestRootHash}`,
'blockchain_digest_timestamp': currentTimestamp,
'blockchain_file': `[[wwbc-${yearMonth}]]`
});
// Update blockchain file
const blockchainFilePath = `${blockchainDirectoryPath}/wwbc-${yearMonth}.md`;
const previousBlockchainEntryDigest = await tp.user.getPreviousBlockchainEntryDigest(app, blockchainDirectoryPath, tp.user.computeSHA256);
console.log(`Previous blockchain entry digest: ${previousBlockchainEntryDigest}`);
// Create the blockchain content without the final hash
const blockchainContentWithoutHash = `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}
${digestTags.join(' ')}`.trim();
// Generate the hash for the blockchain entry
const blockchainEntryHash = tp.user.computeSHA256(blockchainContentWithoutHash);
// Create the final blockchain content
const blockchainFileContent = `${blockchainContentWithoutHash}
#ds/block/${blockchainEntryHash}`;
const { status: blockchainUpdateStatus, file: blockchainFile } = await tp.user.upsertToFile(blockchainFilePath, `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}`, blockchainFileContent);
if (blockchainFile) {
await tp.user.updateFrontMatter(blockchainFile, {
cssclasses: [`locked`]
});
}
if (blockchainUpdateStatus === 'updated') {
console.log(`Updated blockchain file: ${blockchainFilePath}`);
} else {
console.log(`Blockchain file already up to date: ${blockchainFilePath}`);
}
const endTime = Date.now();
const runtime = ((endTime - startTime) / 1000).toFixed(2);
console.log(`\n[${currentDate}] DS Tagger Chain process completed successfully`);
const statusMessage = `DS Tagger Chain v${version} completed:
Runtime: ${runtime}s
#ds/root/${digestRootHash}
Tiles processed: ${tiles.length}
Tiles digested: ${digestedTiles}
Tiles not digested: ${nonDigestedTiles}
Tiles updated: ${updatedTiles}
Date: ${currentDate}`;
const tileFilesMessage = `Tile files updated (BUGY):
${Object.entries(tileFilesUpdated).map(([file, status]) => `${file}: ${status}`).join('\n')}`;
const blockchainEntryMessage = `Blockchain entry (${blockchainUpdateStatus}):
${blockchainFileContent}`;
console.log(statusMessage);
console.log(tileFilesMessage);
console.log(blockchainEntryMessage);
new Notice(statusMessage, 15000);
new Notice(tileFilesMessage, 15000);
new Notice(blockchainEntryMessage, 15000);
} catch (error) {
console.error(`[${currentDate}] An error occurred:`, error);
new Notice(`Error in DS Tagger Chain v${version}: ${error.message}. Check console for details.`, 15000);
}
}
// Run the script and output the result
await dsTaggerChain();
%>EOT
EOT
EOT
DeformattedTile Doc Seal 0.9 - Digest & Seal - Current Document.md
<%*
// Doc Seal 0.9 for Obsidian Templater
// Version 0.9.7
/* * *Preserve Specs for Tile and Blockchain formats* * *
Tile Spec:
- Structure `###### #Digested-Tile #ds/{deformat-digest}/{YYYY-MM-DD}\nAuthors:: {authors}\nLicense:: {license}\nDigest Root:: {digestRootHash}\n###### #MarkdownTile\n{tile}\n###### #DeformattedTile\n{deformatted-tile}\n###### #EOT\n---\n`
- Location: `x/ds/tiles/{deformat-digest}.md`
- Upsert Logic: Skip (with Notice message) if `#ds/{deformat-digest}/{YYYY-MM-DD}` exists, append otherwise
Blockchain Spec:
- Structure: `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${YYYY-MM-DDTHH:mm}\n${digestTags.join(' ')}\n#ds/block/{currentBlockchainEntryDigest}`
- Location: `x/ds/blockchains/wwbc-{YY-MM}.md`
- Blockchain Logic: {previousBlockchainEntryDigest} is a hash of {YY-MM} for initial block or the BlockchainEntryDigest of the previous entry; if there are no "wwbc-....md" files yet, use the hash of the YY-MM, if there are not blocks in this months file yet, use the last #ds/block from the previous month, otherwise, use the last #ds/block in the current month's file
Script Spec:
- use Obsidian Templater scripting language for the script
- use tp.user.updateFrontMatter to update frontmatter
- 15s Notice messages about updates, 3 messages: status, tiles, and blockchain
- tp.user scripts: computeSHA256(content, length = 12); splitIntoTiles(content); ensureDirectoryExists(path); upsertToFile(filePath, header, content); updateFrontMatter(file, updates); getPreviousBlockchainEntryDigest(app, computeSHA256);
- inline helper functions: createDigestTag(hash, date); createDigestRootHash(digestTags);
*/
function createDigestTag(hash, date) {
return `#ds/${hash}/${date}`;
}
function createDigestRootHash(digestTags) {
return tp.user.computeSHA256(digestTags.join(' '), 12);
}
// Main function
async function dsTaggerChain() {
const version = "0.9.7";
const startTime = Date.now();
const currentDate = new Date().toISOString().split('T')[0];
const currentTimestamp = new Date().toISOString();
console.log(`[${currentDate}] DS Tagger Chain v${version} started`);
// Configuration
const tileDirectoryPath = "x/ds/tiles";
const blockchainDirectoryPath = "x/ds/blockchains";
try {
// Ensure directories exist
await tp.user.ensureDirectoryExists(tileDirectoryPath);
await tp.user.ensureDirectoryExists(blockchainDirectoryPath);
let content = tp.file.content;
const fileName = tp.file.title;
const currentFile = tp.file.find_tfile(fileName);
if (typeof content !== 'string') {
throw new Error('Received non-string content');
}
const authors = tp.frontmatter.authors || 'Unknown';
const license = tp.frontmatter.license || 'Unspecified';
console.log(`[${currentDate}] Authors extracted: ${authors}`);
console.log(`[${currentDate}] License extracted: ${license}`);
console.log(`[${currentDate}] File content length: ${content.length} characters`);
const { frontmatter, tiles } = tp.user.splitIntoTiles(content);
console.log(`[${currentDate}] Number of tiles: ${tiles.length}`);
let processedTiles = [];
let digestedTiles = 0;
let nonDigestedTiles = 0;
let updatedTiles = 0;
let digestTags = [];
let tileFilesUpdated = {};
for (let i = 0; i < tiles.length; i++) {
let tile = tiles[i];
const tileHash = tp.user.computeSHA256(tile);
console.log(`\n[${currentDate}] Processing tile ${i + 1} (${tileHash})`);
let existingDigestMatch = tile.match(/\s*(#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2})/);
let existingDigest = existingDigestMatch ? existingDigestMatch[1] : null;
console.log(`Existing Digest Tag: ${existingDigest || 'None'}`);
let cleanTile = tile.replace(/\s*#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2}/, '').trim();
let { deformattedContent, charactersRemoved } = tp.user.deformatTile(cleanTile);
let digest = tp.user.computeSHA256(deformattedContent);
let digestTag = createDigestTag(digest, currentDate);
console.log(`New Digest Tag: ${digestTag}`);
if (existingDigest && existingDigest.includes(digest)) {
console.log(`Content unchanged for tile ${tileHash}. Keeping existing Digest Tag.`);
digestTag = existingDigest;
nonDigestedTiles++;
// new Notice(`Skipping unchanged tile: ${digestTag}`, 15000);
} else {
console.log(`Content changed or new for tile ${tileHash}. Updating Digest Tag.`);
if (existingDigest) {
updatedTiles++;
} else {
digestedTiles++;
}
}
let processedTile = `${cleanTile} ${digestTag}`;
processedTiles.push(processedTile);
digestTags.push(digestTag);
console.log(`Tile ${tileHash} stats: Characters removed: ${charactersRemoved}`);
const tileFilePath = `${tileDirectoryPath}/${digest}.md`;
const digestRootHash = createDigestRootHash(digestTags);
const tileFileContent = `###### #Digested-Tile ${digestTag}
Authors:: ${authors}
License:: ${license}
Digest Root:: ${digestRootHash}
#MarkdownTile
${cleanTile}
#DeformattedTile
${deformattedContent}
#EOT
---`;
const { status: tileUpdateStatus, file: tileFile } = await tp.user.upsertToFile(tileFilePath, `###### #Digested-Tile ${digestTag}`, tileFileContent);
tileFilesUpdated[tileFilePath] = tileUpdateStatus;
// Update tile file frontmatter
if (tileFile) {
await tp.user.updateFrontMatter(tileFile, {
aliases: [digestTag],
authors: authors,
license: license,
'digest-root': digestRootHash
});
}
}
let result = frontmatter + '\n' + processedTiles.join('\n\n');
const yearMonth = currentDate.slice(2, 7);
let digestRootHash = createDigestRootHash(digestTags);
console.log(`\n[${currentDate}] Digest Root hash created: ${digestRootHash}`);
// Modify the current file content
await app.vault.modify(currentFile, result);
// Update current file frontmatter using tp.user.updateFrontMatter after modifying content
await tp.user.updateFrontMatter(currentFile, {
aliases: [`#ds/root/${digestRootHash}`],
'blockchain_last_digest_root': `#ds/root/${digestRootHash}`,
'blockchain_digest_timestamp': currentTimestamp,
'blockchain_file': `[[wwbc-${yearMonth}]]`
});
// Update blockchain file
const blockchainFilePath = `${blockchainDirectoryPath}/wwbc-${yearMonth}.md`;
const previousBlockchainEntryDigest = await tp.user.getPreviousBlockchainEntryDigest(app, blockchainDirectoryPath, tp.user.computeSHA256);
console.log(`Previous blockchain entry digest: ${previousBlockchainEntryDigest}`);
// Create the blockchain content without the final hash
const blockchainContentWithoutHash = `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}
${digestTags.join(' ')}`.trim();
// Generate the hash for the blockchain entry
const blockchainEntryHash = tp.user.computeSHA256(blockchainContentWithoutHash);
// Create the final blockchain content
const blockchainFileContent = `${blockchainContentWithoutHash}
#ds/block/${blockchainEntryHash}`;
const { status: blockchainUpdateStatus, file: blockchainFile } = await tp.user.upsertToFile(blockchainFilePath, `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}`, blockchainFileContent);
if (blockchainFile) {
await tp.user.updateFrontMatter(blockchainFile, {
cssclasses: [`locked`]
});
}
if (blockchainUpdateStatus === 'updated') {
console.log(`Updated blockchain file: ${blockchainFilePath}`);
} else {
console.log(`Blockchain file already up to date: ${blockchainFilePath}`);
}
const endTime = Date.now();
const runtime = ((endTime - startTime) / 1000).toFixed(2);
console.log(`\n[${currentDate}] DS Tagger Chain process completed successfully`);
const statusMessage = `DS Tagger Chain v${version} completed:
Runtime: ${runtime}s
#ds/root/${digestRootHash}
Tiles processed: ${tiles.length}
Tiles digested: ${digestedTiles}
Tiles not digested: ${nonDigestedTiles}
Tiles updated: ${updatedTiles}
Date: ${currentDate}`;
const tileFilesMessage = `Tile files updated (BUGY):
${Object.entries(tileFilesUpdated).map(([file, status]) => `${file}: ${status}`).join('\n')}`;
const blockchainEntryMessage = `Blockchain entry (${blockchainUpdateStatus}):
${blockchainFileContent}`;
console.log(statusMessage);
console.log(tileFilesMessage);
console.log(blockchainEntryMessage);
new Notice(statusMessage, 15000);
new Notice(tileFilesMessage, 15000);
new Notice(blockchainEntryMessage, 15000);
} catch (error) {
console.error(`[${currentDate}] An error occurred:`, error);
new Notice(`Error in DS Tagger Chain v${version}: ${error.message}. Check console for details.`, 15000);
}
}
// Run the script and output the result
await dsTaggerChain();
%>DeformattedTile Doc Seal 0.9 - Digest & Seal - Current Document.md
<%*
// Doc Seal 0.9 for Obsidian Templater
// Version 0.9.7
/* * *Preserve Specs for Tile and Blockchain formats* * *
Tile Spec:
- Structure `###### #Digested-Tile #ds/{deformat-digest}/{YYYY-MM-DD}\nAuthors:: {authors}\nLicense:: {license}\nDigest Root:: {digestRootHash}\n###### #MarkdownTile\n{tile}\n###### #DeformattedTile\n{deformatted-tile}\n###### #EOT\n---\n`
- Location: `x/ds/tiles/{deformat-digest}.md`
- Upsert Logic: Skip (with Notice message) if `#ds/{deformat-digest}/{YYYY-MM-DD}` exists, append otherwise
Blockchain Spec:
- Structure: `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${YYYY-MM-DDTHH:mm}\n${digestTags.join(' ')}\n#ds/block/{currentBlockchainEntryDigest}`
- Location: `x/ds/blockchains/wwbc-{YY-MM}.md`
- Blockchain Logic: {previousBlockchainEntryDigest} is a hash of {YY-MM} for initial block or the BlockchainEntryDigest of the previous entry; if there are no "wwbc-....md" files yet, use the hash of the YY-MM, if there are not blocks in this months file yet, use the last #ds/block from the previous month, otherwise, use the last #ds/block in the current month's file
Script Spec:
- use Obsidian Templater scripting language for the script
- use tp.user.updateFrontMatter to update frontmatter
- 15s Notice messages about updates, 3 messages: status, tiles, and blockchain
- tp.user scripts: computeSHA256(content, length = 12); splitIntoTiles(content); ensureDirectoryExists(path); upsertToFile(filePath, header, content); updateFrontMatter(file, updates); getPreviousBlockchainEntryDigest(app, computeSHA256);
- inline helper functions: createDigestTag(hash, date); createDigestRootHash(digestTags);
*/
function createDigestTag(hash, date) {
return `#ds/${hash}/${date}`;
}
function createDigestRootHash(digestTags) {
return tp.user.computeSHA256(digestTags.join(' '), 12);
}
// Main function
async function dsTaggerChain() {
const version = "0.9.7";
const startTime = Date.now();
const currentDate = new Date().toISOString().split('T')[0];
const currentTimestamp = new Date().toISOString();
console.log(`[${currentDate}] DS Tagger Chain v${version} started`);
// Configuration
const tileDirectoryPath = "x/ds/tiles";
const blockchainDirectoryPath = "x/ds/blockchains";
try {
// Ensure directories exist
await tp.user.ensureDirectoryExists(tileDirectoryPath);
await tp.user.ensureDirectoryExists(blockchainDirectoryPath);
let content = tp.file.content;
const fileName = tp.file.title;
const currentFile = tp.file.find_tfile(fileName);
if (typeof content !== 'string') {
throw new Error('Received non-string content');
}
const authors = tp.frontmatter.authors || 'Unknown';
const license = tp.frontmatter.license || 'Unspecified';
console.log(`[${currentDate}] Authors extracted: ${authors}`);
console.log(`[${currentDate}] License extracted: ${license}`);
console.log(`[${currentDate}] File content length: ${content.length} characters`);
const { frontmatter, tiles } = tp.user.splitIntoTiles(content);
console.log(`[${currentDate}] Number of tiles: ${tiles.length}`);
let processedTiles = [];
let digestedTiles = 0;
let nonDigestedTiles = 0;
let updatedTiles = 0;
let digestTags = [];
let tileFilesUpdated = {};
for (let i = 0; i < tiles.length; i++) {
let tile = tiles[i];
const tileHash = tp.user.computeSHA256(tile);
console.log(`\n[${currentDate}] Processing tile ${i + 1} (${tileHash})`);
let existingDigestMatch = tile.match(/\s*(#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2})/);
let existingDigest = existingDigestMatch ? existingDigestMatch[1] : null;
console.log(`Existing Digest Tag: ${existingDigest || 'None'}`);
let cleanTile = tile.replace(/\s*#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2}/, '').trim();
let { deformattedContent, charactersRemoved } = tp.user.deformatTile(cleanTile);
let digest = tp.user.computeSHA256(deformattedContent);
let digestTag = createDigestTag(digest, currentDate);
console.log(`New Digest Tag: ${digestTag}`);
if (existingDigest && existingDigest.includes(digest)) {
console.log(`Content unchanged for tile ${tileHash}. Keeping existing Digest Tag.`);
digestTag = existingDigest;
nonDigestedTiles++;
// new Notice(`Skipping unchanged tile: ${digestTag}`, 15000);
} else {
console.log(`Content changed or new for tile ${tileHash}. Updating Digest Tag.`);
if (existingDigest) {
updatedTiles++;
} else {
digestedTiles++;
}
}
let processedTile = `${cleanTile} ${digestTag}`;
processedTiles.push(processedTile);
digestTags.push(digestTag);
console.log(`Tile ${tileHash} stats: Characters removed: ${charactersRemoved}`);
const tileFilePath = `${tileDirectoryPath}/${digest}.md`;
const digestRootHash = createDigestRootHash(digestTags);
const tileFileContent = `###### #Digested-Tile ${digestTag}
Authors:: ${authors}
License:: ${license}
Digest Root:: ${digestRootHash}
#MarkdownTile
${cleanTile}
#DeformattedTile
${deformattedContent}
#EOT
---`;
const { status: tileUpdateStatus, file: tileFile } = await tp.user.upsertToFile(tileFilePath, `###### #Digested-Tile ${digestTag}`, tileFileContent);
tileFilesUpdated[tileFilePath] = tileUpdateStatus;
// Update tile file frontmatter
if (tileFile) {
await tp.user.updateFrontMatter(tileFile, {
aliases: [digestTag],
authors: authors,
license: license,
'digest-root': digestRootHash
});
}
}
let result = frontmatter + '\n' + processedTiles.join('\n\n');
const yearMonth = currentDate.slice(2, 7);
let digestRootHash = createDigestRootHash(digestTags);
console.log(`\n[${currentDate}] Digest Root hash created: ${digestRootHash}`);
// Modify the current file content
await app.vault.modify(currentFile, result);
// Update current file frontmatter using tp.user.updateFrontMatter after modifying content
await tp.user.updateFrontMatter(currentFile, {
aliases: [`#ds/root/${digestRootHash}`],
'blockchain_last_digest_root': `#ds/root/${digestRootHash}`,
'blockchain_digest_timestamp': currentTimestamp,
'blockchain_file': `[[wwbc-${yearMonth}]]`
});
// Update blockchain file
const blockchainFilePath = `${blockchainDirectoryPath}/wwbc-${yearMonth}.md`;
const previousBlockchainEntryDigest = await tp.user.getPreviousBlockchainEntryDigest(app, blockchainDirectoryPath, tp.user.computeSHA256);
console.log(`Previous blockchain entry digest: ${previousBlockchainEntryDigest}`);
// Create the blockchain content without the final hash
const blockchainContentWithoutHash = `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}
${digestTags.join(' ')}`.trim();
// Generate the hash for the blockchain entry
const blockchainEntryHash = tp.user.computeSHA256(blockchainContentWithoutHash);
// Create the final blockchain content
const blockchainFileContent = `${blockchainContentWithoutHash}
#ds/block/${blockchainEntryHash}`;
const { status: blockchainUpdateStatus, file: blockchainFile } = await tp.user.upsertToFile(blockchainFilePath, `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}`, blockchainFileContent);
if (blockchainFile) {
await tp.user.updateFrontMatter(blockchainFile, {
cssclasses: [`locked`]
});
}
if (blockchainUpdateStatus === 'updated') {
console.log(`Updated blockchain file: ${blockchainFilePath}`);
} else {
console.log(`Blockchain file already up to date: ${blockchainFilePath}`);
}
const endTime = Date.now();
const runtime = ((endTime - startTime) / 1000).toFixed(2);
console.log(`\n[${currentDate}] DS Tagger Chain process completed successfully`);
const statusMessage = `DS Tagger Chain v${version} completed:
Runtime: ${runtime}s
#ds/root/${digestRootHash}
Tiles processed: ${tiles.length}
Tiles digested: ${digestedTiles}
Tiles not digested: ${nonDigestedTiles}
Tiles updated: ${updatedTiles}
Date: ${currentDate}`;
const tileFilesMessage = `Tile files updated (BUGY):
${Object.entries(tileFilesUpdated).map(([file, status]) => `${file}: ${status}`).join('\n')}`;
const blockchainEntryMessage = `Blockchain entry (${blockchainUpdateStatus}):
${blockchainFileContent}`;
console.log(statusMessage);
console.log(tileFilesMessage);
console.log(blockchainEntryMessage);
new Notice(statusMessage, 15000);
new Notice(tileFilesMessage, 15000);
new Notice(blockchainEntryMessage, 15000);
} catch (error) {
console.error(`[${currentDate}] An error occurred:`, error);
new Notice(`Error in DS Tagger Chain v${version}: ${error.message}. Check console for details.`, 15000);
}
}
// Run the script and output the result
await dsTaggerChain();
%>EOT
DeformattedTile Doc Seal 0.9 - Digest & Seal - Current Document.md
<%*
// Doc Seal 0.9 for Obsidian Templater
// Version 0.9.7
/* * *Preserve Specs for Tile and Blockchain formats* * *
Tile Spec:
- Structure `###### #Digested-Tile #ds/{deformat-digest}/{YYYY-MM-DD}\nAuthors:: {authors}\nLicense:: {license}\nDigest Root:: {digestRootHash}\n###### #MarkdownTile\n{tile}\n###### #DeformattedTile\n{deformatted-tile}\n###### #EOT\n---\n`
- Location: `x/ds/tiles/{deformat-digest}.md`
- Upsert Logic: Skip (with Notice message) if `#ds/{deformat-digest}/{YYYY-MM-DD}` exists, append otherwise
Blockchain Spec:
- Structure: `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${YYYY-MM-DDTHH:mm}\n${digestTags.join(' ')}\n#ds/block/{currentBlockchainEntryDigest}`
- Location: `x/ds/blockchains/wwbc-{YY-MM}.md`
- Blockchain Logic: {previousBlockchainEntryDigest} is a hash of {YY-MM} for initial block or the BlockchainEntryDigest of the previous entry; if there are no "wwbc-....md" files yet, use the hash of the YY-MM, if there are not blocks in this months file yet, use the last #ds/block from the previous month, otherwise, use the last #ds/block in the current month's file
Script Spec:
- use Obsidian Templater scripting language for the script
- use tp.user.updateFrontMatter to update frontmatter
- 15s Notice messages about updates, 3 messages: status, tiles, and blockchain
- tp.user scripts: computeSHA256(content, length = 12); splitIntoTiles(content); ensureDirectoryExists(path); upsertToFile(filePath, header, content); updateFrontMatter(file, updates); getPreviousBlockchainEntryDigest(app, computeSHA256);
- inline helper functions: createDigestTag(hash, date); createDigestRootHash(digestTags);
*/
function createDigestTag(hash, date) {
return `#ds/${hash}/${date}`;
}
function createDigestRootHash(digestTags) {
return tp.user.computeSHA256(digestTags.join(' '), 12);
}
// Main function
async function dsTaggerChain() {
const version = "0.9.7";
const startTime = Date.now();
const currentDate = new Date().toISOString().split('T')[0];
const currentTimestamp = new Date().toISOString();
console.log(`[${currentDate}] DS Tagger Chain v${version} started`);
// Configuration
const tileDirectoryPath = "x/ds/tiles";
const blockchainDirectoryPath = "x/ds/blockchains";
try {
// Ensure directories exist
await tp.user.ensureDirectoryExists(tileDirectoryPath);
await tp.user.ensureDirectoryExists(blockchainDirectoryPath);
let content = tp.file.content;
const fileName = tp.file.title;
const currentFile = tp.file.find_tfile(fileName);
if (typeof content !== 'string') {
throw new Error('Received non-string content');
}
const authors = tp.frontmatter.authors || 'Unknown';
const license = tp.frontmatter.license || 'Unspecified';
console.log(`[${currentDate}] Authors extracted: ${authors}`);
console.log(`[${currentDate}] License extracted: ${license}`);
console.log(`[${currentDate}] File content length: ${content.length} characters`);
const { frontmatter, tiles } = tp.user.splitIntoTiles(content);
console.log(`[${currentDate}] Number of tiles: ${tiles.length}`);
let processedTiles = [];
let digestedTiles = 0;
let nonDigestedTiles = 0;
let updatedTiles = 0;
let digestTags = [];
let tileFilesUpdated = {};
for (let i = 0; i < tiles.length; i++) {
let tile = tiles[i];
const tileHash = tp.user.computeSHA256(tile);
console.log(`\n[${currentDate}] Processing tile ${i + 1} (${tileHash})`);
let existingDigestMatch = tile.match(/\s*(#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2})/);
let existingDigest = existingDigestMatch ? existingDigestMatch[1] : null;
console.log(`Existing Digest Tag: ${existingDigest || 'None'}`);
let cleanTile = tile.replace(/\s*#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2}/, '').trim();
let { deformattedContent, charactersRemoved } = tp.user.deformatTile(cleanTile);
let digest = tp.user.computeSHA256(deformattedContent);
let digestTag = createDigestTag(digest, currentDate);
console.log(`New Digest Tag: ${digestTag}`);
if (existingDigest && existingDigest.includes(digest)) {
console.log(`Content unchanged for tile ${tileHash}. Keeping existing Digest Tag.`);
digestTag = existingDigest;
nonDigestedTiles++;
// new Notice(`Skipping unchanged tile: ${digestTag}`, 15000);
} else {
console.log(`Content changed or new for tile ${tileHash}. Updating Digest Tag.`);
if (existingDigest) {
updatedTiles++;
} else {
digestedTiles++;
}
}
let processedTile = `${cleanTile} ${digestTag}`;
processedTiles.push(processedTile);
digestTags.push(digestTag);
console.log(`Tile ${tileHash} stats: Characters removed: ${charactersRemoved}`);
const tileFilePath = `${tileDirectoryPath}/${digest}.md`;
const digestRootHash = createDigestRootHash(digestTags);
const tileFileContent = `###### #Digested-Tile ${digestTag}
Authors:: ${authors}
License:: ${license}
Digest Root:: ${digestRootHash}
#MarkdownTile
${cleanTile}
#DeformattedTile
${deformattedContent}
#EOT
---`;
const { status: tileUpdateStatus, file: tileFile } = await tp.user.upsertToFile(tileFilePath, `###### #Digested-Tile ${digestTag}`, tileFileContent);
tileFilesUpdated[tileFilePath] = tileUpdateStatus;
// Update tile file frontmatter
if (tileFile) {
await tp.user.updateFrontMatter(tileFile, {
aliases: [digestTag],
authors: authors,
license: license,
'digest-root': digestRootHash
});
}
}
let result = frontmatter + '\n' + processedTiles.join('\n\n');
const yearMonth = currentDate.slice(2, 7);
let digestRootHash = createDigestRootHash(digestTags);
console.log(`\n[${currentDate}] Digest Root hash created: ${digestRootHash}`);
// Modify the current file content
await app.vault.modify(currentFile, result);
// Update current file frontmatter using tp.user.updateFrontMatter after modifying content
await tp.user.updateFrontMatter(currentFile, {
aliases: [`#ds/root/${digestRootHash}`],
'blockchain_last_digest_root': `#ds/root/${digestRootHash}`,
'blockchain_digest_timestamp': currentTimestamp,
'blockchain_file': `[[wwbc-${yearMonth}]]`
});
// Update blockchain file
const blockchainFilePath = `${blockchainDirectoryPath}/wwbc-${yearMonth}.md`;
const previousBlockchainEntryDigest = await tp.user.getPreviousBlockchainEntryDigest(app, blockchainDirectoryPath, tp.user.computeSHA256);
console.log(`Previous blockchain entry digest: ${previousBlockchainEntryDigest}`);
// Create the blockchain content without the final hash
const blockchainContentWithoutHash = `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}
${digestTags.join(' ')}`.trim();
// Generate the hash for the blockchain entry
const blockchainEntryHash = tp.user.computeSHA256(blockchainContentWithoutHash);
// Create the final blockchain content
const blockchainFileContent = `${blockchainContentWithoutHash}
#ds/block/${blockchainEntryHash}`;
const { status: blockchainUpdateStatus, file: blockchainFile } = await tp.user.upsertToFile(blockchainFilePath, `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}`, blockchainFileContent);
if (blockchainFile) {
await tp.user.updateFrontMatter(blockchainFile, {
cssclasses: [`locked`]
});
}
if (blockchainUpdateStatus === 'updated') {
console.log(`Updated blockchain file: ${blockchainFilePath}`);
} else {
console.log(`Blockchain file already up to date: ${blockchainFilePath}`);
}
const endTime = Date.now();
const runtime = ((endTime - startTime) / 1000).toFixed(2);
console.log(`\n[${currentDate}] DS Tagger Chain process completed successfully`);
const statusMessage = `DS Tagger Chain v${version} completed:
Runtime: ${runtime}s
#ds/root/${digestRootHash}
Tiles processed: ${tiles.length}
Tiles digested: ${digestedTiles}
Tiles not digested: ${nonDigestedTiles}
Tiles updated: ${updatedTiles}
Date: ${currentDate}`;
const tileFilesMessage = `Tile files updated (BUGY):
${Object.entries(tileFilesUpdated).map(([file, status]) => `${file}: ${status}`).join('\n')}`;
const blockchainEntryMessage = `Blockchain entry (${blockchainUpdateStatus}):
${blockchainFileContent}`;
console.log(statusMessage);
console.log(tileFilesMessage);
console.log(blockchainEntryMessage);
new Notice(statusMessage, 15000);
new Notice(tileFilesMessage, 15000);
new Notice(blockchainEntryMessage, 15000);
} catch (error) {
console.error(`[${currentDate}] An error occurred:`, error);
new Notice(`Error in DS Tagger Chain v${version}: ${error.message}. Check console for details.`, 15000);
}
}
// Run the script and output the result
await dsTaggerChain();
%>DeformattedTile Doc Seal 0.9 - Digest & Seal - Current Document.md
<%*
// Doc Seal 0.9 for Obsidian Templater
// Version 0.9.7
/* * *Preserve Specs for Tile and Blockchain formats* * *
Tile Spec:
- Structure `###### #Digested-Tile #ds/{deformat-digest}/{YYYY-MM-DD}\nAuthors:: {authors}\nLicense:: {license}\nDigest Root:: {digestRootHash}\n###### #MarkdownTile\n{tile}\n###### #DeformattedTile\n{deformatted-tile}\n###### #EOT\n---\n`
- Location: `x/ds/tiles/{deformat-digest}.md`
- Upsert Logic: Skip (with Notice message) if `#ds/{deformat-digest}/{YYYY-MM-DD}` exists, append otherwise
Blockchain Spec:
- Structure: `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${YYYY-MM-DDTHH:mm}\n${digestTags.join(' ')}\n#ds/block/{currentBlockchainEntryDigest}`
- Location: `x/ds/blockchains/wwbc-{YY-MM}.md`
- Blockchain Logic: {previousBlockchainEntryDigest} is a hash of {YY-MM} for initial block or the BlockchainEntryDigest of the previous entry; if there are no "wwbc-....md" files yet, use the hash of the YY-MM, if there are not blocks in this months file yet, use the last #ds/block from the previous month, otherwise, use the last #ds/block in the current month's file
Script Spec:
- use Obsidian Templater scripting language for the script
- use tp.user.updateFrontMatter to update frontmatter
- 15s Notice messages about updates, 3 messages: status, tiles, and blockchain
- tp.user scripts: computeSHA256(content, length = 12); splitIntoTiles(content); ensureDirectoryExists(path); upsertToFile(filePath, header, content); updateFrontMatter(file, updates); getPreviousBlockchainEntryDigest(app, computeSHA256);
- inline helper functions: createDigestTag(hash, date); createDigestRootHash(digestTags);
*/
function createDigestTag(hash, date) {
return `#ds/${hash}/${date}`;
}
function createDigestRootHash(digestTags) {
return tp.user.computeSHA256(digestTags.join(' '), 12);
}
// Main function
async function dsTaggerChain() {
const version = "0.9.7";
const startTime = Date.now();
const currentDate = new Date().toISOString().split('T')[0];
const currentTimestamp = new Date().toISOString();
console.log(`[${currentDate}] DS Tagger Chain v${version} started`);
// Configuration
const tileDirectoryPath = "x/ds/tiles";
const blockchainDirectoryPath = "x/ds/blockchains";
try {
// Ensure directories exist
await tp.user.ensureDirectoryExists(tileDirectoryPath);
await tp.user.ensureDirectoryExists(blockchainDirectoryPath);
let content = tp.file.content;
const fileName = tp.file.title;
const currentFile = tp.file.find_tfile(fileName);
if (typeof content !== 'string') {
throw new Error('Received non-string content');
}
const authors = tp.frontmatter.authors || 'Unknown';
const license = tp.frontmatter.license || 'Unspecified';
console.log(`[${currentDate}] Authors extracted: ${authors}`);
console.log(`[${currentDate}] License extracted: ${license}`);
console.log(`[${currentDate}] File content length: ${content.length} characters`);
const { frontmatter, tiles } = tp.user.splitIntoTiles(content);
console.log(`[${currentDate}] Number of tiles: ${tiles.length}`);
let processedTiles = [];
let digestedTiles = 0;
let nonDigestedTiles = 0;
let updatedTiles = 0;
let digestTags = [];
let tileFilesUpdated = {};
for (let i = 0; i < tiles.length; i++) {
let tile = tiles[i];
const tileHash = tp.user.computeSHA256(tile);
console.log(`\n[${currentDate}] Processing tile ${i + 1} (${tileHash})`);
let existingDigestMatch = tile.match(/\s*(#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2})/);
let existingDigest = existingDigestMatch ? existingDigestMatch[1] : null;
console.log(`Existing Digest Tag: ${existingDigest || 'None'}`);
let cleanTile = tile.replace(/\s*#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2}/, '').trim();
let { deformattedContent, charactersRemoved } = tp.user.deformatTile(cleanTile);
let digest = tp.user.computeSHA256(deformattedContent);
let digestTag = createDigestTag(digest, currentDate);
console.log(`New Digest Tag: ${digestTag}`);
if (existingDigest && existingDigest.includes(digest)) {
console.log(`Content unchanged for tile ${tileHash}. Keeping existing Digest Tag.`);
digestTag = existingDigest;
nonDigestedTiles++;
// new Notice(`Skipping unchanged tile: ${digestTag}`, 15000);
} else {
console.log(`Content changed or new for tile ${tileHash}. Updating Digest Tag.`);
if (existingDigest) {
updatedTiles++;
} else {
digestedTiles++;
}
}
let processedTile = `${cleanTile} ${digestTag}`;
processedTiles.push(processedTile);
digestTags.push(digestTag);
console.log(`Tile ${tileHash} stats: Characters removed: ${charactersRemoved}`);
const tileFilePath = `${tileDirectoryPath}/${digest}.md`;
const digestRootHash = createDigestRootHash(digestTags);
const tileFileContent = `###### #Digested-Tile ${digestTag}
Authors:: ${authors}
License:: ${license}
Digest Root:: ${digestRootHash}
#MarkdownTile
${cleanTile}
#DeformattedTile
${deformattedContent}
#EOT
---`;
const { status: tileUpdateStatus, file: tileFile } = await tp.user.upsertToFile(tileFilePath, `###### #Digested-Tile ${digestTag}`, tileFileContent);
tileFilesUpdated[tileFilePath] = tileUpdateStatus;
// Update tile file frontmatter
if (tileFile) {
await tp.user.updateFrontMatter(tileFile, {
aliases: [digestTag],
authors: authors,
license: license,
'digest-root': digestRootHash
});
}
}
let result = frontmatter + '\n' + processedTiles.join('\n\n');
const yearMonth = currentDate.slice(2, 7);
let digestRootHash = createDigestRootHash(digestTags);
console.log(`\n[${currentDate}] Digest Root hash created: ${digestRootHash}`);
// Modify the current file content
await app.vault.modify(currentFile, result);
// Update current file frontmatter using tp.user.updateFrontMatter after modifying content
await tp.user.updateFrontMatter(currentFile, {
aliases: [`#ds/root/${digestRootHash}`],
'blockchain_last_digest_root': `#ds/root/${digestRootHash}`,
'blockchain_digest_timestamp': currentTimestamp,
'blockchain_file': `[[wwbc-${yearMonth}]]`
});
// Update blockchain file
const blockchainFilePath = `${blockchainDirectoryPath}/wwbc-${yearMonth}.md`;
const previousBlockchainEntryDigest = await tp.user.getPreviousBlockchainEntryDigest(app, blockchainDirectoryPath, tp.user.computeSHA256);
console.log(`Previous blockchain entry digest: ${previousBlockchainEntryDigest}`);
// Create the blockchain content without the final hash
const blockchainContentWithoutHash = `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}
${digestTags.join(' ')}`.trim();
// Generate the hash for the blockchain entry
const blockchainEntryHash = tp.user.computeSHA256(blockchainContentWithoutHash);
// Create the final blockchain content
const blockchainFileContent = `${blockchainContentWithoutHash}
#ds/block/${blockchainEntryHash}`;
const { status: blockchainUpdateStatus, file: blockchainFile } = await tp.user.upsertToFile(blockchainFilePath, `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}`, blockchainFileContent);
if (blockchainFile) {
await tp.user.updateFrontMatter(blockchainFile, {
cssclasses: [`locked`]
});
}
if (blockchainUpdateStatus === 'updated') {
console.log(`Updated blockchain file: ${blockchainFilePath}`);
} else {
console.log(`Blockchain file already up to date: ${blockchainFilePath}`);
}
const endTime = Date.now();
const runtime = ((endTime - startTime) / 1000).toFixed(2);
console.log(`\n[${currentDate}] DS Tagger Chain process completed successfully`);
const statusMessage = `DS Tagger Chain v${version} completed:
Runtime: ${runtime}s
#ds/root/${digestRootHash}
Tiles processed: ${tiles.length}
Tiles digested: ${digestedTiles}
Tiles not digested: ${nonDigestedTiles}
Tiles updated: ${updatedTiles}
Date: ${currentDate}`;
const tileFilesMessage = `Tile files updated (BUGY):
${Object.entries(tileFilesUpdated).map(([file, status]) => `${file}: ${status}`).join('\n')}`;
const blockchainEntryMessage = `Blockchain entry (${blockchainUpdateStatus}):
${blockchainFileContent}`;
console.log(statusMessage);
console.log(tileFilesMessage);
console.log(blockchainEntryMessage);
new Notice(statusMessage, 15000);
new Notice(tileFilesMessage, 15000);
new Notice(blockchainEntryMessage, 15000);
} catch (error) {
console.error(`[${currentDate}] An error occurred:`, error);
new Notice(`Error in DS Tagger Chain v${version}: ${error.message}. Check console for details.`, 15000);
}
}
// Run the script and output the result
await dsTaggerChain();
%>EOT
EOT
DeformattedTile Doc Seal 0.9 - Digest & Seal - Current Document.md
<%*
// Doc Seal 0.9 for Obsidian Templater
// Version 0.9.7
/* * *Preserve Specs for Tile and Blockchain formats* * *
Tile Spec:
- Structure `###### #Digested-Tile #ds/{deformat-digest}/{YYYY-MM-DD}\nAuthors:: {authors}\nLicense:: {license}\nDigest Root:: {digestRootHash}\n###### #MarkdownTile\n{tile}\n###### #DeformattedTile\n{deformatted-tile}\n###### #EOT\n---\n`
- Location: `x/ds/tiles/{deformat-digest}.md`
- Upsert Logic: Skip (with Notice message) if `#ds/{deformat-digest}/{YYYY-MM-DD}` exists, append otherwise
Blockchain Spec:
- Structure: `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${YYYY-MM-DDTHH:mm}\n${digestTags.join(' ')}\n#ds/block/{currentBlockchainEntryDigest}`
- Location: `x/ds/blockchains/wwbc-{YY-MM}.md`
- Blockchain Logic: {previousBlockchainEntryDigest} is a hash of {YY-MM} for initial block or the BlockchainEntryDigest of the previous entry; if there are no "wwbc-....md" files yet, use the hash of the YY-MM, if there are not blocks in this months file yet, use the last #ds/block from the previous month, otherwise, use the last #ds/block in the current month's file
Script Spec:
- use Obsidian Templater scripting language for the script
- use tp.user.updateFrontMatter to update frontmatter
- 15s Notice messages about updates, 3 messages: status, tiles, and blockchain
- tp.user scripts: computeSHA256(content, length = 12); splitIntoTiles(content); ensureDirectoryExists(path); upsertToFile(filePath, header, content); updateFrontMatter(file, updates); getPreviousBlockchainEntryDigest(app, computeSHA256);
- inline helper functions: createDigestTag(hash, date); createDigestRootHash(digestTags);
*/
function createDigestTag(hash, date) {
return `#ds/${hash}/${date}`;
}
function createDigestRootHash(digestTags) {
return tp.user.computeSHA256(digestTags.join(' '), 12);
}
// Main function
async function dsTaggerChain() {
const version = "0.9.7";
const startTime = Date.now();
const currentDate = new Date().toISOString().split('T')[0];
const currentTimestamp = new Date().toISOString();
console.log(`[${currentDate}] DS Tagger Chain v${version} started`);
// Configuration
const tileDirectoryPath = "x/ds/tiles";
const blockchainDirectoryPath = "x/ds/blockchains";
try {
// Ensure directories exist
await tp.user.ensureDirectoryExists(tileDirectoryPath);
await tp.user.ensureDirectoryExists(blockchainDirectoryPath);
let content = tp.file.content;
const fileName = tp.file.title;
const currentFile = tp.file.find_tfile(fileName);
if (typeof content !== 'string') {
throw new Error('Received non-string content');
}
const authors = tp.frontmatter.authors || 'Unknown';
const license = tp.frontmatter.license || 'Unspecified';
console.log(`[${currentDate}] Authors extracted: ${authors}`);
console.log(`[${currentDate}] License extracted: ${license}`);
console.log(`[${currentDate}] File content length: ${content.length} characters`);
const { frontmatter, tiles } = tp.user.splitIntoTiles(content);
console.log(`[${currentDate}] Number of tiles: ${tiles.length}`);
let processedTiles = [];
let digestedTiles = 0;
let nonDigestedTiles = 0;
let updatedTiles = 0;
let digestTags = [];
let tileFilesUpdated = {};
for (let i = 0; i < tiles.length; i++) {
let tile = tiles[i];
const tileHash = tp.user.computeSHA256(tile);
console.log(`\n[${currentDate}] Processing tile ${i + 1} (${tileHash})`);
let existingDigestMatch = tile.match(/\s*(#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2})/);
let existingDigest = existingDigestMatch ? existingDigestMatch[1] : null;
console.log(`Existing Digest Tag: ${existingDigest || 'None'}`);
let cleanTile = tile.replace(/\s*#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2}/, '').trim();
let { deformattedContent, charactersRemoved } = tp.user.deformatTile(cleanTile);
let digest = tp.user.computeSHA256(deformattedContent);
let digestTag = createDigestTag(digest, currentDate);
console.log(`New Digest Tag: ${digestTag}`);
if (existingDigest && existingDigest.includes(digest)) {
console.log(`Content unchanged for tile ${tileHash}. Keeping existing Digest Tag.`);
digestTag = existingDigest;
nonDigestedTiles++;
// new Notice(`Skipping unchanged tile: ${digestTag}`, 15000);
} else {
console.log(`Content changed or new for tile ${tileHash}. Updating Digest Tag.`);
if (existingDigest) {
updatedTiles++;
} else {
digestedTiles++;
}
}
let processedTile = `${cleanTile} ${digestTag}`;
processedTiles.push(processedTile);
digestTags.push(digestTag);
console.log(`Tile ${tileHash} stats: Characters removed: ${charactersRemoved}`);
const tileFilePath = `${tileDirectoryPath}/${digest}.md`;
const digestRootHash = createDigestRootHash(digestTags);
const tileFileContent = `###### #Digested-Tile ${digestTag}
Authors:: ${authors}
License:: ${license}
Digest Root:: ${digestRootHash}
#MarkdownTile
${cleanTile}
#DeformattedTile
${deformattedContent}
#EOT
---`;
const { status: tileUpdateStatus, file: tileFile } = await tp.user.upsertToFile(tileFilePath, `###### #Digested-Tile ${digestTag}`, tileFileContent);
tileFilesUpdated[tileFilePath] = tileUpdateStatus;
// Update tile file frontmatter
if (tileFile) {
await tp.user.updateFrontMatter(tileFile, {
aliases: [digestTag],
authors: authors,
license: license,
'digest-root': digestRootHash
});
}
}
let result = frontmatter + '\n' + processedTiles.join('\n\n');
const yearMonth = currentDate.slice(2, 7);
let digestRootHash = createDigestRootHash(digestTags);
console.log(`\n[${currentDate}] Digest Root hash created: ${digestRootHash}`);
// Modify the current file content
await app.vault.modify(currentFile, result);
// Update current file frontmatter using tp.user.updateFrontMatter after modifying content
await tp.user.updateFrontMatter(currentFile, {
aliases: [`#ds/root/${digestRootHash}`],
'blockchain_last_digest_root': `#ds/root/${digestRootHash}`,
'blockchain_digest_timestamp': currentTimestamp,
'blockchain_file': `[[wwbc-${yearMonth}]]`
});
// Update blockchain file
const blockchainFilePath = `${blockchainDirectoryPath}/wwbc-${yearMonth}.md`;
const previousBlockchainEntryDigest = await tp.user.getPreviousBlockchainEntryDigest(app, blockchainDirectoryPath, tp.user.computeSHA256);
console.log(`Previous blockchain entry digest: ${previousBlockchainEntryDigest}`);
// Create the blockchain content without the final hash
const blockchainContentWithoutHash = `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}
${digestTags.join(' ')}`.trim();
// Generate the hash for the blockchain entry
const blockchainEntryHash = tp.user.computeSHA256(blockchainContentWithoutHash);
// Create the final blockchain content
const blockchainFileContent = `${blockchainContentWithoutHash}
#ds/block/${blockchainEntryHash}`;
const { status: blockchainUpdateStatus, file: blockchainFile } = await tp.user.upsertToFile(blockchainFilePath, `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}`, blockchainFileContent);
if (blockchainFile) {
await tp.user.updateFrontMatter(blockchainFile, {
cssclasses: [`locked`]
});
}
if (blockchainUpdateStatus === 'updated') {
console.log(`Updated blockchain file: ${blockchainFilePath}`);
} else {
console.log(`Blockchain file already up to date: ${blockchainFilePath}`);
}
const endTime = Date.now();
const runtime = ((endTime - startTime) / 1000).toFixed(2);
console.log(`\n[${currentDate}] DS Tagger Chain process completed successfully`);
const statusMessage = `DS Tagger Chain v${version} completed:
Runtime: ${runtime}s
#ds/root/${digestRootHash}
Tiles processed: ${tiles.length}
Tiles digested: ${digestedTiles}
Tiles not digested: ${nonDigestedTiles}
Tiles updated: ${updatedTiles}
Date: ${currentDate}`;
const tileFilesMessage = `Tile files updated (BUGY):
${Object.entries(tileFilesUpdated).map(([file, status]) => `${file}: ${status}`).join('\n')}`;
const blockchainEntryMessage = `Blockchain entry (${blockchainUpdateStatus}):
${blockchainFileContent}`;
console.log(statusMessage);
console.log(tileFilesMessage);
console.log(blockchainEntryMessage);
new Notice(statusMessage, 15000);
new Notice(tileFilesMessage, 15000);
new Notice(blockchainEntryMessage, 15000);
} catch (error) {
console.error(`[${currentDate}] An error occurred:`, error);
new Notice(`Error in DS Tagger Chain v${version}: ${error.message}. Check console for details.`, 15000);
}
}
// Run the script and output the result
await dsTaggerChain();
%>DeformattedTile Doc Seal 0.9 - Digest & Seal - Current Document.md
<%*
// Doc Seal 0.9 for Obsidian Templater
// Version 0.9.7
/* * *Preserve Specs for Tile and Blockchain formats* * *
Tile Spec:
- Structure `###### #Digested-Tile #ds/{deformat-digest}/{YYYY-MM-DD}\nAuthors:: {authors}\nLicense:: {license}\nDigest Root:: {digestRootHash}\n###### #MarkdownTile\n{tile}\n###### #DeformattedTile\n{deformatted-tile}\n###### #EOT\n---\n`
- Location: `x/ds/tiles/{deformat-digest}.md`
- Upsert Logic: Skip (with Notice message) if `#ds/{deformat-digest}/{YYYY-MM-DD}` exists, append otherwise
Blockchain Spec:
- Structure: `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${YYYY-MM-DDTHH:mm}\n${digestTags.join(' ')}\n#ds/block/{currentBlockchainEntryDigest}`
- Location: `x/ds/blockchains/wwbc-{YY-MM}.md`
- Blockchain Logic: {previousBlockchainEntryDigest} is a hash of {YY-MM} for initial block or the BlockchainEntryDigest of the previous entry; if there are no "wwbc-....md" files yet, use the hash of the YY-MM, if there are not blocks in this months file yet, use the last #ds/block from the previous month, otherwise, use the last #ds/block in the current month's file
Script Spec:
- use Obsidian Templater scripting language for the script
- use tp.user.updateFrontMatter to update frontmatter
- 15s Notice messages about updates, 3 messages: status, tiles, and blockchain
- tp.user scripts: computeSHA256(content, length = 12); splitIntoTiles(content); ensureDirectoryExists(path); upsertToFile(filePath, header, content); updateFrontMatter(file, updates); getPreviousBlockchainEntryDigest(app, computeSHA256);
- inline helper functions: createDigestTag(hash, date); createDigestRootHash(digestTags);
*/
function createDigestTag(hash, date) {
return `#ds/${hash}/${date}`;
}
function createDigestRootHash(digestTags) {
return tp.user.computeSHA256(digestTags.join(' '), 12);
}
// Main function
async function dsTaggerChain() {
const version = "0.9.7";
const startTime = Date.now();
const currentDate = new Date().toISOString().split('T')[0];
const currentTimestamp = new Date().toISOString();
console.log(`[${currentDate}] DS Tagger Chain v${version} started`);
// Configuration
const tileDirectoryPath = "x/ds/tiles";
const blockchainDirectoryPath = "x/ds/blockchains";
try {
// Ensure directories exist
await tp.user.ensureDirectoryExists(tileDirectoryPath);
await tp.user.ensureDirectoryExists(blockchainDirectoryPath);
let content = tp.file.content;
const fileName = tp.file.title;
const currentFile = tp.file.find_tfile(fileName);
if (typeof content !== 'string') {
throw new Error('Received non-string content');
}
const authors = tp.frontmatter.authors || 'Unknown';
const license = tp.frontmatter.license || 'Unspecified';
console.log(`[${currentDate}] Authors extracted: ${authors}`);
console.log(`[${currentDate}] License extracted: ${license}`);
console.log(`[${currentDate}] File content length: ${content.length} characters`);
const { frontmatter, tiles } = tp.user.splitIntoTiles(content);
console.log(`[${currentDate}] Number of tiles: ${tiles.length}`);
let processedTiles = [];
let digestedTiles = 0;
let nonDigestedTiles = 0;
let updatedTiles = 0;
let digestTags = [];
let tileFilesUpdated = {};
for (let i = 0; i < tiles.length; i++) {
let tile = tiles[i];
const tileHash = tp.user.computeSHA256(tile);
console.log(`\n[${currentDate}] Processing tile ${i + 1} (${tileHash})`);
let existingDigestMatch = tile.match(/\s*(#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2})/);
let existingDigest = existingDigestMatch ? existingDigestMatch[1] : null;
console.log(`Existing Digest Tag: ${existingDigest || 'None'}`);
let cleanTile = tile.replace(/\s*#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2}/, '').trim();
let { deformattedContent, charactersRemoved } = tp.user.deformatTile(cleanTile);
let digest = tp.user.computeSHA256(deformattedContent);
let digestTag = createDigestTag(digest, currentDate);
console.log(`New Digest Tag: ${digestTag}`);
if (existingDigest && existingDigest.includes(digest)) {
console.log(`Content unchanged for tile ${tileHash}. Keeping existing Digest Tag.`);
digestTag = existingDigest;
nonDigestedTiles++;
// new Notice(`Skipping unchanged tile: ${digestTag}`, 15000);
} else {
console.log(`Content changed or new for tile ${tileHash}. Updating Digest Tag.`);
if (existingDigest) {
updatedTiles++;
} else {
digestedTiles++;
}
}
let processedTile = `${cleanTile} ${digestTag}`;
processedTiles.push(processedTile);
digestTags.push(digestTag);
console.log(`Tile ${tileHash} stats: Characters removed: ${charactersRemoved}`);
const tileFilePath = `${tileDirectoryPath}/${digest}.md`;
const digestRootHash = createDigestRootHash(digestTags);
const tileFileContent = `###### #Digested-Tile ${digestTag}
Authors:: ${authors}
License:: ${license}
Digest Root:: ${digestRootHash}
#MarkdownTile
${cleanTile}
#DeformattedTile
${deformattedContent}
#EOT
---`;
const { status: tileUpdateStatus, file: tileFile } = await tp.user.upsertToFile(tileFilePath, `###### #Digested-Tile ${digestTag}`, tileFileContent);
tileFilesUpdated[tileFilePath] = tileUpdateStatus;
// Update tile file frontmatter
if (tileFile) {
await tp.user.updateFrontMatter(tileFile, {
aliases: [digestTag],
authors: authors,
license: license,
'digest-root': digestRootHash
});
}
}
let result = frontmatter + '\n' + processedTiles.join('\n\n');
const yearMonth = currentDate.slice(2, 7);
let digestRootHash = createDigestRootHash(digestTags);
console.log(`\n[${currentDate}] Digest Root hash created: ${digestRootHash}`);
// Modify the current file content
await app.vault.modify(currentFile, result);
// Update current file frontmatter using tp.user.updateFrontMatter after modifying content
await tp.user.updateFrontMatter(currentFile, {
aliases: [`#ds/root/${digestRootHash}`],
'blockchain_last_digest_root': `#ds/root/${digestRootHash}`,
'blockchain_digest_timestamp': currentTimestamp,
'blockchain_file': `[[wwbc-${yearMonth}]]`
});
// Update blockchain file
const blockchainFilePath = `${blockchainDirectoryPath}/wwbc-${yearMonth}.md`;
const previousBlockchainEntryDigest = await tp.user.getPreviousBlockchainEntryDigest(app, blockchainDirectoryPath, tp.user.computeSHA256);
console.log(`Previous blockchain entry digest: ${previousBlockchainEntryDigest}`);
// Create the blockchain content without the final hash
const blockchainContentWithoutHash = `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}
${digestTags.join(' ')}`.trim();
// Generate the hash for the blockchain entry
const blockchainEntryHash = tp.user.computeSHA256(blockchainContentWithoutHash);
// Create the final blockchain content
const blockchainFileContent = `${blockchainContentWithoutHash}
#ds/block/${blockchainEntryHash}`;
const { status: blockchainUpdateStatus, file: blockchainFile } = await tp.user.upsertToFile(blockchainFilePath, `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}`, blockchainFileContent);
if (blockchainFile) {
await tp.user.updateFrontMatter(blockchainFile, {
cssclasses: [`locked`]
});
}
if (blockchainUpdateStatus === 'updated') {
console.log(`Updated blockchain file: ${blockchainFilePath}`);
} else {
console.log(`Blockchain file already up to date: ${blockchainFilePath}`);
}
const endTime = Date.now();
const runtime = ((endTime - startTime) / 1000).toFixed(2);
console.log(`\n[${currentDate}] DS Tagger Chain process completed successfully`);
const statusMessage = `DS Tagger Chain v${version} completed:
Runtime: ${runtime}s
#ds/root/${digestRootHash}
Tiles processed: ${tiles.length}
Tiles digested: ${digestedTiles}
Tiles not digested: ${nonDigestedTiles}
Tiles updated: ${updatedTiles}
Date: ${currentDate}`;
const tileFilesMessage = `Tile files updated (BUGY):
${Object.entries(tileFilesUpdated).map(([file, status]) => `${file}: ${status}`).join('\n')}`;
const blockchainEntryMessage = `Blockchain entry (${blockchainUpdateStatus}):
${blockchainFileContent}`;
console.log(statusMessage);
console.log(tileFilesMessage);
console.log(blockchainEntryMessage);
new Notice(statusMessage, 15000);
new Notice(tileFilesMessage, 15000);
new Notice(blockchainEntryMessage, 15000);
} catch (error) {
console.error(`[${currentDate}] An error occurred:`, error);
new Notice(`Error in DS Tagger Chain v${version}: ${error.message}. Check console for details.`, 15000);
}
}
// Run the script and output the result
await dsTaggerChain();
%>EOT
DeformattedTile Doc Seal 0.9 - Digest & Seal - Current Document.md
<%*
// Doc Seal 0.9 for Obsidian Templater
// Version 0.9.7
/* * *Preserve Specs for Tile and Blockchain formats* * *
Tile Spec:
- Structure `###### #Digested-Tile #ds/{deformat-digest}/{YYYY-MM-DD}\nAuthors:: {authors}\nLicense:: {license}\nDigest Root:: {digestRootHash}\n###### #MarkdownTile\n{tile}\n###### #DeformattedTile\n{deformatted-tile}\n###### #EOT\n---\n`
- Location: `x/ds/tiles/{deformat-digest}.md`
- Upsert Logic: Skip (with Notice message) if `#ds/{deformat-digest}/{YYYY-MM-DD}` exists, append otherwise
Blockchain Spec:
- Structure: `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${YYYY-MM-DDTHH:mm}\n${digestTags.join(' ')}\n#ds/block/{currentBlockchainEntryDigest}`
- Location: `x/ds/blockchains/wwbc-{YY-MM}.md`
- Blockchain Logic: {previousBlockchainEntryDigest} is a hash of {YY-MM} for initial block or the BlockchainEntryDigest of the previous entry; if there are no "wwbc-....md" files yet, use the hash of the YY-MM, if there are not blocks in this months file yet, use the last #ds/block from the previous month, otherwise, use the last #ds/block in the current month's file
Script Spec:
- use Obsidian Templater scripting language for the script
- use tp.user.updateFrontMatter to update frontmatter
- 15s Notice messages about updates, 3 messages: status, tiles, and blockchain
- tp.user scripts: computeSHA256(content, length = 12); splitIntoTiles(content); ensureDirectoryExists(path); upsertToFile(filePath, header, content); updateFrontMatter(file, updates); getPreviousBlockchainEntryDigest(app, computeSHA256);
- inline helper functions: createDigestTag(hash, date); createDigestRootHash(digestTags);
*/
function createDigestTag(hash, date) {
return `#ds/${hash}/${date}`;
}
function createDigestRootHash(digestTags) {
return tp.user.computeSHA256(digestTags.join(' '), 12);
}
// Main function
async function dsTaggerChain() {
const version = "0.9.7";
const startTime = Date.now();
const currentDate = new Date().toISOString().split('T')[0];
const currentTimestamp = new Date().toISOString();
console.log(`[${currentDate}] DS Tagger Chain v${version} started`);
// Configuration
const tileDirectoryPath = "x/ds/tiles";
const blockchainDirectoryPath = "x/ds/blockchains";
try {
// Ensure directories exist
await tp.user.ensureDirectoryExists(tileDirectoryPath);
await tp.user.ensureDirectoryExists(blockchainDirectoryPath);
let content = tp.file.content;
const fileName = tp.file.title;
const currentFile = tp.file.find_tfile(fileName);
if (typeof content !== 'string') {
throw new Error('Received non-string content');
}
const authors = tp.frontmatter.authors || 'Unknown';
const license = tp.frontmatter.license || 'Unspecified';
console.log(`[${currentDate}] Authors extracted: ${authors}`);
console.log(`[${currentDate}] License extracted: ${license}`);
console.log(`[${currentDate}] File content length: ${content.length} characters`);
const { frontmatter, tiles } = tp.user.splitIntoTiles(content);
console.log(`[${currentDate}] Number of tiles: ${tiles.length}`);
let processedTiles = [];
let digestedTiles = 0;
let nonDigestedTiles = 0;
let updatedTiles = 0;
let digestTags = [];
let tileFilesUpdated = {};
for (let i = 0; i < tiles.length; i++) {
let tile = tiles[i];
const tileHash = tp.user.computeSHA256(tile);
console.log(`\n[${currentDate}] Processing tile ${i + 1} (${tileHash})`);
let existingDigestMatch = tile.match(/\s*(#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2})/);
let existingDigest = existingDigestMatch ? existingDigestMatch[1] : null;
console.log(`Existing Digest Tag: ${existingDigest || 'None'}`);
let cleanTile = tile.replace(/\s*#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2}/, '').trim();
let { deformattedContent, charactersRemoved } = tp.user.deformatTile(cleanTile);
let digest = tp.user.computeSHA256(deformattedContent);
let digestTag = createDigestTag(digest, currentDate);
console.log(`New Digest Tag: ${digestTag}`);
if (existingDigest && existingDigest.includes(digest)) {
console.log(`Content unchanged for tile ${tileHash}. Keeping existing Digest Tag.`);
digestTag = existingDigest;
nonDigestedTiles++;
// new Notice(`Skipping unchanged tile: ${digestTag}`, 15000);
} else {
console.log(`Content changed or new for tile ${tileHash}. Updating Digest Tag.`);
if (existingDigest) {
updatedTiles++;
} else {
digestedTiles++;
}
}
let processedTile = `${cleanTile} ${digestTag}`;
processedTiles.push(processedTile);
digestTags.push(digestTag);
console.log(`Tile ${tileHash} stats: Characters removed: ${charactersRemoved}`);
const tileFilePath = `${tileDirectoryPath}/${digest}.md`;
const digestRootHash = createDigestRootHash(digestTags);
const tileFileContent = `###### #Digested-Tile ${digestTag}
Authors:: ${authors}
License:: ${license}
Digest Root:: ${digestRootHash}
#MarkdownTile
${cleanTile}
#DeformattedTile
${deformattedContent}
#EOT
---`;
const { status: tileUpdateStatus, file: tileFile } = await tp.user.upsertToFile(tileFilePath, `###### #Digested-Tile ${digestTag}`, tileFileContent);
tileFilesUpdated[tileFilePath] = tileUpdateStatus;
// Update tile file frontmatter
if (tileFile) {
await tp.user.updateFrontMatter(tileFile, {
aliases: [digestTag],
authors: authors,
license: license,
'digest-root': digestRootHash
});
}
}
let result = frontmatter + '\n' + processedTiles.join('\n\n');
const yearMonth = currentDate.slice(2, 7);
let digestRootHash = createDigestRootHash(digestTags);
console.log(`\n[${currentDate}] Digest Root hash created: ${digestRootHash}`);
// Modify the current file content
await app.vault.modify(currentFile, result);
// Update current file frontmatter using tp.user.updateFrontMatter after modifying content
await tp.user.updateFrontMatter(currentFile, {
aliases: [`#ds/root/${digestRootHash}`],
'blockchain_last_digest_root': `#ds/root/${digestRootHash}`,
'blockchain_digest_timestamp': currentTimestamp,
'blockchain_file': `[[wwbc-${yearMonth}]]`
});
// Update blockchain file
const blockchainFilePath = `${blockchainDirectoryPath}/wwbc-${yearMonth}.md`;
const previousBlockchainEntryDigest = await tp.user.getPreviousBlockchainEntryDigest(app, blockchainDirectoryPath, tp.user.computeSHA256);
console.log(`Previous blockchain entry digest: ${previousBlockchainEntryDigest}`);
// Create the blockchain content without the final hash
const blockchainContentWithoutHash = `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}
${digestTags.join(' ')}`.trim();
// Generate the hash for the blockchain entry
const blockchainEntryHash = tp.user.computeSHA256(blockchainContentWithoutHash);
// Create the final blockchain content
const blockchainFileContent = `${blockchainContentWithoutHash}
#ds/block/${blockchainEntryHash}`;
const { status: blockchainUpdateStatus, file: blockchainFile } = await tp.user.upsertToFile(blockchainFilePath, `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}`, blockchainFileContent);
if (blockchainFile) {
await tp.user.updateFrontMatter(blockchainFile, {
cssclasses: [`locked`]
});
}
if (blockchainUpdateStatus === 'updated') {
console.log(`Updated blockchain file: ${blockchainFilePath}`);
} else {
console.log(`Blockchain file already up to date: ${blockchainFilePath}`);
}
const endTime = Date.now();
const runtime = ((endTime - startTime) / 1000).toFixed(2);
console.log(`\n[${currentDate}] DS Tagger Chain process completed successfully`);
const statusMessage = `DS Tagger Chain v${version} completed:
Runtime: ${runtime}s
#ds/root/${digestRootHash}
Tiles processed: ${tiles.length}
Tiles digested: ${digestedTiles}
Tiles not digested: ${nonDigestedTiles}
Tiles updated: ${updatedTiles}
Date: ${currentDate}`;
const tileFilesMessage = `Tile files updated (BUGY):
${Object.entries(tileFilesUpdated).map(([file, status]) => `${file}: ${status}`).join('\n')}`;
const blockchainEntryMessage = `Blockchain entry (${blockchainUpdateStatus}):
${blockchainFileContent}`;
console.log(statusMessage);
console.log(tileFilesMessage);
console.log(blockchainEntryMessage);
new Notice(statusMessage, 15000);
new Notice(tileFilesMessage, 15000);
new Notice(blockchainEntryMessage, 15000);
} catch (error) {
console.error(`[${currentDate}] An error occurred:`, error);
new Notice(`Error in DS Tagger Chain v${version}: ${error.message}. Check console for details.`, 15000);
}
}
// Run the script and output the result
await dsTaggerChain();
%>DeformattedTile Doc Seal 0.9 - Digest & Seal - Current Document.md
<%*
// Doc Seal 0.9 for Obsidian Templater
// Version 0.9.7
/* * *Preserve Specs for Tile and Blockchain formats* * *
Tile Spec:
- Structure `###### #Digested-Tile #ds/{deformat-digest}/{YYYY-MM-DD}\nAuthors:: {authors}\nLicense:: {license}\nDigest Root:: {digestRootHash}\n###### #MarkdownTile\n{tile}\n###### #DeformattedTile\n{deformatted-tile}\n###### #EOT\n---\n`
- Location: `x/ds/tiles/{deformat-digest}.md`
- Upsert Logic: Skip (with Notice message) if `#ds/{deformat-digest}/{YYYY-MM-DD}` exists, append otherwise
Blockchain Spec:
- Structure: `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${YYYY-MM-DDTHH:mm}\n${digestTags.join(' ')}\n#ds/block/{currentBlockchainEntryDigest}`
- Location: `x/ds/blockchains/wwbc-{YY-MM}.md`
- Blockchain Logic: {previousBlockchainEntryDigest} is a hash of {YY-MM} for initial block or the BlockchainEntryDigest of the previous entry; if there are no "wwbc-....md" files yet, use the hash of the YY-MM, if there are not blocks in this months file yet, use the last #ds/block from the previous month, otherwise, use the last #ds/block in the current month's file
Script Spec:
- use Obsidian Templater scripting language for the script
- use tp.user.updateFrontMatter to update frontmatter
- 15s Notice messages about updates, 3 messages: status, tiles, and blockchain
- tp.user scripts: computeSHA256(content, length = 12); splitIntoTiles(content); ensureDirectoryExists(path); upsertToFile(filePath, header, content); updateFrontMatter(file, updates); getPreviousBlockchainEntryDigest(app, computeSHA256);
- inline helper functions: createDigestTag(hash, date); createDigestRootHash(digestTags);
*/
function createDigestTag(hash, date) {
return `#ds/${hash}/${date}`;
}
function createDigestRootHash(digestTags) {
return tp.user.computeSHA256(digestTags.join(' '), 12);
}
// Main function
async function dsTaggerChain() {
const version = "0.9.7";
const startTime = Date.now();
const currentDate = new Date().toISOString().split('T')[0];
const currentTimestamp = new Date().toISOString();
console.log(`[${currentDate}] DS Tagger Chain v${version} started`);
// Configuration
const tileDirectoryPath = "x/ds/tiles";
const blockchainDirectoryPath = "x/ds/blockchains";
try {
// Ensure directories exist
await tp.user.ensureDirectoryExists(tileDirectoryPath);
await tp.user.ensureDirectoryExists(blockchainDirectoryPath);
let content = tp.file.content;
const fileName = tp.file.title;
const currentFile = tp.file.find_tfile(fileName);
if (typeof content !== 'string') {
throw new Error('Received non-string content');
}
const authors = tp.frontmatter.authors || 'Unknown';
const license = tp.frontmatter.license || 'Unspecified';
console.log(`[${currentDate}] Authors extracted: ${authors}`);
console.log(`[${currentDate}] License extracted: ${license}`);
console.log(`[${currentDate}] File content length: ${content.length} characters`);
const { frontmatter, tiles } = tp.user.splitIntoTiles(content);
console.log(`[${currentDate}] Number of tiles: ${tiles.length}`);
let processedTiles = [];
let digestedTiles = 0;
let nonDigestedTiles = 0;
let updatedTiles = 0;
let digestTags = [];
let tileFilesUpdated = {};
for (let i = 0; i < tiles.length; i++) {
let tile = tiles[i];
const tileHash = tp.user.computeSHA256(tile);
console.log(`\n[${currentDate}] Processing tile ${i + 1} (${tileHash})`);
let existingDigestMatch = tile.match(/\s*(#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2})/);
let existingDigest = existingDigestMatch ? existingDigestMatch[1] : null;
console.log(`Existing Digest Tag: ${existingDigest || 'None'}`);
let cleanTile = tile.replace(/\s*#ds\/[a-f0-9]+\/\d{4}-\d{2}-\d{2}/, '').trim();
let { deformattedContent, charactersRemoved } = tp.user.deformatTile(cleanTile);
let digest = tp.user.computeSHA256(deformattedContent);
let digestTag = createDigestTag(digest, currentDate);
console.log(`New Digest Tag: ${digestTag}`);
if (existingDigest && existingDigest.includes(digest)) {
console.log(`Content unchanged for tile ${tileHash}. Keeping existing Digest Tag.`);
digestTag = existingDigest;
nonDigestedTiles++;
// new Notice(`Skipping unchanged tile: ${digestTag}`, 15000);
} else {
console.log(`Content changed or new for tile ${tileHash}. Updating Digest Tag.`);
if (existingDigest) {
updatedTiles++;
} else {
digestedTiles++;
}
}
let processedTile = `${cleanTile} ${digestTag}`;
processedTiles.push(processedTile);
digestTags.push(digestTag);
console.log(`Tile ${tileHash} stats: Characters removed: ${charactersRemoved}`);
const tileFilePath = `${tileDirectoryPath}/${digest}.md`;
const digestRootHash = createDigestRootHash(digestTags);
const tileFileContent = `###### #Digested-Tile ${digestTag}
Authors:: ${authors}
License:: ${license}
Digest Root:: ${digestRootHash}
#MarkdownTile
${cleanTile}
#DeformattedTile
${deformattedContent}
#EOT
---`;
const { status: tileUpdateStatus, file: tileFile } = await tp.user.upsertToFile(tileFilePath, `###### #Digested-Tile ${digestTag}`, tileFileContent);
tileFilesUpdated[tileFilePath] = tileUpdateStatus;
// Update tile file frontmatter
if (tileFile) {
await tp.user.updateFrontMatter(tileFile, {
aliases: [digestTag],
authors: authors,
license: license,
'digest-root': digestRootHash
});
}
}
let result = frontmatter + '\n' + processedTiles.join('\n\n');
const yearMonth = currentDate.slice(2, 7);
let digestRootHash = createDigestRootHash(digestTags);
console.log(`\n[${currentDate}] Digest Root hash created: ${digestRootHash}`);
// Modify the current file content
await app.vault.modify(currentFile, result);
// Update current file frontmatter using tp.user.updateFrontMatter after modifying content
await tp.user.updateFrontMatter(currentFile, {
aliases: [`#ds/root/${digestRootHash}`],
'blockchain_last_digest_root': `#ds/root/${digestRootHash}`,
'blockchain_digest_timestamp': currentTimestamp,
'blockchain_file': `[[wwbc-${yearMonth}]]`
});
// Update blockchain file
const blockchainFilePath = `${blockchainDirectoryPath}/wwbc-${yearMonth}.md`;
const previousBlockchainEntryDigest = await tp.user.getPreviousBlockchainEntryDigest(app, blockchainDirectoryPath, tp.user.computeSHA256);
console.log(`Previous blockchain entry digest: ${previousBlockchainEntryDigest}`);
// Create the blockchain content without the final hash
const blockchainContentWithoutHash = `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}
${digestTags.join(' ')}`.trim();
// Generate the hash for the blockchain entry
const blockchainEntryHash = tp.user.computeSHA256(blockchainContentWithoutHash);
// Create the final blockchain content
const blockchainFileContent = `${blockchainContentWithoutHash}
#ds/block/${blockchainEntryHash}`;
const { status: blockchainUpdateStatus, file: blockchainFile } = await tp.user.upsertToFile(blockchainFilePath, `### [[${fileName}]] 🔒 #ds/root/${digestRootHash} chained to #ds/block/${previousBlockchainEntryDigest} on ${currentTimestamp}`, blockchainFileContent);
if (blockchainFile) {
await tp.user.updateFrontMatter(blockchainFile, {
cssclasses: [`locked`]
});
}
if (blockchainUpdateStatus === 'updated') {
console.log(`Updated blockchain file: ${blockchainFilePath}`);
} else {
console.log(`Blockchain file already up to date: ${blockchainFilePath}`);
}
const endTime = Date.now();
const runtime = ((endTime - startTime) / 1000).toFixed(2);
console.log(`\n[${currentDate}] DS Tagger Chain process completed successfully`);
const statusMessage = `DS Tagger Chain v${version} completed:
Runtime: ${runtime}s
#ds/root/${digestRootHash}
Tiles processed: ${tiles.length}
Tiles digested: ${digestedTiles}
Tiles not digested: ${nonDigestedTiles}
Tiles updated: ${updatedTiles}
Date: ${currentDate}`;
const tileFilesMessage = `Tile files updated (BUGY):
${Object.entries(tileFilesUpdated).map(([file, status]) => `${file}: ${status}`).join('\n')}`;
const blockchainEntryMessage = `Blockchain entry (${blockchainUpdateStatus}):
${blockchainFileContent}`;
console.log(statusMessage);
console.log(tileFilesMessage);
console.log(blockchainEntryMessage);
new Notice(statusMessage, 15000);
new Notice(tileFilesMessage, 15000);
new Notice(blockchainEntryMessage, 15000);
} catch (error) {
console.error(`[${currentDate}] An error occurred:`, error);
new Notice(`Error in DS Tagger Chain v${version}: ${error.message}. Check console for details.`, 15000);
}
}
// Run the script and output the result
await dsTaggerChain();
%>