### Install Development Dependencies with pnpm Source: https://github.com/mara-li/obsidian-enhanced-copy/blob/master/README.md Installs the pnpm package manager globally and then installs project dependencies using pnpm. This is a prerequisite for developing the plugin. ```bash npm i pnpm -g pnpm install ``` -------------------------------- ### Start Plugin Development Build Source: https://github.com/mara-li/obsidian-enhanced-copy/blob/master/README.md Starts the development build for the Obsidian Enhanced Copy plugin. This command enables hot-reloading for faster development cycles. Ensure the hot-reload-plugin is enabled in Obsidian. ```bash pnpm run dev ``` -------------------------------- ### Create a Release Build Source: https://github.com/mara-li/obsidian-enhanced-copy/blob/master/README.md Generates a production-ready build of the Obsidian Enhanced Copy plugin. This command is used for creating distributable versions of the plugin. ```bash pnpm run build ``` -------------------------------- ### Initialize and Register Commands - Enhanced Copy Plugin (TypeScript) Source: https://context7.com/mara-li/obsidian-enhanced-copy/llms.txt Initializes the Enhanced Copy plugin, loads settings, and registers commands for copying text. It supports a main 'Copy selected text' command and profile-specific commands for different user-defined copy configurations. ```typescript import { Plugin, MarkdownView, ItemView } from "obsidian"; // Plugin initialization and command registration export default class EnhancedCopy extends Plugin { settings: EnhancedCopySettings = DEFAULT_SETTINGS; profileCSS: ProfileCSS = new Map(); async onload() { await this.loadSettings(); this.addSettingTab(new EnhancedCopySettingTab(this.app, this)); // Register main copy command this.addCommand({ id: "copy-all-in-markdown", name: "Copy selected text", callback: async () => { const profile = this.getProfile() ?? this.getDefaultProfile(); const { selectedText } = await this.enhancedCopy(profile); await this.writeToClipboard(selectedText, profile); }, }); // Register profile-specific commands for (const profile of this.settings.profiles) { this.addCommand({ id: `copy-${profile.name}-in-markdown`, name: profile.name, checkCallback: (checking: boolean) => { const view = this.app.workspace.getActiveViewOfType(MarkdownView); if (!checking) { this.enhancedCopy(profile).then(({ selectedText }) => { this.writeToClipboard(selectedText, profile); }); } return true; }, }); } } } ``` -------------------------------- ### Export Plugin to Obsidian Vault Source: https://github.com/mara-li/obsidian-enhanced-copy/blob/master/README.md Exports the plugin to your Obsidian main vault. Requires a `.env` file with `VAULT` and `VAULT_DEV` paths configured. ```bash pnpm run export ``` -------------------------------- ### Profile Auto-Rules System in TypeScript Source: https://context7.com/mara-li/obsidian-enhanced-copy/llms.txt Implements a system to select copy profiles based on auto-rules that match file path, tags, or frontmatter metadata. Supports regex patterns and negation for exclusion logic. The `getProfile` method iterates through settings to find a matching profile. ```typescript interface AutoRules { type: "path" | "tag" | "frontmatter"; value: string; // Regex pattern not?: boolean; // Negation flag } // Profile selection based on file metadata getProfile(viewOfType?: ApplyingToView): GlobalSettings | undefined { const activeFile = this.app.workspace.getActiveFile(); if (!activeFile) return; const path = activeFile.path; const cache = this.app.metadataCache.getFileCache(activeFile); const tags = cache ? (getAllTags(cache) ?? []) : []; const frontmatterKeys = cache?.frontmatter?.enhanced_copy; for (const profile of this.settings.profiles) { if (profile.autoRules) { // Check exclusion rules first (NOT conditions) const excluded = profile.autoRules.find( (rule) => rule.not && this.checkByRules(rule, path, tags, frontmatterKeys) ); if (excluded) continue; // Check inclusion rules for (const rule of profile.autoRules) { if (!rule.not && this.checkByRules(rule, path, tags, frontmatterKeys)) { return profile; } } } } } // Example auto-rules configuration const discordProfile: GlobalSettings = { name: "Discord", applyingTo: ApplyingToView.All, autoRules: [ { type: "path", value: "^social/discord/.*" }, { type: "tag", value: "#discord" }, { type: "frontmatter", value: "discord" }, { type: "path", value: "^private/.*", not: true } // Exclude private folder ], // ... other settings }; ``` -------------------------------- ### Environment Variables for Vault Paths Source: https://github.com/mara-li/obsidian-enhanced-copy/blob/master/README.md Configuration for the `.env` file to specify paths for your Obsidian main vault and development vault. This is used by the export script. ```dotenv VAULT=path/to/main/vault VAULT_DEV=path/to/dev/vault ``` -------------------------------- ### Define Enhanced Copy Plugin Settings Interface (TypeScript) Source: https://context7.com/mara-li/obsidian-enhanced-copy/llms.txt This TypeScript interface defines the structure for the main settings of the Enhanced Copy plugin. It includes options for HTML copying, RTF support, applying views, hotkeys, global settings for editing and reading modes, developer mode, and custom profiles. ```typescript interface EnhancedCopySettings { copyAsHTML: boolean; rtf?: boolean; applyingTo: ApplyingToView; // "all" | "reading" | "edit" separateHotkey: boolean; editing: GlobalSettings; reading: GlobalSettings; devMode: boolean; profiles: GlobalSettings[]; } interface GlobalSettings { name?: string; copyAsHTML?: boolean; rtf?: boolean; cssFile?: string; footnotes: ConversionOfFootnotes; links: ConversionOfLinks; callout: CalloutKeepType; convertDataview?: ConvertDataview; highlight: boolean; hardBreak: boolean; replaceText: ReplaceText[]; overrideNativeCopy: boolean; spaceReadingSize?: number; tabToSpace?: boolean; tabSpaceSize?: number; wikiToMarkdown?: boolean; applyingTo?: ApplyingToView; autoRules?: AutoRules[]; } // Default settings const DEFAULT_SETTINGS: EnhancedCopySettings = { copyAsHTML: false, applyingTo: ApplyingToView.All, separateHotkey: false, editing: { footnotes: ConversionOfFootnotes.Keep, links: ConversionOfLinks.Keep, callout: CalloutKeepType.Obsidian, highlight: false, hardBreak: false, replaceText: [], overrideNativeCopy: false, }, reading: { footnotes: ConversionOfFootnotes.Keep, links: ConversionOfLinks.Keep, callout: CalloutKeepType.Obsidian, highlight: false, hardBreak: false, replaceText: [], overrideNativeCopy: false, spaceReadingSize: -1, }, devMode: false, profiles: [], }; ``` -------------------------------- ### Convert Dataview Queries to Markdown Output (TypeScript) Source: https://context7.com/mara-li/obsidian-enhanced-copy/llms.txt Evaluates Dataview DQL and DataviewJS queries within markdown text and replaces them with their rendered markdown output. It supports both inline queries and code block queries, leveraging the Dataview API for execution. This feature is crucial for exporting dynamic content generated by Dataview into static markdown. ```typescript interface ConvertDataview { enable: boolean; djs: { inline: boolean; block: boolean }; // DataviewJS dql: { inline: boolean; block: boolean }; // Dataview Query Language } // Convert Dataview queries to markdown async function convertDataviewQueries( settings: GlobalSettings, path: string, text: string, plugin: EnhancedCopy ): Promise { const dvApi = getAPI(plugin.app); if (!dvApi) return text; let replacedText = text; const compiler = new DataviewCompiler(settings, dvApi, text, path); // Process DQL code blocks: ```dataview ... ``` if (settings.convertDataview?.dql?.block) { const dataViewRegex = /```dataview\s(.+?)```/gms; for (const queryBlock of text.matchAll(dataViewRegex)) { const markdown = await compiler.dataviewDQL(queryBlock[1]); replacedText = replacedText.replace(queryBlock[0], markdown); } } // Process inline DQL: `= query` if (settings.convertDataview?.dql?.inline) { const inlinePrefix = dvApi.settings.inlineQueryPrefix || "="; const inlineRegex = new RegExp(``${inlinePrefix}(.+?)``, "gsm"); for (const query of text.matchAll(inlineRegex)) { const result = dvApi.evaluateInline(query[1].trim(), path); if (result.successful) { replacedText = replacedText.replace(query[0], result.value?.toString() ?? ""); } } } return replacedText; } // Example: Copy converts Dataview to output // Input: ```dataview // TABLE file.name FROM "notes" // ``` // Output: | File | file.name | // | --- | --- | // | Note 1 | Note 1 | ``` -------------------------------- ### Markdown Conversion Pipeline in TypeScript Source: https://context7.com/mara-li/obsidian-enhanced-copy/llms.txt Applies a series of transformations to markdown text for reading view output. Each transformation handles specific markdown elements like links, footnotes, callouts, and highlights. The `convertMarkdown` function orchestrates these transformations. ```typescript // Main conversion function for reading view function convertMarkdown( markdown: string, overrides: GlobalSettings, plugin: EnhancedCopy ): string { return removeEmptyLineBeforeList( convertSpaceSize( convertCallout( hardBreak( removeHighlightMark( fixFootNotes( removeLinksBracketsInMarkdown( textReplacement(markdown, overrides), overrides ), overrides ), overrides ), overrides, plugin ), overrides, plugin ), overrides ) ); } // Link conversion options enum ConversionOfLinks { Keep = "keep", // [text](url) -> [text](url) Remove = "remove", // [text](url) -> text External = "external" // Keep only https:// links } // Example: Remove internal links, keep external const settings: GlobalSettings = { links: ConversionOfLinks.External, footnotes: ConversionOfFootnotes.Format, callout: CalloutKeepType.Strong, highlight: true, // Remove ==highlights== hardBreak: true, // Add two spaces before newlines }; ``` -------------------------------- ### Apply Regex Text Replacements in Markdown Source: https://context7.com/mara-li/obsidian-enhanced-copy/llms.txt Transforms markdown text by applying a series of user-defined regex patterns and their replacements. It handles both plain string replacements and complex regular expressions with flags, allowing for flexible text manipulation before copying. ```typescript interface ReplaceText { pattern: string; // Plain string or /regex/flags replacement: string; // Replacement text with capture groups } function textReplacement(markdown: string, settings: GlobalSettings): string { for (const replace of settings.replaceText) { let pattern: string | RegExp = replace.pattern; // Check if pattern is regex format: /pattern/flags if (pattern.match(/^\/.*\/([gmiyus]+)?$/)) { const flags = pattern.replace(/^\/.*\/([gmiyus]+)?$/, "$1"); const regex = pattern.replace(/^\/(.*)\/(\.*)$/, "$1"); pattern = new RegExp(regex, flags.length > 0 ? flags : undefined); markdown = markdown.replace(pattern, replace.replacement); } else { // Plain string replacement markdown = markdown.replaceAll(pattern, replace.replacement); } } return markdown; } // Example replacements const replaceRules: ReplaceText[] = [ { pattern: "Obsidian", replacement: "my notes app" }, { pattern: "/\\[\\[(.+?)\\]/g", replacement: "$1" }, // Remove wiki brackets { pattern: "/^#+\\s*/gm", replacement: "" }, // Remove heading markers { pattern: "/:::spoiler(.+?):::/gs", replacement: "
$1
" } ]; ``` -------------------------------- ### Default CSS Loading Logic Source: https://github.com/mara-li/obsidian-enhanced-copy/blob/master/README.md TypeScript code defining the default CSS used for HTML export in the Obsidian Enhanced Copy plugin. This file is referenced in the plugin's documentation. ```typescript // Default CSS loading logic is defined here. // This file is located at: ./src/utils/loadCssForHtml.ts ``` -------------------------------- ### Write HTML Content to Clipboard Source: https://context7.com/mara-li/obsidian-enhanced-copy/llms.txt Writes content to the system clipboard as an HTML blob, which is particularly useful for RTF support in other applications. This function ensures that rich text formatting is preserved during copy-paste operations. ```typescript // Write to clipboard as HTML blob for RTF support writeBlob(selectedText: string): ClipboardItem[] { const blob = new Blob([selectedText], { type: "text/html" }); return [new ClipboardItem({ "text/html": blob })]; } async writeToClipboard(text: string, profile?: GlobalSettings) { if (profile?.rtf) { const item = this.writeBlob(text); await navigator.clipboard.write(item); } await navigator.clipboard.writeText(text); } ``` -------------------------------- ### Convert Edit View Markdown with Advanced Features (TypeScript) Source: https://context7.com/mara-li/obsidian-enhanced-copy/llms.txt Processes markdown from the editing view, applying a series of conversions including text replacements, Dataview query evaluation, wikilink conversion, tab-to-space conversion, and standard markdown enhancements. It can also optionally export the final markdown as HTML. This function orchestrates multiple conversion utilities for comprehensive markdown processing. ```typescript async function convertEditMarkdown( markdown: string, overrides: GlobalSettings, plugin: EnhancedCopy, path?: string | null ): Promise { // Apply regex replacements first markdown = textReplacement(markdown, overrides); // Convert Dataview queries to markdown output if (path && overrides.convertDataview && plugin.app.plugins.enabledPlugins.has("dataview")) { markdown = await convertDataviewQueries(overrides, path, markdown, plugin); } // Convert [[wikilinks]] to [markdown](links) if (overrides.wikiToMarkdown) { markdown = convertWikiToMarkdown(markdown); markdown = removeLinksBracketsInMarkdown(markdown, overrides); } // Convert tabs to spaces markdown = convertTabToSpace(markdown, overrides); // Apply standard conversions markdown = removeMarkdownFootNotes(markdown, overrides); markdown = convertCallout(markdown, overrides, plugin); markdown = removeHighlightMark(markdown, overrides); markdown = hardBreak(markdown, overrides, plugin); // Optionally export as HTML if (overrides.copyAsHTML) { return await markdownToHtml(markdown, overrides, plugin); } return markdown; } // Wikilink conversion function convertWikiToMarkdown(markdown: string): string { const regexWikiLinks = /[[^]]+]]/g; return markdown.replaceAll(regexWikiLinks, (_match, p1) => { const parts = p1.split("|"); if (parts.length === 1) { return `[${p1}](${p1})`; // [[link]] -> [link](link) } return `[${parts[1]}](${parts[0]})`; // [[link|text]] -> [text](link) }); } ``` -------------------------------- ### Export Markdown to HTML with Custom CSS Source: https://context7.com/mara-li/obsidian-enhanced-copy/llms.txt Converts markdown content to HTML, optionally embedding custom CSS for styling. This function is used for exporting content as HTML or preparing it for RTF export, ensuring consistent formatting across different applications. ```typescript // Convert markdown to HTML with custom CSS async function markdownToHtml( markdown: string, overrides: GlobalSettings, plugin: EnhancedCopy ): Promise { const component = new Component(); const div = document.createElement("div"); component.load(); await MarkdownRenderer.render(plugin.app, markdown, div, "", component); component.unload(); const html = div.innerHTML.trim(); if (overrides.rtf) { const css = plugin.profileCSS.get(overrides.name ?? "edit") ?? DEFAULT_CSS; return `${html}`; } return html; } // Settings for HTML export const htmlProfile: GlobalSettings = { name: "Word Export", copyAsHTML: true, rtf: true, cssFile: ".obsidian/snippets/export.css", // Custom CSS path // ... other settings }; ``` -------------------------------- ### Extract Selection from Obsidian Reading View as HTML Source: https://context7.com/mara-li/obsidian-enhanced-copy/llms.txt Retrieves selected text from Obsidian's reading view and returns it as HTML. It includes logic to handle list renumbering and convert callout divs to blockquotes, ensuring accurate representation of the selected content. ```typescript // Get selection from reading view as HTML then convert to markdown function getSelectionAsHTML(settings: GlobalSettings): string { const selection = activeWindow.getSelection(); if (!selection) return ""; const range = selection.getRangeAt(0); const fragment = range.cloneContents(); const div = document.createElement("div"); div.appendChild(fragment); // Handle list renumbering for partial selections const ancestor = range.commonAncestorContainer; if (ancestor.nodeName === "OL" || ancestor.nodeName === "UL") { div = reNumerateList(div, ancestor.nodeName.toLowerCase()); } // Convert callout divs to blockquotes div = replaceAllDivCalloutToBlockquote(div, ancestor, settings); if (settings.copyAsHTML) { return div.innerHTML; } return htmlToMarkdown(div.innerHTML); } ``` -------------------------------- ### Footnote Conversion in TypeScript Source: https://context7.com/mara-li/obsidian-enhanced-copy/llms.txt Handles Obsidian's internal footnote format, allowing removal, preservation, or reformatting to standard markdown `[^1]` syntax. The `fixFootNotes` and `fixFootnoteContents` functions manage these conversions. ```typescript enum ConversionOfFootnotes { Keep = "keep", // Keep Obsidian format: [[1]](#fn-1-xxx) Remove = "remove", // Remove footnotes entirely Format = "format" // Convert to: [^1] } // Convert Obsidian footnotes to standard markdown function fixFootNotes(markdown: string, settings: GlobalSettings): string { const regexFootNotes = /[{2}(\w+)]{2}\((.*)\)/g; if (settings.footnotes === ConversionOfFootnotes.Remove) { // footnote[[1]](#fn-1-xxx) -> footnote markdown = markdown.replace(regexFootNotes, ""); } else if (settings.footnotes === ConversionOfFootnotes.Format) { // footnote[[1]](#fn-1-xxx) -> footnote[^1] markdown = markdown.replace(regexFootNotes, "[^$1]"); } return fixFootnoteContents(markdown, settings); } // Fix footnote content format function fixFootnoteContents(markdown: string, settings: GlobalSettings): string { const regexFootNotes = /(.*)[\]\(#fnref-(\d)-\w+\)/g; if (settings.footnotes === ConversionOfFootnotes.Format) { // coucou[](#fnref-1-xxx) -> [^1]: coucou markdown = markdown.replace(regexFootNotes, "[^$2]: $1"); } return markdown; } ``` -------------------------------- ### Convert Obsidian Callouts to Markdown Formats (TypeScript) Source: https://context7.com/mara-li/obsidian-enhanced-copy/llms.txt Transforms Obsidian-style callouts into compatible markdown formats, such as GitHub-flavored blockquotes. It supports options to keep the original Obsidian format, convert the callout type to bold text, or remove the callout type while retaining the title. This function is essential for ensuring callouts render correctly in various markdown environments. ```typescript enum CalloutKeepType { Obsidian = "obsidian", // Keep: > [!note] Title Strong = "strong", // Convert to: > **Note** Title Remove = "remove", // Remove callout type entirely RemoveKeepTitle = "removeKeepTitle" // Keep only title as bold } function convertCallout( markdown: string, overrides: GlobalSettings, plugin: EnhancedCopy ): string { const calloutRegex = /^>* *[!(\w+)\|?(.*)] *(.*)$/gm; if (overrides.callout === CalloutKeepType.Strong) { // > [!info] Important -> > **Info** Important return markdown.replace(calloutRegex, "> **$1** $3"); } if (overrides.callout === CalloutKeepType.RemoveKeepTitle) { // > [!warning] Be careful -> > **Be careful** return markdown.replace(calloutRegex, (_match, _type, _fold, title) => { return title ? `> **${title}**` : ""; }); } return markdown; } // Example input/output: // Input: > [!tip] Pro tip // > Use keyboard shortcuts // Output (Strong): > **Tip** Pro tip // > Use keyboard shortcuts ``` -------------------------------- ### Process and Transform Selected Text - Enhanced Copy Function (TypeScript) Source: https://context7.com/mara-li/obsidian-enhanced-copy/llms.txt The core function that processes selected text from Obsidian views (reading, editing, canvas). It applies customizable markdown conversions based on the active view and user-defined profiles, returning the transformed text and export format. ```typescript async enhancedCopy( profile?: GlobalSettings ): Promise<{ selectedText: string; exportAsHTML: boolean }> { const activeView = this.app.workspace.getActiveViewOfType(MarkdownView); let selectedText: string; let viewIn: ApplyingToView; if (activeView && activeView.getMode() !== "source") { // Reading view - convert HTML selection to markdown selectedText = getSelectionAsHTML(profile ?? this.settings.reading); viewIn = ApplyingToView.Reading; } else if (activeView) { // Editing view - get raw editor selection const editor = activeView.editor; selectedText = copySelectionRange(editor, this); viewIn = ApplyingToView.Edit; } else { // Canvas or other views const leafType = this.app.workspace.getActiveViewOfType(ItemView)?.getViewType(); if (leafType === "canvas") { selectedText = canvasSelectionText(this.app, this); } else { selectedText = activeWindow.getSelection()?.toString() ?? ""; } viewIn = ApplyingToView.Reading; } // Apply conversions based on view type if (viewIn === ApplyingToView.Reading) { selectedText = convertMarkdown(selectedText, profile ?? this.settings.reading, this); } else { selectedText = await convertEditMarkdown( selectedText, profile ?? this.settings.editing, this, this.app.workspace.getActiveFile()?.path ); } return { selectedText, exportAsHTML: profile?.rtf ?? false }; } ``` -------------------------------- ### Handle Canvas Element Selection in Obsidian Source: https://context7.com/mara-li/obsidian-enhanced-copy/llms.txt Retrieves selected text from Obsidian's canvas view. If an editor is active, it uses the editor's selection handling; otherwise, it falls back to retrieving HTML from the reading view, ensuring text can be copied from various canvas elements. ```typescript // Canvas selection handling function canvasSelectionText(app: App, plugin: EnhancedCopy): string { const editor = app.workspace.activeEditor; if (editor) { return copySelectionRange(editor.editor as Editor, plugin); } return getSelectionAsHTML(plugin.settings.reading); } ``` -------------------------------- ### Copy Selection from Obsidian Editor with Multi-Cursor Support Source: https://context7.com/mara-li/obsidian-enhanced-copy/llms.txt Extracts selected text from Obsidian's editor, supporting multiple cursors. It iterates through all active selections, retrieves the text for each, and concatenates them into a single string, handling line breaks appropriately. ```typescript // Get selection from editor with multi-cursor support function copySelectionRange(editor: Editor, plugin: EnhancedCopy): string { let selectedText = ""; const selections = editor.listSelections(); for (const selected of selections) { const head = getHead(selected.head, selected.anchor); const anchor = getAnchor(selected.head, selected.anchor); selectedText += `${editor.getRange(head, anchor)}\n`; } return selectedText.slice(0, -1); // Remove trailing newline } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.