diff --git a/src/SmilesBlock.ts b/src/SmilesBlock.ts index 687ecc9..166f0ae 100644 --- a/src/SmilesBlock.ts +++ b/src/SmilesBlock.ts @@ -7,8 +7,9 @@ import { import { gDrawer } from './global/drawer'; import { gDataview, isPluginEnabled, getDataview } from './global/dataview'; -import { ChemPluginSettings, DEFAULT_SD_OPTIONS } from './settings/base'; +import { ChemPluginSettings } from './settings/base'; import { addBlock, removeBlock } from './global/blocks'; +import { themes } from './settings/theme'; import { i18n } from 'src/lib/i18n'; @@ -47,7 +48,8 @@ export class SmilesBlock extends MarkdownRenderChild { this.renderCell(rows[0], div, this.theme); } else { const table = this.el.createDiv({ cls: 'chem-table' }); - const maxWidth = this.settings.options?.width ?? 300; + const maxWidth = + this.settings.smilesDrawerOptions.moleculeOptions.width ?? 300; rows.forEach((row) => { const cell = table.createDiv({ cls: 'chem-cell' }); @@ -62,7 +64,8 @@ export class SmilesBlock extends MarkdownRenderChild { }); table.style.gridTemplateColumns = `repeat(auto-fill, minmax(${ - this.settings.options.width?.toString() ?? '300' + this.settings.smilesDrawerOptions.moleculeOptions.width?.toString() ?? + '300' }px, 1fr)`; } } @@ -146,7 +149,7 @@ export class SmilesBlock extends MarkdownRenderChild { errorCb(error, target.createEl('div')); } ); - if (this.settings.options.scale == 0) + if (this.settings.smilesDrawerOptions.moleculeOptions.scale == 0) svg.style.width = `${this.settings.imgWidth.toString()}px`; return svg; }; @@ -223,7 +226,7 @@ export class SmilesBlock extends MarkdownRenderChild { // Apply background color if (!this.settings.copy.transparent) { - ctx.fillStyle = DEFAULT_SD_OPTIONS.themes[copyTheme].BACKGROUND; + ctx.fillStyle = themes.copyTheme.BACKGROUND; ctx.fillRect(0, 0, canvas.width, canvas.height); } diff --git a/src/SmilesInline.ts b/src/SmilesInline.ts index 820b213..9ee0d62 100644 --- a/src/SmilesInline.ts +++ b/src/SmilesInline.ts @@ -112,7 +112,7 @@ export function inlinePlugin(settings: ChemPluginSettings) { errorCb(error, target.createEl('div')); } ); - if (settings.options.scale == 0) + if (settings.smilesDrawerOptions.moleculeOptions.scale == 0) svg.style.width = `${settings.imgWidth.toString()}px`; return svg; }; diff --git a/src/global/drawer.ts b/src/global/drawer.ts index 8fa8551..346f6f8 100644 --- a/src/global/drawer.ts +++ b/src/global/drawer.ts @@ -1,10 +1,20 @@ -import { DEFAULT_SD_OPTIONS, SMILES_DRAWER_OPTIONS } from 'src/settings/base'; +import { + DEFAULT_SD_OPTIONS, + SD_MoleculeOptions, + SD_ReactionOptions, +} from 'src/settings/smilesDrawerOptions'; import SmilesDrawer from 'smiles-drawer'; export let gDrawer = new SmilesDrawer.SmiDrawer(DEFAULT_SD_OPTIONS); -export const setDrawer = (options: Partial<SMILES_DRAWER_OPTIONS>) => { - gDrawer = new SmilesDrawer.SmiDrawer({ ...DEFAULT_SD_OPTIONS, ...options }); +export const setDrawer = ( + moleculeOptions: Partial<SD_MoleculeOptions>, + reactionOptions: Partial<SD_ReactionOptions> +) => { + gDrawer = new SmilesDrawer.SmiDrawer( + { ...DEFAULT_SD_OPTIONS.moleculeOptions, ...moleculeOptions }, + { ...DEFAULT_SD_OPTIONS.reactionOptions, ...reactionOptions } + ); }; export const clearDrawer = () => { diff --git a/src/main.ts b/src/main.ts index ec9ed88..942814d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,11 +1,7 @@ import { Plugin, MarkdownPostProcessorContext } from 'obsidian'; -import { - DEFAULT_SETTINGS, - ChemPluginSettings, - SETTINGS_VERSION, -} from './settings/base'; +import { ChemPluginSettings } from './settings/base'; import { ChemSettingTab } from './settings/SettingTab'; -import { updateSettingsVersion } from './settings/update'; +import { migrateSettings } from './settings/base'; import { SmilesBlock } from './SmilesBlock'; import { inlinePlugin } from './SmilesInline'; @@ -23,7 +19,10 @@ export default class ChemPlugin extends Plugin { // this.addRibbonIcon('hexagon', 'This is Chem Plugin', () => {}); // initialize global variables - setDrawer(this.settings.options); + setDrawer( + this.settings.smilesDrawerOptions.moleculeOptions, + this.settings.smilesDrawerOptions.reactionOptions + ); setBlocks(); setObserver(); // editor extension @@ -44,17 +43,7 @@ export default class ChemPlugin extends Plugin { } async loadSettings() { - const candidate = Object.assign({}, await this.loadData()); - if ('version' in candidate && candidate.version == SETTINGS_VERSION) - this.settings = Object.assign({}, DEFAULT_SETTINGS, candidate); - else if (Object.keys(candidate).length === 0) - this.settings = Object.assign({}, DEFAULT_SETTINGS); - else - this.settings = Object.assign( - {}, - DEFAULT_SETTINGS, - updateSettingsVersion(candidate) - ); + this.settings = migrateSettings(await this.loadData()); } async saveSettings() { diff --git a/src/settings/LivePreview.ts b/src/settings/LivePreview.ts index def3eb9..43aee98 100644 --- a/src/settings/LivePreview.ts +++ b/src/settings/LivePreview.ts @@ -42,7 +42,7 @@ export class LivePreview { this.settings.darkTheme ); - if (this.settings.options.scale == 0) + if (this.settings.smilesDrawerOptions.moleculeOptions.scale == 0) this.container.style.gridTemplateColumns = `repeat(auto-fill, minmax(${( this.settings?.imgWidth ?? 300 ).toString()}px, 1fr)`; @@ -83,15 +83,18 @@ export class LivePreview { container.style.display = `grid`; container.style.alignContent = `center`; - if (this.settings.options.scale == 0) + if (this.settings.smilesDrawerOptions.moleculeOptions.scale == 0) container.style.width = `${( this.settings?.imgWidth ?? 300 ).toString()}px`; else if ( - container.offsetWidth > (this.settings.options?.width ?? 300) + container.offsetWidth > + (this.settings.smilesDrawerOptions.moleculeOptions?.width ?? + 300) ) { container.style.width = `${( - this.settings.options?.width ?? 300 + this.settings.smilesDrawerOptions.moleculeOptions?.width ?? + 300 ).toString()}px`; } }; @@ -106,20 +109,22 @@ export class LivePreview { errorCb(error, target.createEl('div')); } ); - if (this.settings.options.scale == 0) + if (this.settings.smilesDrawerOptions.moleculeOptions.scale == 0) svg.style.width = `${( this.settings?.imgWidth ?? 300 ).toString()}px`; else if ( - parseFloat(svg.style.width) > (this.settings.options?.width ?? 300) + parseFloat(svg.style.width) > + (this.settings.smilesDrawerOptions.moleculeOptions?.width ?? 300) ) { const r = parseFloat(svg.style.width) / parseFloat(svg.style.height); svg.style.width = `${( - this.settings.options?.width ?? 300 + this.settings.smilesDrawerOptions.moleculeOptions?.width ?? 300 ).toString()}px`; svg.style.height = `${( - (this.settings.options?.width ?? 300) / r + (this.settings.smilesDrawerOptions.moleculeOptions?.width ?? + 300) / r ).toString()}px`; } return parseFloat(svg.style.width); diff --git a/src/settings/SettingTab.ts b/src/settings/SettingTab.ts index c5b73ac..6d3c8ae 100644 --- a/src/settings/SettingTab.ts +++ b/src/settings/SettingTab.ts @@ -1,12 +1,9 @@ import { App, PluginSettingTab, Setting, SliderComponent } from 'obsidian'; import ChemPlugin from '../main'; -import { - DEFAULT_SD_OPTIONS, - SAMPLE_SMILES_1, - SAMPLE_SMILES_2, - themeList, -} from './base'; +import { themeList } from './theme'; +import { DEFAULT_SETTINGS } from './base'; +import { DEFAULT_SD_OPTIONS } from './smilesDrawerOptions'; import { setDrawer } from 'src/global/drawer'; import { refreshBlocks } from 'src/global/blocks'; @@ -15,8 +12,6 @@ import { LivePreview } from './LivePreview'; import { i18n } from 'src/lib/i18n'; -// Reference: https://smilesdrawer.surge.sh/playground.html - export class ChemSettingTab extends PluginSettingTab { plugin: ChemPlugin; @@ -40,13 +35,10 @@ export class ChemSettingTab extends PluginSettingTab { .setIcon('rotate-ccw') .setTooltip(i18n.t('settings.scale.description')) .onClick(async () => { - this.plugin.settings.options.scale = 1; + this.plugin.settings.smilesDrawerOptions.moleculeOptions.scale = 1; scaleSlider.setValue(50); await this.plugin.saveSettings(); - setDrawer({ - ...DEFAULT_SD_OPTIONS, - ...this.plugin.settings.options, - }); + this.updateDrawer(); onSettingsChange(); unifyBondLength(); }); @@ -54,20 +46,27 @@ export class ChemSettingTab extends PluginSettingTab { const scaleLabel = scaleSetting.controlEl.createDiv('slider-readout'); scaleLabel.setText( - (this.plugin.settings.options.scale ?? 1.0).toFixed(2).toString() + ( + this.plugin.settings.smilesDrawerOptions.moleculeOptions + .scale ?? 1.0 + ) + .toFixed(2) + .toString() ); const scaleSlider = new SliderComponent(scaleSetting.controlEl) - .setValue(50 * (this.plugin.settings.options.scale ?? 1.0)) + .setValue( + 50 * + (this.plugin.settings.smilesDrawerOptions.moleculeOptions + .scale ?? 1.0) + ) .setLimits(0.0, 100, 0.5) .onChange(async (value) => { - this.plugin.settings.options.scale = value / 50; + this.plugin.settings.smilesDrawerOptions.moleculeOptions.scale = + value / 50; scaleLabel.setText((value / 50).toFixed(2).toString()); await this.plugin.saveSettings(); - setDrawer({ - ...DEFAULT_SD_OPTIONS, - ...this.plugin.settings.options, - }); + this.updateDrawer(); onSettingsChange(); if (value == 0) unifyImageWidth(); else unifyBondLength(); @@ -112,11 +111,11 @@ export class ChemSettingTab extends PluginSettingTab { .setDesc(i18n.t('settings.preview.sample.description')) .addText((text) => text - .setPlaceholder(SAMPLE_SMILES_1) + .setPlaceholder(DEFAULT_SETTINGS.sample1) .setValue(this.plugin.settings.sample1) .onChange(async (value) => { if (value == '') { - value = SAMPLE_SMILES_1; + value = DEFAULT_SETTINGS.sample1; } this.plugin.settings.sample1 = value; await this.plugin.saveSettings(); @@ -125,11 +124,11 @@ export class ChemSettingTab extends PluginSettingTab { ) .addText((text) => text - .setPlaceholder(SAMPLE_SMILES_2) + .setPlaceholder(DEFAULT_SETTINGS.sample2) .setValue(this.plugin.settings.sample2) .onChange(async (value) => { if (value == '') { - value = SAMPLE_SMILES_2; + value = DEFAULT_SETTINGS.sample2; } this.plugin.settings.sample2 = value; await this.plugin.saveSettings(); @@ -149,15 +148,14 @@ export class ChemSettingTab extends PluginSettingTab { .addToggle((toggle) => toggle .setValue( - this.plugin.settings.options?.compactDrawing ?? false + this.plugin.settings.smilesDrawerOptions.moleculeOptions + .compactDrawing ?? false ) .onChange(async (value) => { - this.plugin.settings.options.compactDrawing = value; + this.plugin.settings.smilesDrawerOptions.moleculeOptions.compactDrawing = + value; await this.plugin.saveSettings(); - setDrawer({ - ...DEFAULT_SD_OPTIONS, - ...this.plugin.settings.options, - }); + this.updateDrawer(); onSettingsChange(); }) ); @@ -168,15 +166,14 @@ export class ChemSettingTab extends PluginSettingTab { .addToggle((toggle) => toggle .setValue( - this.plugin.settings.options?.terminalCarbons ?? false + this.plugin.settings.smilesDrawerOptions.moleculeOptions + .terminalCarbons ?? false ) .onChange(async (value) => { - this.plugin.settings.options.terminalCarbons = value; + this.plugin.settings.smilesDrawerOptions.moleculeOptions.terminalCarbons = + value; await this.plugin.saveSettings(); - setDrawer({ - ...DEFAULT_SD_OPTIONS, - ...this.plugin.settings.options, - }); + this.updateDrawer(); onSettingsChange(); }) ); @@ -187,15 +184,14 @@ export class ChemSettingTab extends PluginSettingTab { .addToggle((toggle) => toggle .setValue( - this.plugin.settings.options?.explicitHydrogens ?? false + this.plugin.settings.smilesDrawerOptions.moleculeOptions + .explicitHydrogens ?? false ) .onChange(async (value) => { - this.plugin.settings.options.explicitHydrogens = value; + this.plugin.settings.smilesDrawerOptions.moleculeOptions.explicitHydrogens = + value; await this.plugin.saveSettings(); - setDrawer({ - ...DEFAULT_SD_OPTIONS, - ...this.plugin.settings.options, - }); + this.updateDrawer(); onSettingsChange(); }) ); @@ -312,20 +308,17 @@ export class ChemSettingTab extends PluginSettingTab { .addText((text) => text .setValue( - this.plugin.settings.options.width?.toString() ?? + this.plugin.settings.smilesDrawerOptions.moleculeOptions.width?.toString() ?? '300' ) .onChange(async (value) => { if (value == '') { value = '300'; } - this.plugin.settings.options.width = + this.plugin.settings.smilesDrawerOptions.moleculeOptions.width = parseInt(value); await this.plugin.saveSettings(); - setDrawer({ - ...DEFAULT_SD_OPTIONS, - ...this.plugin.settings.options, - }); + this.updateDrawer(); onSettingsChange(); }) ); @@ -354,11 +347,27 @@ export class ChemSettingTab extends PluginSettingTab { // Initialize preview.render(); - if ((this.plugin.settings.options?.scale ?? 1) == 0) unifyImageWidth(); + if ( + (this.plugin.settings.smilesDrawerOptions.moleculeOptions.scale ?? + 1) == 0 + ) + unifyImageWidth(); else unifyBondLength(); } hide(): void { refreshBlocks(); } + + updateDrawer = () => + setDrawer( + { + ...DEFAULT_SD_OPTIONS.moleculeOptions, + ...this.plugin.settings.smilesDrawerOptions.moleculeOptions, + }, + { + ...DEFAULT_SD_OPTIONS.reactionOptions, + ...this.plugin.settings.smilesDrawerOptions.reactionOptions, + } + ); } diff --git a/src/settings/base.ts b/src/settings/base.ts index 59a4904..e0b3523 100644 --- a/src/settings/base.ts +++ b/src/settings/base.ts @@ -1,327 +1,65 @@ -// Global consts -export const SAMPLE_SMILES_1 = 'OC(=O)C(C)=CC1=CC=CC=C1'; -export const SAMPLE_SMILES_2 = - 'OC(C(=O)O[C@H]1C[N+]2(CCCOC3=CC=CC=C3)CCC1CC2)(C1=CC=CS1)C1=CC=CS1'; -export const SETTINGS_VERSION = 'v2'; +import { ChemPluginSettingsV1, DEFAULT_SETTINGS_V1 } from './v1'; +import { ChemPluginSettingsV2, DEFAULT_SETTINGS_V2 } from './v2'; +import { ChemPluginSettingsV3, DEFAULT_SETTINGS_V3 } from './v3'; -// Plugin settings -export interface ChemPluginSettings { - version: string; - darkTheme: string; - lightTheme: string; - sample1: string; - sample2: string; - imgWidth: number; - copy: { - scale: number; - transparent: boolean; - theme: string; - }; - dataview: boolean; - inlineSmiles: boolean; - inlineSmilesPrefix: string; - options: Partial<SMILES_DRAWER_OPTIONS>; -} +export type ChemPluginSettings = ChemPluginSettingsV3; +export const DEFAULT_SETTINGS = DEFAULT_SETTINGS_V3; +export const SETTINGS_VERSION = 'v3'; -export const DEFAULT_SETTINGS: ChemPluginSettings = { - version: SETTINGS_VERSION, - darkTheme: 'dark', - lightTheme: 'light', - sample1: SAMPLE_SMILES_1, - sample2: SAMPLE_SMILES_2, - imgWidth: 300, - copy: { - scale: 2, - transparent: true, - theme: 'default', - }, - dataview: false, - inlineSmiles: false, - inlineSmilesPrefix: '$smiles=', - options: {}, -}; +// const migrate_1_2 = (v1: ChemPluginSettingsV1): ChemPluginSettingsV2 => { +// v1 = { ...DEFAULT_SETTINGS_V1, ...v1 }; +// return { +// ...DEFAULT_SETTINGS_V2, +// darkTheme: v1.darkTheme, +// lightTheme: v1.lightTheme, +// sample1: v1.sample, +// imgWidth: parseInt(v1.width), +// }; +// }; -// Smiles-drawer options -// Reference: https://smilesdrawer.surge.sh/playground.html -export interface SMILES_DRAWER_OPTIONS { - width: number; - height: number; - scale: number; - bondThickness: number; - shortBondLength: number; - bondSpacing: number; - atomVisualization: 'default' | 'balls' | 'allballs'; - isomeric: boolean; - debug: boolean; - terminalCarbons: boolean; - explicitHydrogens: boolean; - overlapSensitivity: number; - overlapResolutionIterations: number; - compactDrawing: boolean; - fontFamily: string; - fontSizeLarge: number; - fontSizeSmall: number; - padding: number; - experimentalSSSR: boolean; - kkThreshold: number; - kkInnerThreshold: number; - kkMaxIteration: number; - kkMaxInnerIteration: number; - kkMaxEnergy: number; - themes: { - [key: string]: { - C: string; - O: string; - N: string; - F: string; - CL: string; - BR: string; - I: string; - P: string; - S: string; - B: string; - SI: string; - H: string; - BACKGROUND: string; - }; +const migrate_1_3 = (v1: ChemPluginSettingsV1): ChemPluginSettingsV3 => { + v1 = { ...DEFAULT_SETTINGS_V1, ...v1 }; + return { + ...DEFAULT_SETTINGS_V3, + darkTheme: v1.darkTheme, + lightTheme: v1.lightTheme, + sample1: v1.sample, + imgWidth: parseInt(v1.width), }; -} +}; -export const DEFAULT_SD_OPTIONS: SMILES_DRAWER_OPTIONS = { - width: 300, - height: 300, - scale: 1.0, - bondThickness: 1, - shortBondLength: 0.8, - bondSpacing: 5.1, - atomVisualization: 'default', - isomeric: true, - debug: false, - terminalCarbons: false, - explicitHydrogens: true, - overlapSensitivity: 0.42, - overlapResolutionIterations: 1, - compactDrawing: false, - fontFamily: 'Arial, Helvetica, sans-serif', - fontSizeLarge: 11, - fontSizeSmall: 3, - padding: 2, - experimentalSSSR: true, - kkThreshold: 0.1, - kkInnerThreshold: 0.1, - kkMaxIteration: 20000, - kkMaxInnerIteration: 50, - kkMaxEnergy: 1000000000, - themes: { - dark: { - C: '#fff', - O: '#e74c3c', - N: '#3498db', - F: '#27ae60', - CL: '#16a085', - BR: '#d35400', - I: '#8e44ad', - P: '#d35400', - S: '#f1c40f', - B: '#e67e22', - SI: '#e67e22', - H: '#aaa', - BACKGROUND: '#141414', - }, - light: { - C: '#222', - O: '#e74c3c', - N: '#3498db', - F: '#27ae60', - CL: '#16a085', - BR: '#d35400', - I: '#8e44ad', - P: '#d35400', - S: '#f1c40f', - B: '#e67e22', - SI: '#e67e22', - H: '#666', - BACKGROUND: '#fff', - }, - oldschool: { - C: '#000', - O: '#000', - N: '#000', - F: '#000', - CL: '#000', - BR: '#000', - I: '#000', - P: '#000', - S: '#000', - B: '#000', - SI: '#000', - H: '#000', - BACKGROUND: '#fff', - }, - 'oldschool-dark': { - C: '#fff', - O: '#fff', - N: '#fff', - F: '#fff', - CL: '#fff', - BR: '#fff', - I: '#fff', - P: '#fff', - S: '#fff', - B: '#fff', - SI: '#fff', - H: '#fff', - BACKGROUND: '#000', - }, - solarized: { - C: '#586e75', - O: '#dc322f', - N: '#268bd2', - F: '#859900', - CL: '#16a085', - BR: '#cb4b16', - I: '#6c71c4', - P: '#d33682', - S: '#b58900', - B: '#2aa198', - SI: '#2aa198', - H: '#657b83', - BACKGROUND: '#fff', - }, - 'solarized-dark': { - C: '#93a1a1', - O: '#dc322f', - N: '#268bd2', - F: '#859900', - CL: '#16a085', - BR: '#cb4b16', - I: '#6c71c4', - P: '#d33682', - S: '#b58900', - B: '#2aa198', - SI: '#2aa198', - H: '#839496', - BACKGROUND: '#fff', - }, - matrix: { - C: '#678c61', - O: '#2fc079', - N: '#4f7e7e', - F: '#90d762', - CL: '#82d967', - BR: '#23755a', - I: '#409931', - P: '#c1ff8a', - S: '#faff00', - B: '#50b45a', - SI: '#409931', - H: '#426644', - BACKGROUND: '#fff', +const migrate_2_3 = (v2: ChemPluginSettingsV2): ChemPluginSettingsV3 => { + v2 = { ...DEFAULT_SETTINGS_V2, ...v2 }; + return { + ...DEFAULT_SETTINGS_V3, + darkTheme: v2.darkTheme, + lightTheme: v2.lightTheme, + sample1: v2.sample1, + sample2: v2.sample2, + imgWidth: v2.imgWidth, + copy: { + scale: v2.copy.scale, + transparent: v2.copy.transparent, + theme: v2.copy.theme, }, - github: { - C: '#24292f', - O: '#cf222e', - N: '#0969da', - F: '#2da44e', - CL: '#6fdd8b', - BR: '#bc4c00', - I: '#8250df', - P: '#bf3989', - S: '#d4a72c', - B: '#fb8f44', - SI: '#bc4c00', - H: '#57606a', - BACKGROUND: '#fff', + dataview: v2.dataview, + inlineSmiles: v2.inlineSmiles, + inlineSmilesPrefix: v2.inlineSmilesPrefix, + smilesDrawerOptions: { + moleculeOptions: v2.options, + reactionOptions: {}, }, - carbon: { - C: '#161616', - O: '#da1e28', - N: '#0f62fe', - F: '#198038', - CL: '#007d79', - BR: '#fa4d56', - I: '#8a3ffc', - P: '#ff832b', - S: '#f1c21b', - B: '#8a3800', - SI: '#e67e22', - H: '#525252', - BACKGROUND: '#fff', - }, - cyberpunk: { - C: '#ea00d9', - O: '#ff3131', - N: '#0abdc6', - F: '#00ff9f', - CL: '#00fe00', - BR: '#fe9f20', - I: '#ff00ff', - P: '#fe7f00', - S: '#fcee0c', - B: '#ff00ff', - SI: '#ffffff', - H: '#913cb1', - BACKGROUND: '#fff', - }, - gruvbox: { - C: '#665c54', - O: '#cc241d', - N: '#458588', - F: '#98971a', - CL: '#79740e', - BR: '#d65d0e', - I: '#b16286', - P: '#af3a03', - S: '#d79921', - B: '#689d6a', - SI: '#427b58', - H: '#7c6f64', - BACKGROUND: '#fbf1c7', - }, - 'gruvbox-dark': { - C: '#ebdbb2', - O: '#cc241d', - N: '#458588', - F: '#98971a', - CL: '#b8bb26', - BR: '#d65d0e', - I: '#b16286', - P: '#fe8019', - S: '#d79921', - B: '#8ec07c', - SI: '#83a598', - H: '#bdae93', - BACKGROUND: '#282828', - }, - custom: { - C: '#222', - O: '#e74c3c', - N: '#3498db', - F: '#27ae60', - CL: '#16a085', - BR: '#d35400', - I: '#8e44ad', - P: '#d35400', - S: '#f1c40f', - B: '#e67e22', - SI: '#e67e22', - H: '#666', - BACKGROUND: '#fff', - }, - }, + }; +}; + +const migrate_3_3 = (draft: ChemPluginSettingsV3): ChemPluginSettingsV3 => { + return { ...DEFAULT_SETTINGS, ...draft }; }; -export const themeList = { - light: 'Light', - dark: 'Dark', - oldschool: 'Oldschool', - 'oldschool-dark': 'Oldschool Dark', - solarized: 'Solarized', - 'solarized-dark': 'Solarized Dark', - matrix: 'Matrix', - github: 'GitHub', - carbon: 'Carbon', - cyberpunk: 'Cyberpunk', - gruvbox: 'Gruvbox', - 'gruvbox-dark': 'Gruvbox Dark', +export const migrateSettings = (draft: any): ChemPluginSettingsV3 => { + if (Object.keys(draft).length === 0) return DEFAULT_SETTINGS; + if (!('version' in draft)) return migrate_1_3(draft); // v1 + else if (draft.version === 'v2') return migrate_2_3(draft); + else if (draft.version === 'v3') return migrate_3_3(draft); // current + return DEFAULT_SETTINGS; // consider branch coverage rate }; diff --git a/src/settings/smilesDrawerOptions.ts b/src/settings/smilesDrawerOptions.ts new file mode 100644 index 0000000..46b0376 --- /dev/null +++ b/src/settings/smilesDrawerOptions.ts @@ -0,0 +1,97 @@ +import { theme, themes } from './theme'; + +// Smiles-drawer options +// Reference: https://smilesdrawer.surge.sh/playground.html +export interface SD_MoleculeOptions { + width: number; + height: number; + scale: number; + bondThickness: number; + shortBondLength: number; + bondSpacing: number; + atomVisualization: 'default' | 'balls' | 'allballs'; + isomeric: boolean; + debug: boolean; + terminalCarbons: boolean; + explicitHydrogens: boolean; + overlapSensitivity: number; + overlapResolutionIterations: number; + compactDrawing: boolean; + fontFamily: string; + fontSizeLarge: number; + fontSizeSmall: number; + padding: number; + experimentalSSSR: boolean; + kkThreshold: number; + kkInnerThreshold: number; + kkMaxIteration: number; + kkMaxInnerIteration: number; + kkMaxEnergy: number; + themes: Record<string, theme>; +} + +export interface SD_ReactionOptions { + fontSize: number; + fontFamily: string; // comma separated font descriptions. + spacing: number; + plus: { + size: number; + thickness: number; + }; + arrow: { + length: number; + headSize: number; + thickness: number; + margin: number; + }; +} + +export interface SMILES_DRAWER_OPTIONS { + moleculeOptions: SD_MoleculeOptions; + reactionOptions: SD_ReactionOptions; +} + +export const DEFAULT_SD_OPTIONS: SMILES_DRAWER_OPTIONS = { + moleculeOptions: { + width: 300, + height: 300, + scale: 1, + bondThickness: 1, + shortBondLength: 0.8, + bondSpacing: 5.1, + atomVisualization: 'default', + isomeric: true, + debug: false, + terminalCarbons: false, + explicitHydrogens: true, + overlapSensitivity: 0.42, + overlapResolutionIterations: 1, + compactDrawing: false, + fontFamily: 'Arial, Helvetica, sans-serif', + fontSizeLarge: 11, + fontSizeSmall: 3, + padding: 2, + experimentalSSSR: true, + kkThreshold: 0.1, + kkInnerThreshold: 0.1, + kkMaxIteration: 20000, + kkMaxInnerIteration: 50, + kkMaxEnergy: 1000000000, + themes: themes, + }, + reactionOptions: { + fontSize: 9, + fontFamily: 'Arial, Helvetica, sans-serif', + spacing: 10, + plus: { + size: 9, + thickness: 1, + }, + arrow: { + length: 120, + headSize: 6, + thickness: 1, + margin: 3, + }, + }, +}; diff --git a/src/settings/theme.ts b/src/settings/theme.ts new file mode 100644 index 0000000..4d25670 --- /dev/null +++ b/src/settings/theme.ts @@ -0,0 +1,228 @@ +export interface theme { + C: string; + O: string; + N: string; + F: string; + CL: string; + BR: string; + I: string; + P: string; + S: string; + B: string; + SI: string; + H: string; + BACKGROUND: string; +} + +export const themeList = { + light: 'Light', + dark: 'Dark', + oldschool: 'Oldschool', + 'oldschool-dark': 'Oldschool Dark', + solarized: 'Solarized', + 'solarized-dark': 'Solarized Dark', + matrix: 'Matrix', + github: 'GitHub', + carbon: 'Carbon', + cyberpunk: 'Cyberpunk', + gruvbox: 'Gruvbox', + 'gruvbox-dark': 'Gruvbox Dark', +}; + +export const themes: Record<string, theme> = { + dark: { + C: '#fff', + O: '#e74c3c', + N: '#3498db', + F: '#27ae60', + CL: '#16a085', + BR: '#d35400', + I: '#8e44ad', + P: '#d35400', + S: '#f1c40f', + B: '#e67e22', + SI: '#e67e22', + H: '#aaa', + BACKGROUND: '#141414', + }, + light: { + C: '#222', + O: '#e74c3c', + N: '#3498db', + F: '#27ae60', + CL: '#16a085', + BR: '#d35400', + I: '#8e44ad', + P: '#d35400', + S: '#f1c40f', + B: '#e67e22', + SI: '#e67e22', + H: '#666', + BACKGROUND: '#fff', + }, + oldschool: { + C: '#000', + O: '#000', + N: '#000', + F: '#000', + CL: '#000', + BR: '#000', + I: '#000', + P: '#000', + S: '#000', + B: '#000', + SI: '#000', + H: '#000', + BACKGROUND: '#fff', + }, + 'oldschool-dark': { + C: '#fff', + O: '#fff', + N: '#fff', + F: '#fff', + CL: '#fff', + BR: '#fff', + I: '#fff', + P: '#fff', + S: '#fff', + B: '#fff', + SI: '#fff', + H: '#fff', + BACKGROUND: '#000', + }, + solarized: { + C: '#586e75', + O: '#dc322f', + N: '#268bd2', + F: '#859900', + CL: '#16a085', + BR: '#cb4b16', + I: '#6c71c4', + P: '#d33682', + S: '#b58900', + B: '#2aa198', + SI: '#2aa198', + H: '#657b83', + BACKGROUND: '#fff', + }, + 'solarized-dark': { + C: '#93a1a1', + O: '#dc322f', + N: '#268bd2', + F: '#859900', + CL: '#16a085', + BR: '#cb4b16', + I: '#6c71c4', + P: '#d33682', + S: '#b58900', + B: '#2aa198', + SI: '#2aa198', + H: '#839496', + BACKGROUND: '#fff', + }, + matrix: { + C: '#678c61', + O: '#2fc079', + N: '#4f7e7e', + F: '#90d762', + CL: '#82d967', + BR: '#23755a', + I: '#409931', + P: '#c1ff8a', + S: '#faff00', + B: '#50b45a', + SI: '#409931', + H: '#426644', + BACKGROUND: '#fff', + }, + github: { + C: '#24292f', + O: '#cf222e', + N: '#0969da', + F: '#2da44e', + CL: '#6fdd8b', + BR: '#bc4c00', + I: '#8250df', + P: '#bf3989', + S: '#d4a72c', + B: '#fb8f44', + SI: '#bc4c00', + H: '#57606a', + BACKGROUND: '#fff', + }, + carbon: { + C: '#161616', + O: '#da1e28', + N: '#0f62fe', + F: '#198038', + CL: '#007d79', + BR: '#fa4d56', + I: '#8a3ffc', + P: '#ff832b', + S: '#f1c21b', + B: '#8a3800', + SI: '#e67e22', + H: '#525252', + BACKGROUND: '#fff', + }, + cyberpunk: { + C: '#ea00d9', + O: '#ff3131', + N: '#0abdc6', + F: '#00ff9f', + CL: '#00fe00', + BR: '#fe9f20', + I: '#ff00ff', + P: '#fe7f00', + S: '#fcee0c', + B: '#ff00ff', + SI: '#ffffff', + H: '#913cb1', + BACKGROUND: '#fff', + }, + gruvbox: { + C: '#665c54', + O: '#cc241d', + N: '#458588', + F: '#98971a', + CL: '#79740e', + BR: '#d65d0e', + I: '#b16286', + P: '#af3a03', + S: '#d79921', + B: '#689d6a', + SI: '#427b58', + H: '#7c6f64', + BACKGROUND: '#fbf1c7', + }, + 'gruvbox-dark': { + C: '#ebdbb2', + O: '#cc241d', + N: '#458588', + F: '#98971a', + CL: '#b8bb26', + BR: '#d65d0e', + I: '#b16286', + P: '#fe8019', + S: '#d79921', + B: '#8ec07c', + SI: '#83a598', + H: '#bdae93', + BACKGROUND: '#282828', + }, + custom: { + C: '#222', + O: '#e74c3c', + N: '#3498db', + F: '#27ae60', + CL: '#16a085', + BR: '#d35400', + I: '#8e44ad', + P: '#d35400', + S: '#f1c40f', + B: '#e67e22', + SI: '#e67e22', + H: '#666', + BACKGROUND: '#fff', + }, +}; diff --git a/src/settings/update.ts b/src/settings/update.ts deleted file mode 100644 index d8bad03..0000000 --- a/src/settings/update.ts +++ /dev/null @@ -1,59 +0,0 @@ -interface ChemPluginSettingsV1 { - darkTheme: string; - lightTheme: string; - sample: string; - width: string; -} - -// const DEFAULT_SETTINGS_V1: ChemPluginSettingsV1 = { -// darkTheme: 'dark', -// lightTheme: 'light', -// sample: 'CC(=O)NC1=C-C=C-C=C1-C(=O)O', -// width: '300', -// }; - -interface ChemPluginSettingsV2 { - version: string; - darkTheme: string; - lightTheme: string; - sample1: string; - sample2: string; - imgWidth: number; - copy: { - scale: number; - transparent: boolean; - theme: string; - }; - dataview: boolean; - inlineSmiles: boolean; - inlineSmilesPrefix: string; - options: object; -} - -const DEFAULT_SETTINGS_V2: ChemPluginSettingsV2 = { - version: 'v2', - darkTheme: 'dark', - lightTheme: 'light', - sample1: 'OC(=O)C(C)=CC1=CC=CC=C1', - sample2: - 'OC(C(=O)O[C@H]1C[N+]2(CCCOC3=CC=CC=C3)CCC1CC2)(C1=CC=CS1)C1=CC=CS1', - imgWidth: 300, - copy: { - scale: 2, - transparent: true, - theme: 'default', - }, - dataview: false, - inlineSmiles: false, - inlineSmilesPrefix: '$smiles=', - options: {}, -}; - -export const updateSettingsVersion = (stale: ChemPluginSettingsV1) => { - const result = { ...DEFAULT_SETTINGS_V2 }; - result.darkTheme = stale.darkTheme; - result.lightTheme = stale.lightTheme; - result.sample1 = stale.sample; - result.imgWidth = parseInt(stale.width); - return result; -}; diff --git a/src/settings/v1.ts b/src/settings/v1.ts new file mode 100644 index 0000000..5df6469 --- /dev/null +++ b/src/settings/v1.ts @@ -0,0 +1,12 @@ +export interface ChemPluginSettingsV1 { + darkTheme: string; + lightTheme: string; + sample: string; + width: string; +} +export const DEFAULT_SETTINGS_V1: ChemPluginSettingsV1 = { + darkTheme: 'dark', + lightTheme: 'light', + sample: 'CC(=O)NC1=C-C=C-C=C1-C(=O)O', + width: '300', +}; diff --git a/src/settings/v2.ts b/src/settings/v2.ts new file mode 100644 index 0000000..52fcfac --- /dev/null +++ b/src/settings/v2.ts @@ -0,0 +1,35 @@ +export interface ChemPluginSettingsV2 { + version: string; + darkTheme: string; + lightTheme: string; + sample1: string; + sample2: string; + imgWidth: number; + copy: { + scale: number; + transparent: boolean; + theme: string; + }; + dataview: boolean; + inlineSmiles: boolean; + inlineSmilesPrefix: string; + options: object; +} +export const DEFAULT_SETTINGS_V2: ChemPluginSettingsV2 = { + version: 'v2', + darkTheme: 'dark', + lightTheme: 'light', + sample1: 'OC(=O)C(C)=CC1=CC=CC=C1', + sample2: + 'OC(C(=O)O[C@H]1C[N+]2(CCCOC3=CC=CC=C3)CCC1CC2)(C1=CC=CS1)C1=CC=CS1', + imgWidth: 300, + copy: { + scale: 2, + transparent: true, + theme: 'default', + }, + dataview: false, + inlineSmiles: false, + inlineSmilesPrefix: '$smiles=', + options: {}, +}; diff --git a/src/settings/v3.ts b/src/settings/v3.ts new file mode 100644 index 0000000..479a50b --- /dev/null +++ b/src/settings/v3.ts @@ -0,0 +1,43 @@ +import { SD_MoleculeOptions, SD_ReactionOptions } from './smilesDrawerOptions'; + +export interface ChemPluginSettingsV3 { + version: string; + darkTheme: string; + lightTheme: string; + sample1: string; + sample2: string; + imgWidth: number; + copy: { + scale: number; + transparent: boolean; + theme: string; + }; + dataview: boolean; + inlineSmiles: boolean; + inlineSmilesPrefix: string; + smilesDrawerOptions: { + moleculeOptions: Partial<SD_MoleculeOptions>; + reactionOptions: Partial<SD_ReactionOptions>; + }; +} +export const DEFAULT_SETTINGS_V3: ChemPluginSettingsV3 = { + version: 'v3', + darkTheme: 'dark', + lightTheme: 'light', + sample1: 'OC(=O)C(C)=CC1=CC=CC=C1', + sample2: + 'OC(C(=O)O[C@H]1C[N+]2(CCCOC3=CC=CC=C3)CCC1CC2)(C1=CC=CS1)C1=CC=CS1', + imgWidth: 300, + copy: { + scale: 2, + transparent: true, + theme: 'default', + }, + dataview: false, + inlineSmiles: false, + inlineSmilesPrefix: '$smiles=', + smilesDrawerOptions: { + moleculeOptions: {}, + reactionOptions: {}, + }, +};