### Manage CSS Classes for Table Math in TypeScript Source: https://context7.com/eatcodeplay/obsidian-simple-table-math/llms.txt Demonstrates how the plugin applies CSS classes to table cells and rows to enable custom styling of calculated values. It covers adding classes in edit mode (creating a value div) and reading mode (applying class directly to the cell). Example CSS is provided for reference. ```typescript // Applied CSS classes: // - .stm-cell: Added to cells containing calculations // - .stm-value: Added to the display element showing the calculated result // - .stm-row: Added to rows containing any calculated cells // Example custom CSS styling: /* .stm-value { font-weight: bold; color: #4a9eff; } .stm-row { background-color: rgba(74, 158, 255, 0.1); } .stm-row.off { background-color: transparent; } .stm-cell { text-align: right; } */ // The plugin dynamically manages these classes: cell.classList.add('stm-cell'); cell.tabIndex = -1; cell.closest('tr')?.classList.add(...rowClasses); // In reading mode, the cell itself becomes the value element: if (isReadingMode) { vElement = cell; cell.classList.add('stm-value'); } else { // In edit mode, a div wrapper is created: vElement = document.createElement('div'); vElement.classList.add('stm-value'); cell.prepend(vElement); } ``` -------------------------------- ### Initialize Simple Table Math Plugin Source: https://context7.com/eatcodeplay/obsidian-simple-table-math/llms.txt Initializes the Simple Table Math Obsidian plugin, loads settings, and sets up event listeners for table processing and user interactions. It uses debouncing for performance and registers handlers for keyboard navigation and editor events. ```typescript import { Plugin, MarkdownView } from 'obsidian'; export default class SimpleTableMath extends Plugin { settings: SimpleTableMathSettings; debouncedProcessing: () => void; async onload() { await this.loadSettings(); this.addSettingTab(new SettingTab(this.app, this)); // Debounced processing for performance this.debouncedProcessing = debounce(this.process.bind(this), 250); // Register event listeners workspace.onLayoutReady(() => { this.registerEvent(workspace.on('layout-change', this.debouncedProcessing)); this.registerEvent(workspace.on('editor-change', this.debouncedProcessing)); this.registerEvent(workspace.on('editor-menu', this.handleEditorMenuEvent.bind(this))); // Register keyboard navigation handlers this.keymapHandlers = [ app.scope.register(null, 'Tab', this.debouncedProcessing), app.scope.register(null, 'ArrowLeft', this.debouncedProcessing), app.scope.register(null, 'ArrowUp', this.debouncedProcessing), app.scope.register(null, 'ArrowRight', this.debouncedProcessing), app.scope.register(null, 'ArrowDown', this.debouncedProcessing), ]; this.registerDomEvent(document, 'click', this.debouncedProcessing); this.registerDomEvent(document, 'keydown', this.handleKeyDownEvent.bind(this)); }); } } ``` -------------------------------- ### Configure Plugin Settings in TypeScript Source: https://context7.com/eatcodeplay/obsidian-simple-table-math/llms.txt Defines the settings interface and the default configuration for the Simple Table Math plugin. It includes options for decimal places, locale for number formatting, and styling the last row. The `SettingTab` class implements the UI for these settings within Obsidian. ```typescript interface SimpleTableMathSettings { fractions: number; // Decimal places to display locale: string | null; // Locale code for number formatting (e.g., "en-US", "de-DE") styleLastRow: boolean; // Apply special styling to last row with calculations } const DEFAULT_SETTINGS: SimpleTableMathSettings = { fractions: 2, locale: null, styleLastRow: true, } class SettingTab extends PluginSettingTab { display(): void { new Setting(containerEl) .setName('Fractions') .setDesc('Maximum number of decimal places to display.') .addText(text => text .setValue(this.plugin.settings.fractions.toString()) .onChange(async (value) => { this.plugin.settings.fractions = parseInt(value, 10) || 0; await this.plugin.saveSettings(); })); new Setting(containerEl) .setName('Number formatting') .setDesc('Enter a locale code (e.g., en-US, de-CH) for number formatting.') .addText(text => text .setPlaceholder('e.g.: en, en-US, de-CH') .setValue(this.plugin.settings.locale || '') .onChange(async (value) => { this.plugin.settings.locale = (value === '') ? null : value; await this.plugin.saveSettings(); })); new Setting(containerEl) .setName('Highlight last row calculations') .setDesc('Enable styling for the last row in tables with calculations.') .addToggle(component => component .setValue(this.plugin.settings.styleLastRow) .onChange(async (value) => { this.plugin.settings.styleLastRow = value; await this.plugin.saveSettings(); })); } } ``` -------------------------------- ### Handle Copy to Clipboard in TypeScript Source: https://context7.com/eatcodeplay/obsidian-simple-table-math/llms.txt Implements clipboard integration for copying calculated results. It handles both keyboard shortcuts (Ctrl+C/Cmd+C) and context menu actions. Platform-specific key combinations are detected for cross-OS compatibility. The copied content is the text from the element with the class 'stm-value'. ```typescript handleKeyDownEvent(evt: KeyboardEvent) { if (this.isCopyShortcut(evt)) { this.process(); const cell = document.activeElement?.closest('td.stm-cell, th.stm-cell'); if (cell) { const value = cell.querySelector('.stm-value') as HTMLElement | null; if (value) { setTimeout(() => { navigator.clipboard.writeText(value.textContent || ''); this.showNotice('Copied!', 'copy-check'); }, 25); } } } } handleEditorMenuEvent(menu: Menu) { const cell = document.activeElement?.closest('td.stm-cell'); const value = cell?.querySelector('.stm-value') as HTMLElement | null; if (value) { menu.addItem((item: MenuItem) => { item .setTitle('Copy calculated value') .setIcon('square-equal') .onClick(async () => { navigator.clipboard.writeText(value.textContent || ''); this.showNotice('Copied!', 'copy-check'); }); }); } } isCopyShortcut(evt: KeyboardEvent) { if (Platform.isMacOS) { return evt.metaKey && evt.key === 'c' && !evt.altKey && !evt.shiftKey; } return evt.ctrlKey && evt.key === 'c' && !evt.altKey && !evt.shiftKey; } ``` -------------------------------- ### Supported Mathematical Operations - TypeScript Source: https://context7.com/eatcodeplay/obsidian-simple-table-math/llms.txt This section details the implementation of six mathematical operations (SUM, AVG, MIN, MAX, SUB, MUL) within the plugin. Each operation supports calculating results based on values collected from table cells, either from above or to the left of the operation cell. The code demonstrates how to use these operations with specific syntax in table cells. ```typescript // SUM operation - add all values // Usage in table: SUM^ (sum column above) or SUM< (sum row to left) if (operation === 'sum') { result = values.reduce((a, b) => a + b, 0); } // AVG operation - calculate average // Usage: AVG^ or AVG< else if (operation === 'avg' && values.length > 0) { result = values.reduce((a, b) => a + b, 0) / values.length; } // MIN operation - find minimum value // Usage: MIN^ or MIN< else if (operation === 'min') { result = values.length > 0 ? Math.min(...values) : 0; } // MAX operation - find maximum value // Usage: MAX^ or MAX< else if (operation === 'max') { result = values.length > 0 ? Math.max(...values) : 0; } // SUB operation - subtract subsequent values from first // Usage: SUB< (e.g., 100 - 20 - 10 = 70) else if (operation === 'sub') { result = values.length > 0 ? values.reduce((a, b) => a - b) : 0; } // MUL operation - multiply all values together // Usage: MUL< (e.g., 5 * 3 * 2 = 30) else if (operation === 'mul') { result = values.length > 1 ? values.reduce((a, b) => a * b, 1) : 0; } ``` -------------------------------- ### Format Numbers and Currency with Locale in Obsidian Simple Table Math Source: https://context7.com/eatcodeplay/obsidian-simple-table-math/llms.txt This code snippet shows how to format numerical results using internationalized number and currency formatting. It utilizes the user's locale from Obsidian settings or defaults to the system's language, supporting both decimal and currency styles with configurable fraction digits. It also handles scientific notation. ```typescript const defaultLocale = getLanguage(); // Get Obsidian's current language if (exponential) { // Scientific notation format: #e[n] where n is decimal places vElement.textContent = result.toExponential(exponential); // Example: 1234.56 with #e2 → 1.23e+3 } else { vElement.textContent = result.toLocaleString( this.settings.locale || defaultLocale, { style: currency ? 'currency' : 'decimal', currency: currency || undefined, minimumFractionDigits: this.settings.fractions, maximumFractionDigits: this.settings.fractions, } ); } ``` -------------------------------- ### Process Tables and Calculate Operations - TypeScript Source: https://context7.com/eatcodeplay/obsidian-simple-table-math/llms.txt The core `process()` method scans tables in Obsidian, identifies operation tags within cells, and calculates results based on these tags. It adapts to reading or editing modes and supports processing specific active tables. Dependencies include the Obsidian API for view management and DOM manipulation for table element selection. It extracts cell content, parses operation patterns, collects relevant values, performs calculations, and displays formatted results. ```typescript process() { const activeView = this.app.workspace.getActiveViewOfType(MarkdownView); const viewMode = activeView?.getMode() || null; const isReadingMode = viewMode === 'preview'; // Select tables based on mode const tableSelector = isReadingMode ? 'div.el-table > table' : 'div.markdown-rendered table.table-editor'; let tables: HTMLTableElement[] = []; if (isReadingMode || this.forceProcessing) { tables = Array.from(document.querySelectorAll(tableSelector)) || []; } const table = document.activeElement?.closest(tableSelector); if (table) { tables = [table] as HTMLTableElement[]; } // Process each table tables.forEach((table) => { const rows = Array.from(table.querySelectorAll('tr')); rows.forEach((row, rowIndex) => { const cells = Array.from(row.children) as HTMLTableCellElement[]; cells.forEach((cell, colIndex) => { const rawText = this.extractCellContent(cell).trim().toLowerCase(); // Match operation pattern: [operation][direction][range][currency][format] const match = rawText.match(/^([a-z]{3})([<^])(?:(\d+)(?::(\d+))?)?([a-z]{2,4})?(?:\#e(\d+))?$/i); if (match && !this.isDocumentActiveElementChildOf(cell)) { const operation = match[1].toLowerCase(); const direction = match[2]; const startIndex = match[3] ? parseInt(match[3], 10) - 1 : 0; const endIndex = match[4] ? parseInt(match[4], 10) - 1 : -1; const currency = match[5]?.toUpperCase() || null; const exponential = match[6] ? parseInt(match[6], 10) : 0; // Collect values based on direction const values = this.collectValues(direction, rowIndex, colIndex, startIndex, endIndex, rows, cells); // Calculate result const result = this.calculate(operation, values); // Display result with formatting this.displayResult(cell, result, currency, exponential, isReadingMode); } }); }); }); } ``` -------------------------------- ### Extract Numbers with Various Formats in Obsidian Simple Table Math Source: https://context7.com/eatcodeplay/obsidian-simple-table-math/llms.txt This function extracts numerical values from strings, accommodating various formats including thousand separators (commas, apostrophes, spaces) and decimal points. It uses regular expressions to parse the number string and a library (numeral) to convert it into a numerical value. It supports standard, thousands-separated, European, and scientific number formats. ```typescript extractNumber(str: string | null, numRegex: RegExp): number | null { if (!str) { return null; } const match = str.match(numRegex); if (!match) { return null; } // Remove thin spaces, apostrophes, and other thousand separators let numStr = match[0].replace(/['` ]/g, ''); return numeral(numStr).value(); } ``` ```javascript const defaultNumRegex = /-?\d+(?:[.,''`\u202f]\d{3})*(?:[.,]\d+)?/; const exponentialRegex = /^[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?$/; ``` -------------------------------- ### Collect Cell Values Vertically and Horizontally in Obsidian Simple Table Math Source: https://context7.com/eatcodeplay/obsidian-simple-table-math/llms.txt This code demonstrates how to collect values from cells above (vertical) or to the left (horizontal) of a target cell. It handles 1-based indexing for ranges and extracts numerical content, returning an array of numbers. Supports basic mathematical operations in markdown tables. ```typescript if (direction === '^') { const actualStartRow = Math.max(0, startIndex); const actualEndRow = endIndex !== -1 ? endIndex : rowIndex - 1; const finalEndRow = Math.min(actualEndRow, rowIndex - 1); if (actualStartRow <= finalEndRow) { for (let r = actualStartRow; r <= finalEndRow; r++) { const aboveCell = rows[r]?.children?.[colIndex]; const textContent = this.extractCellContent(aboveCell, true); const value = this.extractNumber(textContent, numRegex); if (value !== null) { values.push(value); } } } } // Horizontal direction (<) - collect values from cells to the left else if (direction === '<') { const actualStartCol = Math.max(0, startIndex); const actualEndCol = endIndex !== -1 ? endIndex : colIndex - 1; const finalEndCol = Math.min(actualEndCol, colIndex - 1); if (actualStartCol <= finalEndCol) { for (let c = actualStartCol; c <= finalEndCol; c++) { const leftCell = cells[c]; const textContent = this.extractCellContent(leftCell, true); const value = this.extractNumber(textContent, numRegex); if (value !== null) { values.push(value); } } } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.