Merge pull request #10 from GRA0007/fix/optimisations

Address Obsidian review feedback
This commit is contained in:
Benji Grant 2024-08-21 10:53:49 +10:00 committed by GitHub
commit a101e0e20e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 59 additions and 10 deletions

5
.changes/css-variable.md Normal file
View file

@ -0,0 +1,5 @@
---
"obsidian-css-inlay-colors": minor:feat
---
Use a css variable for the inlay background color instead of setting it directly via an inline style

5
.changes/node-type.md Normal file
View file

@ -0,0 +1,5 @@
---
"obsidian-css-inlay-colors": patch:fix
---
Swap to a more robust method of determining the node type in live preview mode

View file

@ -0,0 +1,5 @@
---
"obsidian-css-inlay-colors": patch:fix
---
Use a cross-window capable version of `instanceof`, which fixes the color picker not working in pop-out windows

5
.changes/state-field.md Normal file
View file

@ -0,0 +1,5 @@
---
"obsidian-css-inlay-colors": patch:fix
---
Use the provided Obsidian state field to determine if the editor is in live preview mode

View file

@ -6,12 +6,24 @@
Show inline color hints for CSS colors in Obsidian.
To use, just put any valid CSS color syntax in a code block like so: \`#8A5CF5\`.
To use, just put any valid CSS color syntax in a code block like so: \`\#8A5CF5\`.
<img src="example.jpg" alt="Example of the extension running for all CSS color formats" width="200">
### Color Picker
Enable the color picker setting to change a color using a color picker in live preview mode. Note that the color picker does not support opacity, and will only let you select from sRGB colors. It will attempt to preserve the existing format you have written, as well as any existing opacity.
### Custom CSS
Customize the inlays by targeting the `.css-color-inlay` class. For example, you can make them circular with the following snippet:
```css
.css-color-inlay {
border-radius: 100px;
}
```
## Development
This project uses Biome and Yarn for linting/formatting and package management. Run `yarn dev` to build on changes.

View file

@ -1,7 +1,7 @@
{
"name": "obsidian-css-inlay-colors",
"version": "1.0.0",
"packageManager": "yarn@4.3.1",
"packageManager": "yarn@4.4.0",
"description": "Show inline color hints for CSS colors",
"main": "main.js",
"scripts": {

View file

@ -1,4 +1,4 @@
import { syntaxTree } from '@codemirror/language'
import { syntaxTree, tokenClassNodeProp } from '@codemirror/language'
import type { Range } from '@codemirror/state'
import {
Decoration,
@ -8,7 +8,9 @@ import {
type ViewUpdate,
WidgetType,
} from '@codemirror/view'
import type { NodeProp } from '@lezer/common'
import { type Color, formatHex, parse } from 'culori'
import { editorLivePreviewField } from 'obsidian'
import { formatColor } from './formatColor'
export const inlayExtension = (colorPickerEnabled: boolean) => {
@ -53,20 +55,28 @@ class CSSColorInlayWidget extends WidgetType {
toDOM() {
const inlay = document.createElement('label')
inlay.className = 'css-color-inlay'
inlay.style.background = this.text
inlay.style.setProperty('--css-color-inlay-color', this.text)
if (this.colorPickerEnabled) {
const input = document.createElement('input')
input.type = 'color'
input.value = formatHex(this.color)
input.addEventListener('change', (e) => {
if (!(e.currentTarget instanceof HTMLInputElement)) return
if (
!e.currentTarget ||
!(e.currentTarget as Node).instanceOf(HTMLInputElement)
)
return
const pos = this.view.posAtDOM(wrapper)
this.view.dispatch({
changes: {
from: pos,
to: pos + this.text.length,
insert: formatColor(this.text, this.color, e.currentTarget.value),
insert: formatColor(
this.text,
this.color,
(e.currentTarget as HTMLInputElement).value,
),
},
})
})
@ -83,8 +93,7 @@ class CSSColorInlayWidget extends WidgetType {
const createColorWidgets = (view: EditorView, colorPickerEnabled: boolean) => {
// Only create widgets in live preview mode
if (!view.dom.parentElement?.classList.contains('is-live-preview'))
return Decoration.none
if (!view.state.field(editorLivePreviewField)) return Decoration.none
const widgets: Range<Decoration>[] = []
@ -93,7 +102,9 @@ const createColorWidgets = (view: EditorView, colorPickerEnabled: boolean) => {
from,
to,
enter: (node) => {
if (node.name.includes('inline-code')) {
if (
node.type.prop(tokenClassNodeProp)?.split(' ').includes('inline-code')
) {
const text = view.state.sliceDoc(node.from, node.to)
// Not a valid color
@ -123,3 +134,8 @@ const createColorWidgets = (view: EditorView, colorPickerEnabled: boolean) => {
return Decoration.set(widgets)
}
// Codemirror does not correctly export a type for this constant, but it does exist
declare module '@codemirror/language' {
const tokenClassNodeProp: NodeProp<string>
}

View file

@ -14,7 +14,7 @@ export const inlayPostProcessor = (el: HTMLElement) => {
code.createSpan({
prepend: true,
cls: 'css-color-inlay',
attr: { style: `background: ${color};` },
attr: { style: `--css-color-inlay-color: ${color};` },
})
}
}

View file

@ -7,6 +7,7 @@
vertical-align: middle;
margin-right: .3em;
margin-top: -.1em;
background: var(--css-color-inlay-color);
input {
height: 0;