Skip to content

πŸ“„ Textarea with syntax highlighting powered by solidjs and shiki.

License

Notifications You must be signed in to change notification settings

bigmistqke/solid-shiki-textarea

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

solid-shiki-textarea

πŸ“„ solid-shiki-textarea

pnpm

Textarea with syntax highlighting powered by solid-js and shiki.

screen-recording.mp4

Installation

npm i shiki solid-shiki-textarea
# or
yarn add shiki solid-shiki-textarea
# or
pnpm add shiki solid-shiki-textarea

Solid Component

The main export of solid-shiki-textarea is a solid component.

Prop Types
import type { LanguageRegistration, ThemeRegistration } from 'shiki'
import type { Language, Theme } from 'shiki-textarea/tm'

type LanguageProps = Language | LanguageRegistration[] | Promise<LanguageRegistration[]>

type ThemeProps = Theme | ThemeRegistration | Promise<ThemeRegistration>

interface ShikiTextareaProps extends Omit<ComponentProps<'div'>, 'style'> {
  language: LanguageProps
  theme: ThemeProps
  code: string
  editable?: boolean
  style?: JSX.CSSProperties
  onInput?: (event: InputEvent & { currentTarget: HTMLTextAreaElement }) => void
}

Usage

Static import of theme/language

import { ShikiTextarea } from 'solid-shiki-textarea'
import minLight from 'shiki/themes/min-light.mjs'
import tsx from 'shiki/langs/tsx.mjs'

export default () => (
  <ShikiTextarea
    language={tsx}
    theme={minLight}
    code="const sum = (a: string, b: string) => a + b"
    editable={true}
    style={{
      padding: '10px',
      'font-size': '16pt',
    }}
    onInput={e => console.log(e.currentTarget.value)}
  />
)

Dynamic import of theme/language

import { ShikiTextarea } from 'solid-shiki-textarea'

export default () => (
  <ShikiTextarea
    language={import('https://esm.sh/shiki/langs/tsx.mjs')}
    theme={import('https://esm.sh/shiki/themes/min-light.mjs')}
    code="const sum = (a: string, b: string) => a + b"
    editable={true}
    style={{
      padding: '10px',
      'font-size': '16pt',
    }}
    onInput={e => console.log(e.currentTarget.value)}
  />
)

Custom Element

We also export a custom-element wrapper <shiki-textarea/> powered by @lume/element

Attribute Types
import { LanguageProps, ThemeProps } from 'shiki-textarea'

interface ShikiTextareaAttributes extends ComponentProps<'div'> {
  language?: LanguageProps
  theme?: ThemeProps
  code?: string
  editable?: boolean
  stylesheet?: string | CSSStyleSheet
  onInput?: (event: InputEvent & { currentTarget: ShikiTextareaElement }) => void
}

Usage

import { setCDN } from 'solid-shiki-textarea'
import 'solid-shiki-textarea/custom-element'

setCDN('/shiki')

export default () => (
  <shiki-textarea
    language="tsx"
    theme="andromeeda"
    code="const sum = (a: string, b: string) => a + b"
    editable={true}
    style={{
      padding: '10px',
      'font-size': '16pt',
    }}
    stylesheet="code, code * { font-style:normal; }"
    onInput={e => console.log(e.currentTarget.value)}
  />
)

Styling The Custom Element

Some DOM ::part() are exported.

  • root can be used to override the background, set a padding or change font-size and line-height.
  • textarea can be used to change the selection color.
  • code can be used to change the code tag.
shiki-textarea::part(root) {
  padding: 20px;
  background: transparent;
  font-size: 18px;
  line-height: 1.25;
}

shiki-textarea::part(textarea)::selection {
  background: deepskyblue;
}

/* to size it to the container, will remove dead-zones */
shiki-textarea {
  min-height: 100%;
  min-width: 100%;
}

The attribute stylesheet could be used as a last resort to customize the theme. In the following example we avoid italics in the rendered coded. The stylesheet is created, cached and reused on the different shiki-textarea instances.

<shiki-textarea
  language="tsx"
  theme="andromeeda"
  code="const sum = (a: string, b: string) => a + b"
  editable={true}
  style={{
    '--padding': '10px',
    'font-size': '16pt',
  }}
  stylesheet="code, code * { font-style:normal; }"
  onInput={e => console.log(e.target.value)}
/>

CDN

// from solid component
import { setCDN } from 'solid-shiki-textarea'

// Set base-url of CDN directly (defaults to https://esm.sh)
setCDN('https://unpkg.com')

// relative to the root
setCDN('/assets/shiki')

// Or use the callback-form
setCDN((type, id) => `./shiki/${type}/${id}.json`)

Themes & Languages

Both, the languages and themes list are exported as string[].

import type { Theme, Language } from 'solid-shiki-textarea/tm'

import { themes, languages } from 'solid-shiki-textarea/tm'

About

πŸ“„ Textarea with syntax highlighting powered by solidjs and shiki.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published