diff --git a/src/__tests__/renderHighlightColorQuote.spec.ts b/src/__tests__/renderHighlightColorQuote.spec.ts
new file mode 100644
index 0000000..8138037
--- /dev/null
+++ b/src/__tests__/renderHighlightColorQuote.spec.ts
@@ -0,0 +1,109 @@
+import { HighlightRenderOption, formatHighlightQuote } from '../util'
+import { HighlightManagerId } from '../settings'
+
+type testCase = {
+ quote: string
+ template: string
+ highlightRenderOption: HighlightRenderOption | null
+ expected: string
+}
+
+const quote = 'some quote'
+const color = 'red'
+const templateWithoutBlockQuote = `{{#highlights}}
+{{{text}}}
+{{/highlights}}`
+const templateWithBlockQuote = `{{#highlights}}
+> {{{text}}}
+{{/highlights}}`
+
+const blockQuoteNoHighlightRenderOption = {
+ quote: quote,
+ template: templateWithBlockQuote,
+ highlightRenderOption: null,
+ expected: quote,
+}
+
+const noBlockQuoteNoHighlightRenderOption = {
+ quote: quote,
+ template: templateWithoutBlockQuote,
+ highlightRenderOption: null,
+ expected: quote,
+}
+
+const blockQuoteOmnivoreRenderOption = {
+ quote: quote,
+ template: templateWithBlockQuote,
+ highlightRenderOption: {
+ highlightManagerId: HighlightManagerId.OMNIVORE,
+ highlightColor: color,
+ },
+ expected: `${quote}`,
+}
+
+const blockQuoteMultiLineOmnivoreRenderOption = {
+ quote: `${quote}
+${quote}`,
+ template: templateWithBlockQuote,
+ highlightRenderOption: {
+ highlightManagerId: HighlightManagerId.OMNIVORE,
+ highlightColor: color,
+ },
+ expected: `${quote}
+> ${quote}`,
+}
+
+const blockQuoteHighlightrRenderOption = {
+ quote: quote,
+ template: templateWithBlockQuote,
+ highlightRenderOption: {
+ highlightManagerId: HighlightManagerId.HIGHLIGHTR,
+ highlightColor: color,
+ },
+ expected: `${quote}`,
+}
+
+const noBlockQuoteMultiLineOmnivoreRenderOption = {
+ quote: `${quote}
+${quote}`,
+ template: templateWithoutBlockQuote,
+ highlightRenderOption: {
+ highlightManagerId: HighlightManagerId.OMNIVORE,
+ highlightColor: color,
+ },
+ expected: `${quote}
+${quote}`,
+}
+
+const blockQuoteEmptyLineOmnivoreRenderOption = {
+ quote: `${quote}
+ `,
+ template: templateWithBlockQuote,
+ highlightRenderOption: {
+ highlightManagerId: HighlightManagerId.OMNIVORE,
+ highlightColor: color,
+ },
+ expected: `${quote}
+>`,
+}
+
+const testCases: testCase[] = [
+ blockQuoteNoHighlightRenderOption,
+ noBlockQuoteNoHighlightRenderOption,
+ blockQuoteOmnivoreRenderOption,
+ blockQuoteMultiLineOmnivoreRenderOption,
+ blockQuoteHighlightrRenderOption,
+ noBlockQuoteMultiLineOmnivoreRenderOption,
+ blockQuoteEmptyLineOmnivoreRenderOption,
+]
+
+describe('formatHighlightQuote', () => {
+ test.each(testCases)('should correctly for format %s', (testCase) => {
+ const result = formatHighlightQuote(
+ testCase.quote,
+ testCase.template,
+ testCase.highlightRenderOption,
+ )
+ expect(result).toBe(testCase.expected)
+ })
+})
diff --git a/src/api.ts b/src/api.ts
index 0e613f5..1300187 100644
--- a/src/api.ts
+++ b/src/api.ts
@@ -1,5 +1,12 @@
import { Item, ItemFormat, Omnivore } from '@omnivore-app/api'
+export enum HighlightColors {
+ Yellow = 'yellow',
+ Red = 'red',
+ Green = 'green',
+ Blue = 'blue',
+}
+
export const getItems = async (
endpoint: string,
apiKey: string,
diff --git a/src/main.ts b/src/main.ts
index 3b9ab88..4f1e028 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,31 +1,21 @@
import { Item } from '@omnivore-app/api'
import {
addIcon,
- App,
normalizePath,
Notice,
Plugin,
- PluginSettingTab,
requestUrl,
- Setting,
stringifyYaml,
TFile,
TFolder,
} from 'obsidian'
import { deleteItem, getItems } from './api'
-import {
- DEFAULT_SETTINGS,
- Filter,
- FRONT_MATTER_VARIABLES,
- HighlightOrder,
- OmnivoreSettings,
-} from './settings'
-import { FolderSuggest } from './settings/file-suggest'
+import { DEFAULT_SETTINGS, OmnivoreSettings } from './settings'
import {
preParseTemplate,
render,
renderFilename,
- renderItemContnet,
+ renderItemContent,
} from './settings/template'
import {
findFrontMatterIndex,
@@ -34,7 +24,9 @@ import {
parseFrontMatterFromContent,
removeFrontMatterFromContent,
replaceIllegalChars,
+ setOrUpdateHighlightColors,
} from './util'
+import { OmnivoreSettingTab } from './settingsTab'
export default class OmnivorePlugin extends Plugin {
settings: OmnivoreSettings
@@ -137,6 +129,8 @@ export default class OmnivorePlugin extends Plugin {
)
this.saveSettings()
}
+ // initialize css highlight color variables
+ setOrUpdateHighlightColors(this.settings.highlightColorMapping)
}
async saveSettings() {
@@ -254,9 +248,7 @@ export default class OmnivorePlugin extends Plugin {
for (const item of items) {
const folderName = replaceIllegalChars(
- normalizePath(
- render(item, folder, this.settings.folderDateFormat),
- )
+ normalizePath(render(item, folder, this.settings.folderDateFormat)),
)
const omnivoreFolder =
this.app.vault.getAbstractFileByPath(folderName)
@@ -267,10 +259,13 @@ export default class OmnivorePlugin extends Plugin {
item.pageType === 'FILE' && includeFileAttachment
? await this.downloadFileAsAttachment(item)
: undefined
- const content = await renderItemContnet(
+ const content = await renderItemContent(
item,
template,
highlightOrder,
+ this.settings.enableHighlightColorRender
+ ? this.settings.highlightManagerId
+ : undefined,
this.settings.dateHighlightedFormat,
this.settings.dateSavedFormat,
isSingleFile,
@@ -447,457 +442,3 @@ export default class OmnivorePlugin extends Plugin {
await this.saveSettings()
}
}
-
-class OmnivoreSettingTab extends PluginSettingTab {
- plugin: OmnivorePlugin
-
- constructor(app: App, plugin: OmnivorePlugin) {
- super(app, plugin)
- this.plugin = plugin
- }
-
- display(): void {
- const { containerEl } = this
-
- containerEl.empty()
-
- containerEl.createEl('h2', { text: 'Settings for Omnivore plugin' })
-
- new Setting(containerEl)
- .setName('API Key')
- .setDesc(
- createFragment((fragment) => {
- fragment.append(
- 'You can create an API key at ',
- fragment.createEl('a', {
- text: 'https://omnivore.app/settings/api',
- href: 'https://omnivore.app/settings/api',
- }),
- )
- }),
- )
- .addText((text) =>
- text
- .setPlaceholder('Enter your Omnivore Api Key')
- .setValue(this.plugin.settings.apiKey)
- .onChange(async (value) => {
- this.plugin.settings.apiKey = value
- await this.plugin.saveSettings()
- }),
- )
-
- new Setting(containerEl)
- .setName('Filter')
- .setDesc(
- "Select an Omnivore search filter type. Changing this would update the 'Custom Query' accordingly and reset the 'Last sync' timestamp",
- )
- .addDropdown((dropdown) => {
- dropdown.addOptions(Filter)
- dropdown
- .setValue(this.plugin.settings.filter)
- .onChange(async (value) => {
- this.plugin.settings.filter = value
- this.plugin.settings.customQuery = getQueryFromFilter(value)
- this.plugin.settings.syncAt = ''
- await this.plugin.saveSettings()
- this.display()
- })
- })
-
- new Setting(containerEl)
- .setName('Custom Query')
- .setDesc(
- createFragment((fragment) => {
- fragment.append(
- 'See ',
- fragment.createEl('a', {
- text: 'https://docs.omnivore.app/using/search',
- href: 'https://docs.omnivore.app/using/search',
- }),
- " for more info on search query syntax. Changing this would reset the 'Last Sync' timestamp",
- )
- }),
- )
- .addText((text) =>
- text
- .setPlaceholder(
- 'Enter an Omnivore custom search query if advanced filter is selected',
- )
- .setValue(this.plugin.settings.customQuery)
- .onChange(async (value) => {
- this.plugin.settings.customQuery = value
- this.plugin.settings.syncAt = ''
- await this.plugin.saveSettings()
- }),
- )
-
- new Setting(containerEl)
- .setName('Last Sync')
- .setDesc(
- "Last time the plugin synced with Omnivore. The 'Sync' command fetches articles updated after this timestamp",
- )
- .addMomentFormat((momentFormat) =>
- momentFormat
- .setPlaceholder('Last Sync')
- .setValue(this.plugin.settings.syncAt)
- .setDefaultFormat("yyyy-MM-dd'T'HH:mm:ss")
- .onChange(async (value) => {
- this.plugin.settings.syncAt = value
- await this.plugin.saveSettings()
- }),
- )
-
- new Setting(containerEl)
- .setName('Highlight Order')
- .setDesc('Select the order in which highlights are applied')
- .addDropdown((dropdown) => {
- dropdown.addOptions(HighlightOrder)
- dropdown
- .setValue(this.plugin.settings.highlightOrder)
- .onChange(async (value) => {
- this.plugin.settings.highlightOrder = value
- await this.plugin.saveSettings()
- })
- })
-
- new Setting(containerEl)
- .setName('Front Matter')
- .setDesc(
- createFragment((fragment) => {
- fragment.append(
- 'Enter the metadata to be used in your note separated by commas. You can also use custom aliases in the format of metatdata::alias, e.g. date_saved::date. ',
- fragment.createEl('br'),
- fragment.createEl('br'),
- 'Available metadata can be found at ',
- fragment.createEl('a', {
- text: 'Reference',
- href: 'https://docs.omnivore.app/integrations/obsidian.html#front-matter',
- }),
- fragment.createEl('br'),
- fragment.createEl('br'),
- 'If you want to use a custom front matter template, you can enter it below under the advanced settings',
- )
- }),
- )
- .addTextArea((text) => {
- text
- .setPlaceholder('Enter the metadata')
- .setValue(this.plugin.settings.frontMatterVariables.join(','))
- .onChange(async (value) => {
- // validate front matter variables and deduplicate
- this.plugin.settings.frontMatterVariables = value
- .split(',')
- .map((v) => v.trim())
- .filter(
- (v, i, a) =>
- FRONT_MATTER_VARIABLES.includes(v.split('::')[0]) &&
- a.indexOf(v) === i,
- )
- await this.plugin.saveSettings()
- })
- text.inputEl.setAttr('rows', 4)
- text.inputEl.setAttr('cols', 30)
- })
-
- new Setting(containerEl)
- .setName('Article Template')
- .setDesc(
- createFragment((fragment) => {
- fragment.append(
- 'Enter template to render articles with ',
- fragment.createEl('a', {
- text: 'Reference',
- href: 'https://docs.omnivore.app/integrations/obsidian.html#controlling-the-layout-of-the-data-imported-to-obsidian',
- }),
- fragment.createEl('br'),
- fragment.createEl('br'),
- 'If you want to use a custom front matter template, you can enter it below under the advanced settings',
- )
- }),
- )
- .addTextArea((text) => {
- text
- .setPlaceholder('Enter the template')
- .setValue(this.plugin.settings.template)
- .onChange(async (value) => {
- // if template is empty, use default template
- this.plugin.settings.template = value
- ? value
- : DEFAULT_SETTINGS.template
- await this.plugin.saveSettings()
- })
- text.inputEl.setAttr('rows', 25)
- text.inputEl.setAttr('cols', 50)
- })
- .addExtraButton((button) => {
- // add a button to reset template
- button
- .setIcon('reset')
- .setTooltip('Reset template')
- .onClick(async () => {
- this.plugin.settings.template = DEFAULT_SETTINGS.template
- await this.plugin.saveSettings()
- this.display()
- new Notice('Template reset')
- })
- })
-
- new Setting(containerEl)
- .setName('Sync on startup')
- .setDesc(
- 'Check this box if you want to sync with Omnivore when the app is loaded',
- )
- .addToggle((toggle) =>
- toggle
- .setValue(this.plugin.settings.syncOnStart)
- .onChange(async (value) => {
- this.plugin.settings.syncOnStart = value
- await this.plugin.saveSettings()
- }),
- )
-
- new Setting(containerEl)
- .setName('Frequency')
- .setDesc(
- 'Enter the frequency in minutes to sync with Omnivore automatically. 0 means manual sync',
- )
- .addText((text) =>
- text
- .setPlaceholder('Enter the frequency')
- .setValue(this.plugin.settings.frequency.toString())
- .onChange(async (value) => {
- // validate frequency
- const frequency = parseInt(value)
- if (isNaN(frequency)) {
- new Notice('Frequency must be a positive integer')
- return
- }
- // save frequency
- this.plugin.settings.frequency = frequency
- await this.plugin.saveSettings()
-
- this.plugin.scheduleSync()
- }),
- )
-
- new Setting(containerEl)
- .setName('Folder')
- .setDesc(
- 'Enter the folder where the data will be stored. {{{title}}}, {{{dateSaved}}} and {{{datePublished}}} could be used in the folder name',
- )
- .addSearch((search) => {
- new FolderSuggest(this.app, search.inputEl)
- search
- .setPlaceholder('Enter the folder')
- .setValue(this.plugin.settings.folder)
- .onChange(async (value) => {
- this.plugin.settings.folder = value
- await this.plugin.saveSettings()
- })
- })
- new Setting(containerEl)
- .setName('Attachment Folder')
- .setDesc(
- 'Enter the folder where the attachment will be downloaded to. {{{title}}}, {{{dateSaved}}} and {{{datePublished}}} could be used in the folder name',
- )
- .addSearch((search) => {
- new FolderSuggest(this.app, search.inputEl)
- search
- .setPlaceholder('Enter the attachment folder')
- .setValue(this.plugin.settings.attachmentFolder)
- .onChange(async (value) => {
- this.plugin.settings.attachmentFolder = value
- await this.plugin.saveSettings()
- })
- })
-
- new Setting(containerEl)
- .setName('Is Single File')
- .setDesc(
- 'Check this box if you want to save all articles in a single file',
- )
- .addToggle((toggle) =>
- toggle
- .setValue(this.plugin.settings.isSingleFile)
- .onChange(async (value) => {
- this.plugin.settings.isSingleFile = value
- await this.plugin.saveSettings()
- }),
- )
-
- new Setting(containerEl)
- .setName('Filename')
- .setDesc(
- 'Enter the filename where the data will be stored. {{id}}, {{{title}}}, {{{dateSaved}}} and {{{datePublished}}} could be used in the filename',
- )
- .addText((text) =>
- text
- .setPlaceholder('Enter the filename')
- .setValue(this.plugin.settings.filename)
- .onChange(async (value) => {
- this.plugin.settings.filename = value
- await this.plugin.saveSettings()
- }),
- )
-
- new Setting(containerEl)
- .setName('Filename Date Format')
- .setDesc(
- createFragment((fragment) => {
- fragment.append(
- 'Enter the format date for use in rendered filename. Format ',
- fragment.createEl('a', {
- text: 'reference',
- href: 'https://moment.github.io/luxon/#/formatting?id=table-of-tokens',
- }),
- )
- }),
- )
- .addText((text) =>
- text
- .setPlaceholder('yyyy-MM-dd')
- .setValue(this.plugin.settings.filenameDateFormat)
- .onChange(async (value) => {
- this.plugin.settings.filenameDateFormat = value
- await this.plugin.saveSettings()
- }),
- )
-
- new Setting(containerEl)
- .setName('Folder Date Format')
- .setDesc(
- createFragment((fragment) => {
- fragment.append(
- 'Enter the format date for use in rendered folder name. Format ',
- fragment.createEl('a', {
- text: 'reference',
- href: 'https://moment.github.io/luxon/#/formatting?id=table-of-tokens',
- }),
- )
- }),
- )
- .addText((text) =>
- text
- .setPlaceholder('yyyy-MM-dd')
- .setValue(this.plugin.settings.folderDateFormat)
- .onChange(async (value) => {
- this.plugin.settings.folderDateFormat = value
- await this.plugin.saveSettings()
- }),
- )
- new Setting(containerEl)
- .setName('Date Saved Format')
- .setDesc(
- 'Enter the date format for dateSaved variable in rendered template',
- )
- .addText((text) =>
- text
- .setPlaceholder("yyyy-MM-dd'T'HH:mm:ss")
- .setValue(this.plugin.settings.dateSavedFormat)
- .onChange(async (value) => {
- this.plugin.settings.dateSavedFormat = value
- await this.plugin.saveSettings()
- }),
- )
- new Setting(containerEl)
- .setName('Date Highlighted Format')
- .setDesc(
- 'Enter the date format for dateHighlighted variable in rendered template',
- )
- .addText((text) =>
- text
- .setPlaceholder('Date Highlighted Format')
- .setValue(this.plugin.settings.dateHighlightedFormat)
- .onChange(async (value) => {
- this.plugin.settings.dateHighlightedFormat = value
- await this.plugin.saveSettings()
- }),
- )
-
- containerEl.createEl('h5', {
- cls: 'omnivore-collapsible',
- text: 'Advanced Settings',
- })
-
- const advancedSettings = containerEl.createEl('div', {
- cls: 'omnivore-content',
- })
-
- new Setting(advancedSettings)
- .setName('API Endpoint')
- .setDesc("Enter the Omnivore server's API endpoint")
- .addText((text) =>
- text
- .setPlaceholder('API endpoint')
- .setValue(this.plugin.settings.endpoint)
- .onChange(async (value) => {
- this.plugin.settings.endpoint = value
- await this.plugin.saveSettings()
- }),
- )
-
- new Setting(advancedSettings)
- .setName('Front Matter Template')
- .setDesc(
- createFragment((fragment) => {
- fragment.append(
- 'Enter YAML template to render the front matter with ',
- fragment.createEl('a', {
- text: 'Reference',
- href: 'https://docs.omnivore.app/integrations/obsidian.html#front-matter-template',
- }),
- fragment.createEl('br'),
- fragment.createEl('br'),
- 'We recommend you to use Front Matter section under the basic settings to define the metadata.',
- fragment.createEl('br'),
- fragment.createEl('br'),
- 'If this template is set, it will override the Front Matter so please make sure your template is a valid YAML.',
- )
- }),
- )
- .addTextArea((text) => {
- text
- .setPlaceholder('Enter the template')
- .setValue(this.plugin.settings.frontMatterTemplate)
- .onChange(async (value) => {
- this.plugin.settings.frontMatterTemplate = value
- await this.plugin.saveSettings()
- })
-
- text.inputEl.setAttr('rows', 10)
- text.inputEl.setAttr('cols', 30)
- })
- .addExtraButton((button) => {
- // add a button to reset template
- button
- .setIcon('reset')
- .setTooltip('Reset front matter template')
- .onClick(async () => {
- this.plugin.settings.frontMatterTemplate =
- DEFAULT_SETTINGS.frontMatterTemplate
- await this.plugin.saveSettings()
- this.display()
- new Notice('Front matter template reset')
- })
- })
-
- const help = containerEl.createEl('p')
- help.innerHTML = `For more information, please visit our GitHub page, email us at feedback@omnivore.app or join our Discord server.`
-
- // script to make collapsible sections
- const coll = document.getElementsByClassName('omnivore-collapsible')
- let i
-
- for (i = 0; i < coll.length; i++) {
- coll[i].addEventListener('click', function () {
- this.classList.toggle('omnivore-active')
- const content = this.nextElementSibling
- if (content.style.maxHeight) {
- content.style.maxHeight = null
- } else {
- content.style.maxHeight = 'fit-content'
- }
- })
- }
- }
-}
diff --git a/src/settings/index.ts b/src/settings/index.ts
index 2c4f63a..e70d33f 100644
--- a/src/settings/index.ts
+++ b/src/settings/index.ts
@@ -1,3 +1,4 @@
+import { HighlightColors } from '../api'
import { DEFAULT_TEMPLATE } from './template'
export const FRONT_MATTER_VARIABLES = [
@@ -20,6 +21,25 @@ export const FRONT_MATTER_VARIABLES = [
'image',
]
+export enum Filter {
+ ALL = 'Sync all the items',
+ LIBRARY = 'Sync only the library items',
+ ARCHIVED = 'Sync only the archived items',
+ HIGHLIGHTS = 'Sync only the highlighted items',
+}
+
+export enum HighlightOrder {
+ LOCATION = 'the location of highlights in the article',
+ TIME = 'the time that highlights are updated',
+}
+
+export enum HighlightManagerId {
+ HIGHLIGHTR = 'hltr',
+ OMNIVORE = 'omni',
+}
+
+export type HighlightColorMapping = { [key in HighlightColors]: string }
+
export const DEFAULT_SETTINGS: OmnivoreSettings = {
dateHighlightedFormat: 'yyyy-MM-dd HH:mm:ss',
dateSavedFormat: 'yyyy-MM-dd HH:mm:ss',
@@ -43,18 +63,14 @@ export const DEFAULT_SETTINGS: OmnivoreSettings = {
frontMatterVariables: [],
frontMatterTemplate: '',
syncOnStart: true,
-}
-
-export enum Filter {
- ALL = 'Sync all the items',
- LIBRARY = 'Sync only the library items',
- ARCHIVED = 'Sync only the archived items',
- HIGHLIGHTS = 'Sync only the highlighted items',
-}
-
-export enum HighlightOrder {
- LOCATION = 'the location of highlights in the article',
- TIME = 'the time that highlights are updated',
+ enableHighlightColorRender: false,
+ highlightManagerId: HighlightManagerId.OMNIVORE,
+ highlightColorMapping: {
+ [HighlightColors.Yellow]: '#fff3a3',
+ [HighlightColors.Red]: '#ff5582',
+ [HighlightColors.Blue]: '#adccff',
+ [HighlightColors.Green]: '#bbfabb',
+ },
}
export interface OmnivoreSettings {
@@ -80,4 +96,7 @@ export interface OmnivoreSettings {
frontMatterTemplate: string
filenameDateFormat: string
syncOnStart: boolean
+ enableHighlightColorRender: boolean
+ highlightManagerId: HighlightManagerId
+ highlightColorMapping: HighlightColorMapping
}
diff --git a/src/settings/template.ts b/src/settings/template.ts
index ee9a9dd..949327a 100644
--- a/src/settings/template.ts
+++ b/src/settings/template.ts
@@ -11,6 +11,7 @@ import {
siteNameFromUrl,
snakeToCamelCase,
} from '../util'
+import { HighlightManagerId } from '.'
type FunctionMap = {
[key: string]: () => (
@@ -182,10 +183,11 @@ export const renderLabels = (labels?: LabelView[]) => {
}))
}
-export const renderItemContnet = async (
+export const renderItemContent = async (
item: Item,
template: string,
highlightOrder: string,
+ highlightManagerId: HighlightManagerId | undefined,
dateHighlightedFormat: string,
dateSavedFormat: string,
isSingleFile: boolean,
@@ -213,8 +215,19 @@ export const renderItemContnet = async (
})
}
const highlights: HighlightView[] = itemHighlights.map((highlight) => {
+ const highlightColor = highlight.color ?? 'yellow'
+ const highlightRenderOption = highlightManagerId
+ ? {
+ highlightColor: highlightColor,
+ highlightManagerId: highlightManagerId,
+ }
+ : null
return {
- text: formatHighlightQuote(highlight.quote, template),
+ text: formatHighlightQuote(
+ highlight.quote,
+ template,
+ highlightRenderOption,
+ ),
highlightUrl: `https://omnivore.app/me/${item.slug}#${highlight.id}`,
highlightID: highlight.id.slice(0, 8),
dateHighlighted: highlight.updatedAt
@@ -222,7 +235,7 @@ export const renderItemContnet = async (
: undefined,
note: highlight.annotation ?? undefined,
labels: renderLabels(highlight.labels || undefined),
- color: highlight.color ?? 'yellow',
+ color: highlightColor,
positionPercent: highlight.highlightPositionPercent || 0,
positionAnchorIndex: highlight.highlightPositionAnchorIndex
? highlight.highlightPositionAnchorIndex + 1
diff --git a/src/settingsTab.ts b/src/settingsTab.ts
new file mode 100644
index 0000000..9ec1787
--- /dev/null
+++ b/src/settingsTab.ts
@@ -0,0 +1,613 @@
+import {
+ App,
+ ColorComponent,
+ Notice,
+ PluginSettingTab,
+ Setting,
+} from 'obsidian'
+import OmnivorePlugin from './main'
+import { FolderSuggest } from './settings/file-suggest'
+import {
+ DEFAULT_SETTINGS,
+ FRONT_MATTER_VARIABLES,
+ Filter,
+ HighlightManagerId,
+ HighlightOrder,
+} from './settings'
+import { getQueryFromFilter, setOrUpdateHighlightColors } from './util'
+import { HighlightColors } from './api'
+
+export class OmnivoreSettingTab extends PluginSettingTab {
+ plugin: OmnivorePlugin
+
+ constructor(app: App, plugin: OmnivorePlugin) {
+ super(app, plugin)
+ this.plugin = plugin
+ }
+
+ display(): void {
+ const { containerEl } = this
+
+ containerEl.empty()
+
+ /**
+ * General Options
+ **/
+ new Setting(containerEl)
+ .setName('API Key')
+ .setDesc(
+ createFragment((fragment) => {
+ fragment.append(
+ 'You can create an API key at ',
+ fragment.createEl('a', {
+ text: 'https://omnivore.app/settings/api',
+ href: 'https://omnivore.app/settings/api',
+ }),
+ )
+ }),
+ )
+ .addText((text) =>
+ text
+ .setPlaceholder('Enter your Omnivore Api Key')
+ .setValue(this.plugin.settings.apiKey)
+ .onChange(async (value) => {
+ this.plugin.settings.apiKey = value
+ await this.plugin.saveSettings()
+ }),
+ )
+
+ /**
+ * Query Options
+ **/
+ containerEl.createEl('h3', { text: 'Query' })
+
+ new Setting(containerEl)
+ .setName('Filter')
+ .setDesc(
+ "Select an Omnivore search filter type. Changing this would update the 'Custom Query' accordingly and reset the 'Last sync' timestamp",
+ )
+ .addDropdown((dropdown) => {
+ dropdown.addOptions(Filter)
+ dropdown
+ .setValue(this.plugin.settings.filter)
+ .onChange(async (value) => {
+ this.plugin.settings.filter = value
+ this.plugin.settings.customQuery = getQueryFromFilter(value)
+ this.plugin.settings.syncAt = ''
+ await this.plugin.saveSettings()
+ this.display()
+ })
+ })
+
+ new Setting(containerEl)
+ .setName('Custom Query')
+ .setDesc(
+ createFragment((fragment) => {
+ fragment.append(
+ 'See ',
+ fragment.createEl('a', {
+ text: 'https://docs.omnivore.app/using/search',
+ href: 'https://docs.omnivore.app/using/search',
+ }),
+ " for more info on search query syntax. Changing this would reset the 'Last Sync' timestamp",
+ )
+ }),
+ )
+ .addText((text) =>
+ text
+ .setPlaceholder(
+ 'Enter an Omnivore custom search query if advanced filter is selected',
+ )
+ .setValue(this.plugin.settings.customQuery)
+ .onChange(async (value) => {
+ this.plugin.settings.customQuery = value
+ this.plugin.settings.syncAt = ''
+ await this.plugin.saveSettings()
+ }),
+ )
+
+ /**
+ * Sync Options, such as folder location, file format, etc.
+ **/
+ containerEl.createEl('h3', { text: 'Sync' })
+
+ new Setting(containerEl)
+ .setName('Sync on startup')
+ .setDesc(
+ 'Check this box if you want to sync with Omnivore when the app is loaded',
+ )
+ .addToggle((toggle) =>
+ toggle
+ .setValue(this.plugin.settings.syncOnStart)
+ .onChange(async (value) => {
+ this.plugin.settings.syncOnStart = value
+ await this.plugin.saveSettings()
+ }),
+ )
+ new Setting(containerEl)
+ .setName('Frequency')
+ .setDesc(
+ 'Enter the frequency in minutes to sync with Omnivore automatically. 0 means manual sync',
+ )
+ .addText((text) =>
+ text
+ .setPlaceholder('Enter the frequency')
+ .setValue(this.plugin.settings.frequency.toString())
+ .onChange(async (value) => {
+ // validate frequency
+ const frequency = parseInt(value)
+ if (isNaN(frequency)) {
+ new Notice('Frequency must be a positive integer')
+ return
+ }
+ // save frequency
+ this.plugin.settings.frequency = frequency
+ await this.plugin.saveSettings()
+
+ this.plugin.scheduleSync()
+ }),
+ )
+
+ new Setting(containerEl)
+ .setName('Last Sync')
+ .setDesc(
+ "Last time the plugin synced with Omnivore. The 'Sync' command fetches articles updated after this timestamp",
+ )
+ .addMomentFormat((momentFormat) =>
+ momentFormat
+ .setPlaceholder('Last Sync')
+ .setValue(this.plugin.settings.syncAt)
+ .setDefaultFormat("yyyy-MM-dd'T'HH:mm:ss")
+ .onChange(async (value) => {
+ this.plugin.settings.syncAt = value
+ await this.plugin.saveSettings()
+ }),
+ )
+
+ new Setting(containerEl)
+ .setName('Is Single File')
+ .setDesc(
+ 'Check this box if you want to save all articles in a single file',
+ )
+ .addToggle((toggle) =>
+ toggle
+ .setValue(this.plugin.settings.isSingleFile)
+ .onChange(async (value) => {
+ this.plugin.settings.isSingleFile = value
+ await this.plugin.saveSettings()
+ }),
+ )
+
+ new Setting(containerEl)
+ .setName('Folder')
+ .setDesc(
+ 'Enter the folder where the data will be stored. {{{title}}}, {{{dateSaved}}} and {{{datePublished}}} could be used in the folder name',
+ )
+ .addSearch((search) => {
+ new FolderSuggest(this.app, search.inputEl)
+ search
+ .setPlaceholder('Enter the folder')
+ .setValue(this.plugin.settings.folder)
+ .onChange(async (value) => {
+ this.plugin.settings.folder = value
+ await this.plugin.saveSettings()
+ })
+ })
+ new Setting(containerEl)
+ .setName('Folder Date Format')
+ .setDesc(
+ createFragment((fragment) => {
+ fragment.append(
+ 'If date is used as part of folder name, specify the format date for use. Format ',
+ fragment.createEl('a', {
+ text: 'reference',
+ href: 'https://moment.github.io/luxon/#/formatting?id=table-of-tokens',
+ }),
+ )
+ }),
+ )
+ .addText((text) =>
+ text
+ .setPlaceholder('yyyy-MM-dd')
+ .setValue(this.plugin.settings.folderDateFormat)
+ .onChange(async (value) => {
+ this.plugin.settings.folderDateFormat = value
+ await this.plugin.saveSettings()
+ }),
+ )
+
+ new Setting(containerEl)
+ .setName('Attachment Folder')
+ .setDesc(
+ 'Enter the folder where the attachment will be downloaded to. {{{title}}}, {{{dateSaved}}} and {{{datePublished}}} could be used in the folder name',
+ )
+ .addSearch((search) => {
+ new FolderSuggest(this.app, search.inputEl)
+ search
+ .setPlaceholder('Enter the attachment folder')
+ .setValue(this.plugin.settings.attachmentFolder)
+ .onChange(async (value) => {
+ this.plugin.settings.attachmentFolder = value
+ await this.plugin.saveSettings()
+ })
+ })
+
+ new Setting(containerEl)
+ .setName('Filename')
+ .setDesc(
+ 'Enter the filename where the data will be stored. {{id}}, {{{title}}}, {{{dateSaved}}} and {{{datePublished}}} could be used in the filename',
+ )
+ .addText((text) =>
+ text
+ .setPlaceholder('Enter the filename')
+ .setValue(this.plugin.settings.filename)
+ .onChange(async (value) => {
+ this.plugin.settings.filename = value
+ await this.plugin.saveSettings()
+ }),
+ )
+
+ new Setting(containerEl)
+ .setName('Filename Date Format')
+ .setDesc(
+ createFragment((fragment) => {
+ fragment.append(
+ 'If date is used as part of file name, specify the format date for use. Format ',
+ fragment.createEl('a', {
+ text: 'reference',
+ href: 'https://moment.github.io/luxon/#/formatting?id=table-of-tokens',
+ }),
+ )
+ }),
+ )
+ .addText((text) =>
+ text
+ .setPlaceholder('yyyy-MM-dd')
+ .setValue(this.plugin.settings.filenameDateFormat)
+ .onChange(async (value) => {
+ this.plugin.settings.filenameDateFormat = value
+ await this.plugin.saveSettings()
+ }),
+ )
+
+ /**
+ * Article Render Options
+ **/
+ containerEl.createEl('h3', { text: 'Article' })
+
+ new Setting(containerEl)
+ .setName('Front Matter')
+ .setDesc(
+ createFragment((fragment) => {
+ fragment.append(
+ 'Enter the metadata to be used in your note separated by commas. You can also use custom aliases in the format of metatdata::alias, e.g. date_saved::date. ',
+ fragment.createEl('br'),
+ fragment.createEl('br'),
+ 'Available metadata can be found at ',
+ fragment.createEl('a', {
+ text: 'Reference',
+ href: 'https://docs.omnivore.app/integrations/obsidian.html#front-matter',
+ }),
+ fragment.createEl('br'),
+ fragment.createEl('br'),
+ 'If you want to use a custom front matter template, you can enter it below under the advanced settings',
+ )
+ }),
+ )
+ .addTextArea((text) => {
+ text
+ .setPlaceholder('Enter the metadata')
+ .setValue(this.plugin.settings.frontMatterVariables.join(','))
+ .onChange(async (value) => {
+ // validate front matter variables and deduplicate
+ this.plugin.settings.frontMatterVariables = value
+ .split(',')
+ .map((v) => v.trim())
+ .filter(
+ (v, i, a) =>
+ FRONT_MATTER_VARIABLES.includes(v.split('::')[0]) &&
+ a.indexOf(v) === i,
+ )
+ await this.plugin.saveSettings()
+ })
+ text.inputEl.setAttr('rows', 4)
+ text.inputEl.setAttr('cols', 30)
+ })
+
+ new Setting(containerEl)
+ .setName('Article Template')
+ .setDesc(
+ createFragment((fragment) => {
+ fragment.append(
+ 'Enter template to render articles with ',
+ fragment.createEl('a', {
+ text: 'Reference',
+ href: 'https://docs.omnivore.app/integrations/obsidian.html#controlling-the-layout-of-the-data-imported-to-obsidian',
+ }),
+ fragment.createEl('br'),
+ fragment.createEl('br'),
+ 'If you want to use a custom front matter template, you can enter it below under the advanced settings',
+ )
+ }),
+ )
+ .addTextArea((text) => {
+ text
+ .setPlaceholder('Enter the template')
+ .setValue(this.plugin.settings.template)
+ .onChange(async (value) => {
+ // if template is empty, use default template
+ this.plugin.settings.template = value
+ ? value
+ : DEFAULT_SETTINGS.template
+ await this.plugin.saveSettings()
+ })
+ text.inputEl.setAttr('rows', 25)
+ text.inputEl.setAttr('cols', 50)
+ })
+ .addExtraButton((button) => {
+ // add a button to reset template
+ button
+ .setIcon('reset')
+ .setTooltip('Reset template')
+ .onClick(async () => {
+ this.plugin.settings.template = DEFAULT_SETTINGS.template
+ await this.plugin.saveSettings()
+ this.display()
+ new Notice('Template reset')
+ })
+ })
+
+ new Setting(containerEl)
+ .setName('Date Saved Format')
+ .setDesc(
+ 'Enter the date format for dateSaved variable in rendered template',
+ )
+ .addText((text) =>
+ text
+ .setPlaceholder("yyyy-MM-dd'T'HH:mm:ss")
+ .setValue(this.plugin.settings.dateSavedFormat)
+ .onChange(async (value) => {
+ this.plugin.settings.dateSavedFormat = value
+ await this.plugin.saveSettings()
+ }),
+ )
+
+ new Setting(containerEl)
+ .setName('Date Highlighted Format')
+ .setDesc(
+ 'Enter the date format for dateHighlighted variable in rendered template',
+ )
+ .addText((text) =>
+ text
+ .setPlaceholder('Date Highlighted Format')
+ .setValue(this.plugin.settings.dateHighlightedFormat)
+ .onChange(async (value) => {
+ this.plugin.settings.dateHighlightedFormat = value
+ await this.plugin.saveSettings()
+ }),
+ )
+
+ /**
+ * Highlight Render Options in Article
+ **/
+ containerEl.createEl('h4', { text: 'Highlights' })
+
+ new Setting(containerEl)
+ .setName('Highlight Order')
+ .setDesc('Select the order in which highlights are applied')
+ .addDropdown((dropdown) => {
+ dropdown.addOptions(HighlightOrder)
+ dropdown
+ .setValue(this.plugin.settings.highlightOrder)
+ .onChange(async (value) => {
+ this.plugin.settings.highlightOrder = value
+ await this.plugin.saveSettings()
+ })
+ })
+
+ new Setting(containerEl)
+ .setName('Render Highlight Color')
+ .setDesc(
+ 'Check this box if you want to render highlights with color used in the Omnivore App',
+ )
+ .addToggle((toggle) =>
+ toggle
+ .setValue(this.plugin.settings.enableHighlightColorRender)
+ .onChange(async (value) => {
+ this.plugin.settings.enableHighlightColorRender = value
+ await this.plugin.saveSettings()
+ this.displayBlock(renderHighlightConfigContainer, value)
+ }),
+ )
+
+ const renderHighlightConfigContainer = containerEl.createEl('div')
+ this.displayBlock(
+ renderHighlightConfigContainer,
+ this.plugin.settings.enableHighlightColorRender,
+ )
+ new Setting(renderHighlightConfigContainer)
+ .setName('Use Highlightr for Highlight styling')
+ .setDesc(
+ createFragment((fragment) => {
+ fragment.append(
+ fragment.createEl('a', {
+ text: 'Highlightr',
+ href: 'https://github.com/chetachiezikeuzor/Highlightr-Plugin',
+ }),
+ ' is a community plugin for managing highlight style and hotkeys',
+ fragment.createEl('br'),
+ "Check this if you'd like to delegate configuration of highlight color and styling to it",
+ fragment.createEl('br'),
+ 'Ensure to select "css-class" as the highlight-method in the highlightr plugin',
+ )
+ }),
+ )
+ .addToggle((toggle) =>
+ toggle
+ .setValue(
+ this.plugin.settings.highlightManagerId ==
+ HighlightManagerId.HIGHLIGHTR,
+ )
+ .onChange(async (value) => {
+ this.plugin.settings.highlightManagerId = value
+ ? HighlightManagerId.HIGHLIGHTR
+ : HighlightManagerId.OMNIVORE
+ await this.plugin.saveSettings()
+ this.displayBlock(omnivoreHighlightConfigContainer, !value)
+ }),
+ )
+
+ const omnivoreHighlightConfigContainer =
+ renderHighlightConfigContainer.createEl('div', {
+ cls: 'omnivore-highlight-config-container',
+ })
+ this.displayBlock(
+ omnivoreHighlightConfigContainer,
+ this.plugin.settings.highlightManagerId == HighlightManagerId.OMNIVORE,
+ )
+ const highlighterSetting = new Setting(omnivoreHighlightConfigContainer)
+ const colorPickers: { [color in string]: ColorComponent } = {}
+
+ highlighterSetting
+ .setName('Configure highlight colors')
+ .setDesc(
+ 'Configure how the highlight colors in Omnivore should render in notes',
+ )
+ .addButton((button) => {
+ button.setButtonText('Save')
+ button.setTooltip('Save highlight color setting')
+ button.setClass('omnivore-btn')
+ button.setClass('omnivore-btn-primary')
+ button.onClick(async (e) => {
+ const highlightColorMapping =
+ this.plugin.settings.highlightColorMapping
+ Object.entries(colorPickers).forEach(([color, picker]) => {
+ highlightColorMapping[color as HighlightColors] = picker.getValue()
+ })
+ setOrUpdateHighlightColors(highlightColorMapping)
+ await this.plugin.saveSettings()
+ new Notice('Saved highlight color settings')
+ })
+ })
+
+ const getPenIcon = (hexCode: string) =>
+ ``
+
+ const colorMap = this.plugin.settings.highlightColorMapping
+ Object.entries(colorMap).forEach(([colorName, hexCode]) => {
+ let penIcon = getPenIcon(hexCode)
+ const settingItem = omnivoreHighlightConfigContainer.createEl('div')
+ settingItem.addClass('omnivore-highlight-setting-item')
+ const colorIcon = settingItem.createEl('span')
+ colorIcon.addClass('omnivore-highlight-setting-icon')
+ colorIcon.innerHTML = penIcon
+
+ const colorSetting = new Setting(settingItem)
+ .setName(colorName)
+ .setDesc(hexCode)
+
+ colorSetting.addColorPicker((colorPicker) => {
+ colorPicker.setValue(hexCode)
+ colorPickers[colorName] = colorPicker
+ colorPicker.onChange((v) => {
+ penIcon = getPenIcon(v)
+ colorIcon.innerHTML = penIcon
+ colorSetting.setDesc(v)
+ })
+ })
+ })
+
+ /**
+ * Advanced Settings
+ **/
+ containerEl.createEl('h3', {
+ cls: 'omnivore-collapsible',
+ text: 'Advanced Settings',
+ })
+
+ const advancedSettings = containerEl.createEl('div', {
+ cls: 'omnivore-content',
+ })
+
+ new Setting(advancedSettings)
+ .setName('API Endpoint')
+ .setDesc("Enter the Omnivore server's API endpoint")
+ .addText((text) =>
+ text
+ .setPlaceholder('API endpoint')
+ .setValue(this.plugin.settings.endpoint)
+ .onChange(async (value) => {
+ this.plugin.settings.endpoint = value
+ await this.plugin.saveSettings()
+ }),
+ )
+
+ new Setting(advancedSettings)
+ .setName('Front Matter Template')
+ .setDesc(
+ createFragment((fragment) => {
+ fragment.append(
+ 'Enter YAML template to render the front matter with ',
+ fragment.createEl('a', {
+ text: 'Reference',
+ href: 'https://docs.omnivore.app/integrations/obsidian.html#front-matter-template',
+ }),
+ fragment.createEl('br'),
+ fragment.createEl('br'),
+ 'We recommend you to use Front Matter section under the basic settings to define the metadata.',
+ fragment.createEl('br'),
+ fragment.createEl('br'),
+ 'If this template is set, it will override the Front Matter so please make sure your template is a valid YAML.',
+ )
+ }),
+ )
+ .addTextArea((text) => {
+ text
+ .setPlaceholder('Enter the template')
+ .setValue(this.plugin.settings.frontMatterTemplate)
+ .onChange(async (value) => {
+ this.plugin.settings.frontMatterTemplate = value
+ await this.plugin.saveSettings()
+ })
+
+ text.inputEl.setAttr('rows', 10)
+ text.inputEl.setAttr('cols', 30)
+ })
+ .addExtraButton((button) => {
+ // add a button to reset template
+ button
+ .setIcon('reset')
+ .setTooltip('Reset front matter template')
+ .onClick(async () => {
+ this.plugin.settings.frontMatterTemplate =
+ DEFAULT_SETTINGS.frontMatterTemplate
+ await this.plugin.saveSettings()
+ this.display()
+ new Notice('Front matter template reset')
+ })
+ })
+
+ const help = containerEl.createEl('p')
+ help.innerHTML = `For more information, please visit our GitHub page, email us at feedback@omnivore.app or join our Discord server.`
+
+ // script to make collapsible sections
+ const coll = document.getElementsByClassName('omnivore-collapsible')
+ let i
+
+ for (i = 0; i < coll.length; i++) {
+ coll[i].addEventListener('click', function () {
+ this.classList.toggle('omnivore-active')
+ const content = this.nextElementSibling
+ if (content.style.maxHeight) {
+ content.style.maxHeight = null
+ } else {
+ content.style.maxHeight = 'fit-content'
+ }
+ })
+ }
+ }
+
+ displayBlock(block: HTMLElement, display: boolean) {
+ block.style.display = display ? 'block' : 'none'
+ }
+}
diff --git a/src/util.ts b/src/util.ts
index 1cd2d58..adad48b 100644
--- a/src/util.ts
+++ b/src/util.ts
@@ -4,6 +4,7 @@ import { DateTime } from 'luxon'
import escape from 'markdown-escape'
import { parseYaml } from 'obsidian'
import outOfCharacter from 'out-of-character'
+import { HighlightColorMapping, HighlightManagerId } from './settings'
export const DATE_FORMAT_W_OUT_SECONDS = "yyyy-MM-dd'T'HH:mm"
export const DATE_FORMAT = `${DATE_FORMAT_W_OUT_SECONDS}:ss`
@@ -18,6 +19,11 @@ export interface HighlightPoint {
top: number
}
+export interface HighlightRenderOption {
+ highlightManagerId: HighlightManagerId
+ highlightColor: string
+}
+
export const getHighlightLocation = (patch: string | null): number => {
if (!patch) {
return 0
@@ -131,9 +137,32 @@ export const siteNameFromUrl = (originalArticleUrl: string): string => {
}
}
+const wrapHighlightMarkup = (
+ quote: string,
+ highlightRenderOption: HighlightRenderOption,
+): string => {
+ const { highlightManagerId, highlightColor } = highlightRenderOption
+
+ const markupRender = (content: string) => {
+ if (content.trim().length === 0) {
+ return ''
+ }
+ if (highlightManagerId == HighlightManagerId.HIGHLIGHTR) {
+ return `${content}`
+ } else {
+ return `${content}`
+ }
+ }
+
+ return quote.replaceAll(/(>)?(.+)$/gm, (_, g1, g2) => {
+ return (g1 ?? '') + markupRender(g2)
+ })
+}
+
export const formatHighlightQuote = (
quote: string | null,
template: string,
+ highlightRenderOption: HighlightRenderOption | null,
): string => {
if (!quote) {
return ''
@@ -144,6 +173,9 @@ export const formatHighlightQuote = (
// replace all empty lines with blockquote '>' to preserve paragraphs
quote = quote.replaceAll('>', '>').replaceAll(/\n/gm, '\n> ')
}
+ if (highlightRenderOption != null) {
+ quote = wrapHighlightMarkup(quote, highlightRenderOption)
+ }
return quote
}
@@ -178,3 +210,13 @@ export const snakeToCamelCase = (str: string) =>
const removeInvisibleChars = (str: string): string => {
return outOfCharacter.replace(str)
}
+
+export const setOrUpdateHighlightColors = (
+ colorSetting: HighlightColorMapping,
+) => {
+ const root = document.documentElement
+
+ Object.entries(colorSetting).forEach(([k, v]) => {
+ root.style.setProperty(`--omni-${k}`, v)
+ })
+}
diff --git a/styles.css b/styles.css
index 7625532..07f3857 100644
--- a/styles.css
+++ b/styles.css
@@ -12,10 +12,66 @@
}
.omnivore-collapsible:after {
- content: "\02795"; /* Unicode character for "plus" sign (+) */
+ content: '\02795'; /* Unicode character for "plus" sign (+) */
float: right;
}
.omnivore-active:after {
- content: "\2796"; /* Unicode character for "minus" sign (-) */
+ content: '\2796'; /* Unicode character for "minus" sign (-) */
+}
+
+.omnivore-highlight-config-container {
+ border-bottom: 1px solid var(--background-modifier-border);
+}
+
+.modal.mod-settings
+ button:not(.mod-cta):not(.mod-warning).omnivore-btn.omnivore-btn-primary {
+ color: var(--text-accent);
+}
+
+.modal.mod-settings
+ button:not(.mod-cta):not(.mod-warning).omnivore-btn.omnivore-btn-primary:hover {
+ color: var(--text-accent-hover);
+ background-color: var(--background-secondary);
+}
+
+/*----------------------------------------------------------------
+Omnivore Highlight Color Config Setting
+----------------------------------------------------------------*/
+
+.omnivore-highlight-setting-item {
+ display: grid;
+ grid-gap: 8px;
+ grid-template-columns: 0.5fr 7fr;
+ align-items: center;
+ border-top: 1px solid var(--background-modifier-border);
+}
+
+.omnivore-highlight-setting-icon {
+ display: flex;
+ height: 24px;
+ width: 24px;
+}
+
+mark.omni {
+ background-color: var(--text-highlight-rgb);
+ font-weight: 500;
+ margin: 0 -0.05em;
+ padding: 0.125em 0.15em;
+ border-radius: 0.25em;
+ -webkit-box-decoration-break: clone;
+ box-decoration-break: clone;
+}
+
+mark.omni-yellow {
+ --text-highlight-rgb: var(--omni-yellow);
+}
+mark.omni-red {
+ --text-highlight-rgb: var(--omni-red);
+}
+mark.omni-green {
+ --text-highlight-rgb: var(--omni-green);
+}
+mark.omni-blue {
+ --text-highlight-rgb: var(--omni-blue);
}
diff --git a/tsconfig.json b/tsconfig.json
index 179f2f1..f335682 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -12,7 +12,7 @@
"isolatedModules": true,
"strictNullChecks": true,
"esModuleInterop": true,
- "lib": ["ES2021", "DOM"]
+ "lib": ["ES2021","ES2021.String", "DOM"]
},
"include": ["src/**/*.ts"]
}