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 { SQLiteDBSettings, DEFAULT_SETTINGS } from "./src/types";
|
||||||
import { pluginState } from "src/pluginState";
|
import { pluginState } from "src/pluginState";
|
||||||
|
import { registerTimestampUpdaterButton } from "src/webcomponents/TimestampUpdaterButton/registerTimestampUpdaterButton";
|
||||||
|
|
||||||
export default class SQLiteDBPlugin extends Plugin {
|
export default class SQLiteDBPlugin extends Plugin {
|
||||||
settings: SQLiteDBSettings;
|
settings: SQLiteDBSettings;
|
||||||
|
|
@ -45,6 +46,8 @@ export default class SQLiteDBPlugin extends Plugin {
|
||||||
registerTextInput(el, this.app, this.dbService);
|
registerTextInput(el, this.app, this.dbService);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
registerTimestampUpdaterButton(this);
|
||||||
|
|
||||||
//? Codeblocks
|
//? Codeblocks
|
||||||
this.registerMarkdownCodeBlockProcessor(
|
this.registerMarkdownCodeBlockProcessor(
|
||||||
"sql",
|
"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