mirror of
https://github.com/ozavodny/obsidian-copy-inline-code-plugin.git
synced 2026-07-22 08:10:25 +00:00
commit
4a25827761
6 changed files with 108 additions and 22 deletions
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "obsidian-sample-plugin",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.2",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "obsidian-sample-plugin",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.2",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@codemirror/language": "^6.8.0",
|
||||
|
|
|
|||
|
|
@ -2,13 +2,15 @@ import { EditorView, WidgetType } from "@codemirror/view";
|
|||
import { Notice } from "obsidian";
|
||||
|
||||
export class CopyWidget extends WidgetType {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
showOnHover: boolean;
|
||||
constructor(showOnHover: boolean) {
|
||||
super();
|
||||
this.showOnHover = showOnHover;
|
||||
}
|
||||
|
||||
toDOM(view: EditorView): HTMLElement {
|
||||
const icon = createSpan({cls: "copy-to-clipboard-icon", text: "\xa0📋"})
|
||||
|
||||
const icon = createSpan({cls: "copy-to-clipboard-icon", text: "\xa0📋"})
|
||||
icon.toggleClass("show-on-hover", this.showOnHover)
|
||||
icon.onclick = (event) => {
|
||||
const element = (event.target as HTMLElement)
|
||||
let previousElement = element.previousElementSibling
|
||||
|
|
|
|||
|
|
@ -11,10 +11,13 @@ import {
|
|||
} from "@codemirror/view";
|
||||
import { CopyWidget } from "./copy-code-widget";
|
||||
|
||||
|
||||
class CopyInlineCodeViewPlugin implements PluginValue {
|
||||
decorations: DecorationSet;
|
||||
showOnHover: boolean;
|
||||
|
||||
constructor(view: EditorView) {
|
||||
constructor(view:EditorView, showOnHover: boolean) {
|
||||
this.showOnHover = showOnHover;
|
||||
this.decorations = this.buildDecorations(view);
|
||||
}
|
||||
|
||||
|
|
@ -28,7 +31,7 @@ class CopyInlineCodeViewPlugin implements PluginValue {
|
|||
|
||||
buildDecorations(view: EditorView): DecorationSet {
|
||||
const builder = new RangeSetBuilder<Decoration>();
|
||||
|
||||
const showOnHover = this.showOnHover
|
||||
for (const { from, to } of view.visibleRanges) {
|
||||
syntaxTree(view.state).iterate({
|
||||
from,
|
||||
|
|
@ -39,7 +42,7 @@ class CopyInlineCodeViewPlugin implements PluginValue {
|
|||
node.to + 1,
|
||||
node.to + 1,
|
||||
Decoration.widget({
|
||||
widget: new CopyWidget(),
|
||||
widget: new CopyWidget(showOnHover),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
|
@ -51,11 +54,11 @@ class CopyInlineCodeViewPlugin implements PluginValue {
|
|||
}
|
||||
}
|
||||
|
||||
const pluginSpec: PluginSpec<CopyInlineCodeViewPlugin> = {
|
||||
decorations: (value: CopyInlineCodeViewPlugin) => value.decorations,
|
||||
export const createCopyPlugin = (showOnHover: boolean) => {
|
||||
return ViewPlugin.define(
|
||||
(view: EditorView) => new CopyInlineCodeViewPlugin(view, showOnHover),
|
||||
{
|
||||
decorations: (p) => p.decorations,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export const copyPlugin = ViewPlugin.fromClass(
|
||||
CopyInlineCodeViewPlugin,
|
||||
pluginSpec
|
||||
);
|
||||
38
src/main.ts
38
src/main.ts
|
|
@ -1,10 +1,36 @@
|
|||
import { CopyInlineCodePluginTab } from "./settings";
|
||||
import { Notice, Plugin } from 'obsidian';
|
||||
import { copyPlugin as copyInlineCodePlugin } from './copy-inline-code-view-plugin';
|
||||
import { createCopyPlugin } from './copy-inline-code-view-plugin';
|
||||
|
||||
|
||||
interface CopyInlineCodePluginSettings {
|
||||
showOnHover: boolean;
|
||||
}
|
||||
|
||||
const DEFAULT_SETTINGS: Partial<CopyInlineCodePluginSettings> = {
|
||||
showOnHover: false,
|
||||
};
|
||||
|
||||
export default class CopyInlineCodePlugin extends Plugin {
|
||||
settings: CopyInlineCodePluginSettings;
|
||||
|
||||
async onload() {
|
||||
this.registerEditorExtension([copyInlineCodePlugin]);
|
||||
async onload() {
|
||||
await this.loadSettings();
|
||||
this.addSettingTab(new CopyInlineCodePluginTab(this.app, this));
|
||||
this.copyInlineCodeLogic();
|
||||
|
||||
}
|
||||
|
||||
async loadSettings() {
|
||||
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
|
||||
}
|
||||
|
||||
async saveSettings() {
|
||||
await this.saveData(this.settings);
|
||||
}
|
||||
|
||||
async copyInlineCodeLogic() {
|
||||
this.registerEditorExtension([createCopyPlugin(this.settings.showOnHover)]);
|
||||
this.registerMarkdownPostProcessor((element, context) => {
|
||||
const inlineCodes = element.querySelectorAll("*:not(pre) > code");
|
||||
|
||||
|
|
@ -14,7 +40,8 @@ export default class CopyInlineCodePlugin extends Plugin {
|
|||
}
|
||||
|
||||
const icon = createSpan({cls: "copy-to-clipboard-icon", text: "\xa0📋"})
|
||||
const textToCopy = code.textContent
|
||||
icon.toggleClass("show-on-hover", this.settings.showOnHover)
|
||||
const textToCopy = code.textContent
|
||||
|
||||
icon.onclick = (event) => {
|
||||
if(textToCopy) {
|
||||
|
|
@ -27,5 +54,6 @@ export default class CopyInlineCodePlugin extends Plugin {
|
|||
code.appendChild(icon)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
34
src/settings.ts
Normal file
34
src/settings.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import CopyInlineCodePlugin from "./main";
|
||||
import { App, PluginSettingTab, Setting } from "obsidian";
|
||||
|
||||
export class CopyInlineCodePluginTab extends PluginSettingTab {
|
||||
plugin: CopyInlineCodePlugin;
|
||||
|
||||
constructor(app: App, plugin: CopyInlineCodePlugin) {
|
||||
super(app, plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
|
||||
display(): void {
|
||||
const { containerEl } = this;
|
||||
|
||||
containerEl.empty();
|
||||
containerEl.createEl('p', {
|
||||
cls: 'tasks-setting-important',
|
||||
text: 'Changing any settings requires a restart of obsidian.',
|
||||
});
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Show on hover")
|
||||
.setDesc("Copy icon only visible on hover (restart obsidian after change)")
|
||||
.addToggle((component) => {
|
||||
component
|
||||
.setValue(this.plugin.settings.showOnHover)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.showOnHover = value;
|
||||
await this.plugin.saveSettings();
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
19
styles.css
19
styles.css
|
|
@ -1,3 +1,22 @@
|
|||
.copy-to-clipboard-icon {
|
||||
cursor: pointer
|
||||
}
|
||||
|
||||
.show-on-hover {
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/* Source Mode */
|
||||
.cm-line:hover .show-on-hover {
|
||||
opacity: 1.0;
|
||||
}
|
||||
/* Reading Mode */
|
||||
code:hover .show-on-hover {
|
||||
opacity: 1.0;
|
||||
}
|
||||
|
||||
.tasks-setting-important {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue