mirror of
https://github.com/stfrigerio/sqliteDB.git
synced 2026-07-22 05:38:02 +00:00
timestamp button
This commit is contained in:
parent
cbf9d4f81d
commit
6d6759bda1
4 changed files with 170 additions and 0 deletions
3
main.ts
3
main.ts
|
|
@ -22,6 +22,7 @@ import { registerTextInput } from "src/webcomponents/TextInput/registerTextInput
|
|||
|
||||
import { SQLiteDBSettings, DEFAULT_SETTINGS } from "./src/types";
|
||||
import { pluginState } from "src/pluginState";
|
||||
import { registerTimestampUpdaterButton } from "src/webcomponents/TimestampUpdaterButton/registerTimestampUpdaterButton";
|
||||
|
||||
export default class SQLiteDBPlugin extends Plugin {
|
||||
settings: SQLiteDBSettings;
|
||||
|
|
@ -45,6 +46,8 @@ export default class SQLiteDBPlugin extends Plugin {
|
|||
registerTextInput(el, this.app, this.dbService);
|
||||
});
|
||||
|
||||
registerTimestampUpdaterButton(this);
|
||||
|
||||
//? Codeblocks
|
||||
this.registerMarkdownCodeBlockProcessor(
|
||||
"sql",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* Creates the HTMLButtonElement for the timestamp updater.
|
||||
*
|
||||
* @param onClick The async function to execute when the button is clicked.
|
||||
* @returns The created HTMLButtonElement.
|
||||
*/
|
||||
export function createTimestampButtonElement(onClick: () => Promise<void>): HTMLButtonElement {
|
||||
const button = document.createElement('button');
|
||||
button.setText('Update Timestamp');
|
||||
button.addClass('timestamp-updater-button');
|
||||
|
||||
button.style.backgroundColor = 'var(--interactive-accent)';
|
||||
button.style.color = 'var(--text-on-accent)';
|
||||
button.style.border = 'none';
|
||||
button.style.padding = '6px 12px';
|
||||
button.style.borderRadius = '4px';
|
||||
button.style.cursor = 'pointer';
|
||||
button.style.fontSize = '0.9em';
|
||||
|
||||
button.addEventListener('click', async (event) => {
|
||||
event.stopPropagation();
|
||||
button.disabled = true;
|
||||
button.style.opacity = '0.7';
|
||||
button.style.cursor = 'wait';
|
||||
try {
|
||||
await onClick();
|
||||
} finally {
|
||||
button.disabled = false;
|
||||
button.style.opacity = '1';
|
||||
button.style.cursor = 'pointer';
|
||||
}
|
||||
});
|
||||
|
||||
return button;
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
import { App, MarkdownPostProcessorContext, Notice, Plugin, TFile } from 'obsidian';
|
||||
import { updateTimestampInFile } from './timestampFileUpdater';
|
||||
import { createTimestampButtonElement } from './createTimestampButtonElement';
|
||||
|
||||
/**
|
||||
* Registers the Markdown postprocessor to find <timestamp-updater-button>
|
||||
* tags and replace them with functional buttons.
|
||||
*
|
||||
* @param plugin The Obsidian Plugin instance.
|
||||
*/
|
||||
export function registerTimestampUpdaterButton(plugin: Plugin): void {
|
||||
|
||||
plugin.registerMarkdownPostProcessor((element, context: MarkdownPostProcessorContext) => {
|
||||
const { app } = plugin;
|
||||
console.log(`Timestamp PostProcessor running for section in: ${context.sourcePath}`);
|
||||
|
||||
const placeholderElements = element.querySelectorAll('.timestamp-updater-placeholder');
|
||||
|
||||
if (placeholderElements.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
placeholderElements.forEach((placeholderEl) => {
|
||||
const handleClick = async () => {
|
||||
const activeFile = app.workspace.getActiveFile();
|
||||
|
||||
if (!activeFile || !(activeFile instanceof TFile)) {
|
||||
new Notice('No active file selected.', 3000);
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await updateTimestampInFile(app, activeFile);
|
||||
new Notice(result.message, result.success ? 2000 : 5000);
|
||||
};
|
||||
|
||||
const buttonElement = createTimestampButtonElement(handleClick);
|
||||
try {
|
||||
placeholderEl.replaceWith(buttonElement);
|
||||
} catch (e) {
|
||||
console.error("Error during replaceWith:", e);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
import { App, Notice, TFile } from 'obsidian';
|
||||
|
||||
// Regex patterns are specific to this module's responsibility
|
||||
const frontmatterRegex = /^---\s*([\s\S]*?)\s*---/;
|
||||
const updatedAtRegexLine = /^(updatedAt:\s*)(.*)$/m; // Find existing line
|
||||
const closingDashRegex = /^\s*---\s*$/; // To find the closing dashes
|
||||
|
||||
interface UpdateResult {
|
||||
success: boolean;
|
||||
message: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the file, updates the 'updatedAt' timestamp in the frontmatter manually,
|
||||
* and saves the file back.
|
||||
*
|
||||
* @param app Obsidian App instance
|
||||
* @param file The TFile to modify
|
||||
* @returns Promise resolving to an UpdateResult object
|
||||
*/
|
||||
export async function updateTimestampInFile(app: App, file: TFile): Promise<UpdateResult> {
|
||||
try {
|
||||
const content = await app.vault.read(file);
|
||||
const match = content.match(frontmatterRegex);
|
||||
|
||||
if (!match || !match[0]) {
|
||||
return { success: false, message: 'No frontmatter found in this file.' };
|
||||
}
|
||||
|
||||
const fullFrontmatterBlock = match[0];
|
||||
const frontmatterContent = match[1];
|
||||
const body = content.substring(fullFrontmatterBlock.length);
|
||||
const newTimestamp = new Date().toISOString();
|
||||
|
||||
let existingTimestamp: string | null = null;
|
||||
let updatedFrontmatterBlock: string;
|
||||
|
||||
const updatedAtMatch = frontmatterContent.match(updatedAtRegexLine);
|
||||
if (updatedAtMatch && updatedAtMatch[2]) {
|
||||
existingTimestamp = updatedAtMatch[2].trim();
|
||||
}
|
||||
|
||||
if (existingTimestamp === newTimestamp) {
|
||||
return { success: true, message: `Timestamp already up-to-date (${newTimestamp.split('T')[1].substring(0, 8)}).` };
|
||||
}
|
||||
|
||||
// Manual Update Logic
|
||||
if (updatedAtMatch) {
|
||||
// Found existing line: replace the value part
|
||||
updatedFrontmatterBlock = fullFrontmatterBlock.replace(
|
||||
updatedAtRegexLine,
|
||||
`$1${newTimestamp}`
|
||||
);
|
||||
} else {
|
||||
// Didn't find the line: Append it before the closing '---'
|
||||
const lines = fullFrontmatterBlock.trimEnd().split('\n');
|
||||
// Find the index of the closing '---' line
|
||||
const closingDashIndex = lines.findIndex(line => closingDashRegex.test(line));
|
||||
|
||||
if (closingDashIndex > 0) { // Ensure closing dashes are found and not the first line
|
||||
lines.splice(closingDashIndex, 0, `updatedAt: ${newTimestamp}`); // Insert before closing dashes
|
||||
updatedFrontmatterBlock = lines.join('\n');
|
||||
// Add back potential trailing newline if original block had one
|
||||
if (fullFrontmatterBlock.endsWith('\n') && !updatedFrontmatterBlock.endsWith('\n')) {
|
||||
updatedFrontmatterBlock += '\n';
|
||||
}
|
||||
} else {
|
||||
console.warn(`FileUpdater: Could not find closing '---' to append timestamp in ${file.basename}`);
|
||||
return { success: false, message: 'Could not reliably update frontmatter (structure error?).' };
|
||||
}
|
||||
}
|
||||
|
||||
// Reconstruct the full content
|
||||
const newContent = updatedFrontmatterBlock + body;
|
||||
|
||||
// Check if content actually changed before writing (prevents unnecessary file modifications)
|
||||
if (newContent === content) {
|
||||
return { success: true, message: `Timestamp already effectively up-to-date.` };
|
||||
}
|
||||
|
||||
await app.vault.modify(file, newContent);
|
||||
return { success: true, message: `Updated timestamp for ${file.basename}` };
|
||||
|
||||
} catch (error: any) {
|
||||
console.error(`FileUpdater: Error processing file ${file.basename}`, error);
|
||||
return { success: false, message: `Error updating timestamp: ${error.message}` };
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue