diff options
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/components/code.svelte | 22 | ||||
-rw-r--r-- | src/lib/components/fit.svelte | 13 | ||||
-rw-r--r-- | src/lib/components/index.ts | 25 | ||||
-rw-r--r-- | src/lib/components/markdown.svelte | 13 | ||||
-rw-r--r-- | src/lib/components/media.svelte | 22 | ||||
-rw-r--r-- | src/lib/components/notes.svelte | 3 | ||||
-rw-r--r-- | src/lib/components/presentation.svelte | 77 | ||||
-rw-r--r-- | src/lib/components/slide.svelte | 48 | ||||
-rw-r--r-- | src/lib/components/stack.svelte | 3 | ||||
-rw-r--r-- | src/lib/components/step.svelte | 53 | ||||
-rw-r--r-- | src/lib/components/stretch.svelte | 13 | ||||
-rw-r--r-- | src/lib/components/vertical.svelte | 3 | ||||
-rw-r--r-- | src/lib/languages/index.ts | 6 | ||||
-rw-r--r-- | src/lib/languages/svelte.ts | 50 | ||||
-rw-r--r-- | src/lib/languages/types.ts | 3 | ||||
-rw-r--r-- | src/lib/motion/index.ts | 4 | ||||
-rw-r--r-- | src/lib/motion/signal.ts | 61 | ||||
-rw-r--r-- | src/lib/motion/types.ts | 2 | ||||
-rw-r--r-- | src/lib/motion/utils.ts | 10 | ||||
-rw-r--r-- | src/lib/styles/code.css | 56 | ||||
-rw-r--r-- | src/lib/styles/tailwind.css | 3 | ||||
-rw-r--r-- | src/lib/styles/theme.css | 127 | ||||
-rw-r--r-- | src/lib/types/highlight.js/index.d.ts | 323 |
23 files changed, 940 insertions, 0 deletions
diff --git a/src/lib/components/code.svelte b/src/lib/components/code.svelte new file mode 100644 index 0000000..255bf7e --- /dev/null +++ b/src/lib/components/code.svelte @@ -0,0 +1,22 @@ +<script lang="ts"> + type Lines = string | boolean | null + type Offset = string | null + type Language = string | null + + export let id = 'code-animation' + export let lines: Lines = true + export let offset: Offset = null + export let lang: Language = null + + delete $$restProps.class +</script> + +<pre data-id={id} class={$$props.class || ''} {...$$restProps}> + <code + data-trim + data-line-numbers={lines || null} + data-ln-start-from={offset} + class="language-{lang}"> +<slot /> + </code> +</pre> diff --git a/src/lib/components/fit.svelte b/src/lib/components/fit.svelte new file mode 100644 index 0000000..8772061 --- /dev/null +++ b/src/lib/components/fit.svelte @@ -0,0 +1,13 @@ +<script lang="ts"> + export let type = 'h2' + + delete $$restProps.class +</script> + +<svelte:element + this={type} + class="r-fit-text {$$props.class || ''}" + {...$$restProps} +> + <slot /> +</svelte:element> diff --git a/src/lib/components/index.ts b/src/lib/components/index.ts new file mode 100644 index 0000000..392800d --- /dev/null +++ b/src/lib/components/index.ts @@ -0,0 +1,25 @@ +import Code from './code.svelte' +import FitText from './fit.svelte' +import Markdown from './markdown.svelte' +import Media from './media.svelte' +import Notes from './notes.svelte' +import Presentation from './presentation.svelte' +import Slide from './slide.svelte' +import Stack from './stack.svelte' +import Step from './step.svelte' +import Stretch from './stretch.svelte' +import Vertical from './vertical.svelte' + +export { + Code, + FitText, + Markdown, + Media, + Notes, + Presentation, + Slide, + Stack, + Step, + Stretch, + Vertical, +} diff --git a/src/lib/components/markdown.svelte b/src/lib/components/markdown.svelte new file mode 100644 index 0000000..204815b --- /dev/null +++ b/src/lib/components/markdown.svelte @@ -0,0 +1,13 @@ +<script lang="ts"> + export let file: string | null = null +</script> + +{#if file} + <section data-markdown={file} /> +{:else} + <section data-markdown> + <div data-template> + <slot /> + </div> + </section> +{/if} diff --git a/src/lib/components/media.svelte b/src/lib/components/media.svelte new file mode 100644 index 0000000..ffa2633 --- /dev/null +++ b/src/lib/components/media.svelte @@ -0,0 +1,22 @@ +<script lang="ts"> + type Bool = boolean | null + type Element = 'video' | 'img' | 'iframe' + + export let type: Element + export let src: string + export let autoplay: Bool = null + export let preload: Bool = null + + delete $$restProps.class +</script> + +<svelte:element + this={type} + data-src={src} + data-autoplay={autoplay} + data-prelod={preload} + class={$$props.class || ''} + {...$$restProps} +> + <slot /> +</svelte:element> diff --git a/src/lib/components/notes.svelte b/src/lib/components/notes.svelte new file mode 100644 index 0000000..198e18d --- /dev/null +++ b/src/lib/components/notes.svelte @@ -0,0 +1,3 @@ +<aside class="notes"> + <slot /> +</aside> diff --git a/src/lib/components/presentation.svelte b/src/lib/components/presentation.svelte new file mode 100644 index 0000000..c11010a --- /dev/null +++ b/src/lib/components/presentation.svelte @@ -0,0 +1,77 @@ +<script lang="ts"> + import { onMount } from 'svelte' + import Reveal from 'reveal.js' + import options from '@config' + + import 'reveal.js/dist/reveal.css' + import '@styles/theme.css' + import '@styles/code.css' + + onMount(() => { + // create deck instance + const deck = new Reveal(options) + + // custom event listeners + const inEvent = new CustomEvent('in') + const outEvent = new CustomEvent('out') + + // keep track of current slide + deck.on('slidechanged', (event) => { + if ('currentSlide' in event) { + const currentSlideEl = event.currentSlide as HTMLElement + currentSlideEl.dispatchEvent(inEvent) + } + + if ('previousSlide' in event) { + const currentPreviousEl = event.previousSlide as HTMLElement + currentPreviousEl.dispatchEvent(outEvent) + } + }) + + deck.on('fragmentshown', (event) => { + if ('fragment' in event) { + const fragmentEl = event.fragment as HTMLElement + fragmentEl.dispatchEvent(inEvent) + } + }) + + deck.on('fragmenthidden', (event) => { + if ('fragment' in event) { + const fragmentEl = event.fragment as HTMLElement + fragmentEl.dispatchEvent(outEvent) + } + }) + + deck.initialize().then(() => { + // we pass the language to the `<Code>` block + // and higlight code blocks after initialization + highlightCodeBlocks(deck) + }) + + // reload page after update to avoid HMR issues + // reloadPageAfterUpdate() + }) + + function highlightCodeBlocks(deck: Reveal.Api) { + const highlight = deck.getPlugin('highlight') + const codeBlocks = [...document.querySelectorAll('code')] + codeBlocks.forEach((block) => { + // @ts-ignore + highlight.highlightBlock(block) + }) + } + + function reloadPageAfterUpdate() { + if (import.meta.hot) { + import.meta.hot.on('vite:afterUpdate', () => { + location.reload() + }) + } + } +</script> + +<div class="reveal"> + <div class="slides"> + <slot /> + </div> +</div> diff --git a/src/lib/components/slide.svelte b/src/lib/components/slide.svelte new file mode 100644 index 0000000..439d312 --- /dev/null +++ b/src/lib/components/slide.svelte @@ -0,0 +1,48 @@ +<script lang="ts"> + type Bool = boolean | null + type String = string | null + type Transition = + | 'none' + | 'fade' + | 'slide' + | 'convex' + | 'concave' + | 'zoom' + | null + + export let animate: Bool = null + export let animateEasing: String = null + export let animateUnmatched: Bool = null + export let animateId: String = null + export let animateRestart: Bool = null + export let background: String = null + export let gradient: String = null + export let image: String = null + export let video: String = null + export let iframe: String = null + export let interactive: Bool = null + export let transition: Transition = null + + delete $$restProps.class +</script> + +<section + on:in + on:out + data-auto-animate={animate} + data-auto-animate-easing={animateEasing} + data-auto-animate-unmatched={animateUnmatched} + data-auto-animate-id={animateId} + data-auto-animate-restart={animateRestart} + data-background-color={background} + data-background-gradient={gradient} + data-background-image={image} + data-background-video={video} + data-background-iframe={iframe} + data-background-interactive={interactive} + data-transition={transition} + class={$$props.class || ''} + {...$$restProps} +> + <slot /> +</section> diff --git a/src/lib/components/stack.svelte b/src/lib/components/stack.svelte new file mode 100644 index 0000000..a03d205 --- /dev/null +++ b/src/lib/components/stack.svelte @@ -0,0 +1,3 @@ +<div class="r-stack"> + <slot /> +</div> diff --git a/src/lib/components/step.svelte b/src/lib/components/step.svelte new file mode 100644 index 0000000..13c2f7c --- /dev/null +++ b/src/lib/components/step.svelte @@ -0,0 +1,53 @@ +<script lang="ts"> + export let order: string | null = null + export let fadeIn = false + export let fadeOut = false + export let fadeUp = false + export let fadeDown = false + export let fadeLeft = false + export let fadeRight = false + export let fadeInThenOut = false + export let currentVisible = false + export let fadeInThenSemiOut = false + export let semiFadeOut = false + export let highlightRed = false + export let highlightGreen = false + export let highlightBlue = false + export let highlightCurrentRed = false + export let highlightCurrentGreen = false + export let highlightCurrentBlue = false + export let grow = false + export let shrink = false + export let strike = false + + delete $$restProps.class +</script> + +<p + on:in + on:out + class:fade-in={fadeIn} + class:fade-out={fadeOut} + class:fade-up={fadeUp} + class:fade-down={fadeDown} + class:fade-left={fadeLeft} + class:fade-right={fadeRight} + class:fade-in-then-out={fadeInThenOut} + class:current-visible={currentVisible} + class:fade-in-then-semi-out={fadeInThenSemiOut} + class:semi-fade-out={semiFadeOut} + class:highlight-red={highlightRed} + class:highlight-green={highlightGreen} + class:highlight-blue={highlightBlue} + class:highlight-current-red={highlightCurrentRed} + class:highlight-current-green={highlightCurrentGreen} + class:highlight-current-blue={highlightCurrentBlue} + class:grow + class:shrink + class:strike + class="fragment {$$props.class || ''}" + data-fragment-index={order} + {...$$restProps} +> + <slot /> +</p> diff --git a/src/lib/components/stretch.svelte b/src/lib/components/stretch.svelte new file mode 100644 index 0000000..be808d5 --- /dev/null +++ b/src/lib/components/stretch.svelte @@ -0,0 +1,13 @@ +<script lang="ts"> + export let type = 'p' + + delete $$restProps.class +</script> + +<svelte:element + this={type} + class="r-stretch {$$props.class || ''}" + {...$$restProps} +> + <slot /> +</svelte:element> diff --git a/src/lib/components/vertical.svelte b/src/lib/components/vertical.svelte new file mode 100644 index 0000000..fb20c0a --- /dev/null +++ b/src/lib/components/vertical.svelte @@ -0,0 +1,3 @@ +<section> + <slot /> +</section> diff --git a/src/lib/languages/index.ts b/src/lib/languages/index.ts new file mode 100644 index 0000000..296c1fa --- /dev/null +++ b/src/lib/languages/index.ts @@ -0,0 +1,6 @@ +import { svelte } from './svelte' +import type { Hljs } from './types' + +export function registerLanguages(hljs: Hljs) { + hljs.registerLanguage('svelte', svelte) +} diff --git a/src/lib/languages/svelte.ts b/src/lib/languages/svelte.ts new file mode 100644 index 0000000..237c7c7 --- /dev/null +++ b/src/lib/languages/svelte.ts @@ -0,0 +1,50 @@ +import type { Hljs } from './types' + +export function svelte(hljs: Hljs) { + return { + subLanguage: 'xml', + contains: [ + hljs.COMMENT('<!--', '-->', { + relevance: 10, + }), + { + begin: /^(\s*)(<script(\s*context="module")?>)/gm, + end: /^(\s*)(<\/script>)/gm, + subLanguage: 'javascript', + excludeBegin: true, + excludeEnd: true, + contains: [ + { + begin: /^(\s*)(\$:)/gm, + end: /(\s*)/gm, + className: 'keyword', + }, + ], + }, + { + begin: /^(\s*)(<style.*>)/gm, + end: /^(\s*)(<\/style>)/gm, + subLanguage: 'css', + excludeBegin: true, + excludeEnd: true, + }, + { + begin: /\{/gm, + end: /\}/gm, + subLanguage: 'javascript', + contains: [ + { + begin: /[\{]/, + end: /[\}]/, + skip: true, + }, + { + begin: /([#:\/@])(if|else|each|await|then|catch|debug|html)/gm, + className: 'keyword', + relevance: 10, + }, + ], + }, + ], + } +} diff --git a/src/lib/languages/types.ts b/src/lib/languages/types.ts new file mode 100644 index 0000000..a030e24 --- /dev/null +++ b/src/lib/languages/types.ts @@ -0,0 +1,3 @@ +import hljs from 'highlight.js' + +export type Hljs = typeof hljs diff --git a/src/lib/motion/index.ts b/src/lib/motion/index.ts new file mode 100644 index 0000000..79e3d36 --- /dev/null +++ b/src/lib/motion/index.ts @@ -0,0 +1,4 @@ +import { signal } from './signal' +import { animate, all } from './utils' + +export { signal, animate, all } diff --git a/src/lib/motion/signal.ts b/src/lib/motion/signal.ts new file mode 100644 index 0000000..99697ce --- /dev/null +++ b/src/lib/motion/signal.ts @@ -0,0 +1,61 @@ +import { tweened, type TweenedOptions } from 'svelte/motion' +import { cubicInOut } from 'svelte/easing' +import { interpolate } from 'd3-interpolate' +import type { AnimationFn, Resolve } from './types' + +export function signal<TweenValues>( + values: TweenValues, + options: TweenedOptions<TweenValues> = {} +) { + const { subscribe, update, set } = tweened<TweenValues>(values, { + duration: 1000, + easing: cubicInOut, + interpolate, + ...options, + }) + + let tasks: AnimationFn[] = [] + + function to( + this: any, + values: Partial<TweenValues>, + toOptions: TweenedOptions<TweenValues> = {} + ) { + if (typeof values === 'object') { + tasks.push(() => update((prev) => ({ ...prev, ...values }), toOptions)) + } else { + tasks.push(() => set(values, toOptions)) + } + return this + } + + function reset() { + set(values, { duration: 0 }) + tasks = [] + } + + function sfx(this: any, sound: string, { volume = 0.5 } = {}) { + const audio = new Audio(sound) + audio.volume = volume + + tasks.push(async () => { + audio + .play() + .catch(() => + console.error('To play sounds interact with the page first.') + ) + }) + + return this + } + + async function then(resolve: Resolve) { + for (const task of tasks) { + await task() + } + resolve() + tasks = [] + } + + return { subscribe, to, reset, sfx, then } +} diff --git a/src/lib/motion/types.ts b/src/lib/motion/types.ts new file mode 100644 index 0000000..e97a109 --- /dev/null +++ b/src/lib/motion/types.ts @@ -0,0 +1,2 @@ +export type AnimationFn = () => Promise<void> +export type Resolve = (value?: any) => Promise<void> diff --git a/src/lib/motion/utils.ts b/src/lib/motion/utils.ts new file mode 100644 index 0000000..a81c02e --- /dev/null +++ b/src/lib/motion/utils.ts @@ -0,0 +1,10 @@ +import { onMount } from 'svelte' +import type { AnimationFn } from './types' + +export function animate(fn: AnimationFn) { + onMount(fn) +} + +export function all(...animations: AnimationFn[]) { + return Promise.all(animations) +} diff --git a/src/lib/styles/code.css b/src/lib/styles/code.css new file mode 100644 index 0000000..36adfe4 --- /dev/null +++ b/src/lib/styles/code.css @@ -0,0 +1,56 @@ +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + color: #e4f0fb; + background-color: var(--r-background-color); +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-selector-class, +.hljs-literal, +.hljs-strong, +.hljs-name, +.hljs-string { + color: #5de4c7; +} + +.hljs-code { + color: #66d9ef; +} + +.hljs-class .hljs-title { + color: #add7ff; +} + +.hljs-symbol, +.hljs-regexp, +.hljs-link { + color: #e4f0fb; +} + +.hljs-bullet, +.hljs-subst, +.hljs-title, +.hljs-section, +.hljs-emphasis, +.hljs-type, +.hljs-built_in, +.hljs-builtin-name, +.hljs-selector-attr, +.hljs-selector-pseudo, +.hljs-addition, +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-attr { + color: #add7ff; +} + +.hljs-comment, +.hljs-quote, +.hljs-deletion, +.hljs-meta { + color: #a6accd; +} diff --git a/src/lib/styles/tailwind.css b/src/lib/styles/tailwind.css new file mode 100644 index 0000000..b5c61c9 --- /dev/null +++ b/src/lib/styles/tailwind.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/src/lib/styles/theme.css b/src/lib/styles/theme.css new file mode 100644 index 0000000..5215feb --- /dev/null +++ b/src/lib/styles/theme.css @@ -0,0 +1,127 @@ +@import '@fontsource-variable/manrope'; +@import '@fontsource-variable/jetbrains-mono'; + +:root { + --r-background-color: hsl(226 19% 13%); + --r-main-font: 'Manrope Variable'; + --r-main-font-size: 42px; + --r-main-color: hsl(226 19% 98%); + --r-heading-font: 'Manrope'; + --r-code-font: 'JetBrains Mono Variable'; + --r-link-color: hsl(180 100% 50%); +} + +/* required for Reveal.js to work */ +#app { + display: contents; +} + +.reveal-viewport { + background-color: var(--r-background-color); +} + +.reveal { + color: var(--r-main-color); + font-family: var(--r-main-font); + font-size: var(--r-main-font-size); + font-weight: normal; +} + +.reveal pre { + display: block; + position: relative; + margin-inline: auto; + font-family: var(--r-code-font); + font-size: 0.55em; + line-height: 1.6em; + text-align: left; + word-wrap: break-word; +} + +.reveal code { + font-family: var(--r-code-font); + text-transform: none; + tab-size: 2; +} + +.reveal code::-webkit-scrollbar { + display: none; + scrollbar-width: none; +} + +.reveal pre code { + max-height: 600px; + display: block; + padding: 5px; + overflow: auto; + word-wrap: normal; +} + +.reveal .code-wrapper { + white-space: normal; +} + +.reveal .code-wrapper code { + white-space: pre; +} + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; +} + +.reveal table th { + font-weight: bold; +} + +.reveal table th, +.reveal table td { + padding: 0.2em 0.5em 0.2em 0.5em; + text-align: left; + border-bottom: 1px solid; +} + +.reveal table th[align='center'], +.reveal table td[align='center'] { + text-align: center; +} + +.reveal table th[align='right'], +.reveal table td[align='right'] { + text-align: right; +} + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; +} + +.reveal sup { + vertical-align: super; + font-size: smaller; +} + +.reveal sub { + vertical-align: sub; + font-size: smaller; +} + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; +} + +.reveal small * { + vertical-align: top; +} + +.reveal .controls { + color: var(--r-link-color); +} + +.reveal .progress { + color: var(--r-link-color); +} diff --git a/src/lib/types/highlight.js/index.d.ts b/src/lib/types/highlight.js/index.d.ts new file mode 100644 index 0000000..98dfac2 --- /dev/null +++ b/src/lib/types/highlight.js/index.d.ts @@ -0,0 +1,323 @@ +/* + Yoinked from https://github.com/highlightjs/highlight.js/blob/main/types/index.d.ts +*/ + +/* eslint-disable no-unused-vars */ +/* eslint-disable no-use-before-define */ +// For TS consumers who use Node and don't have dom in their tsconfig lib, import the necessary types here. +/// <reference lib="dom" /> + +declare module 'highlight.js/private' { + import { CompiledMode, Mode, Language } from 'highlight.js' + + type MatchType = 'begin' | 'end' | 'illegal' + type EnhancedMatch = RegExpMatchArray & { + rule: CompiledMode + type: MatchType + } + type AnnotatedError = Error & { + mode?: Mode | Language + languageName?: string + badRule?: Mode + } + + type KeywordData = [string, number] + type KeywordDict = Record<string, KeywordData> +} +declare module 'highlight.js' { + import { KeywordDict } from 'highlight.js/private' + + export type HLJSApi = PublicApi & ModesAPI + + export interface VuePlugin { + install: (vue: any) => void + } + + // perhaps make this an interface? + type RegexEitherOptions = { + capture?: boolean + } + + interface PublicApi { + highlight: ( + codeOrLanguageName: string, + optionsOrCode: string | HighlightOptions, + ignoreIllegals?: boolean + ) => HighlightResult + highlightAuto: ( + code: string, + languageSubset?: string[] + ) => AutoHighlightResult + highlightBlock: (element: HTMLElement) => void + highlightElement: (element: HTMLElement) => void + configure: (options: Partial<HLJSOptions>) => void + initHighlighting: () => void + initHighlightingOnLoad: () => void + highlightAll: () => void + registerLanguage: (languageName: string, language: LanguageFn) => void + unregisterLanguage: (languageName: string) => void + listLanguages: () => string[] + registerAliases: ( + aliasList: string | string[], + { languageName }: { languageName: string } + ) => void + getLanguage: (languageName: string) => Language | undefined + autoDetection: (languageName: string) => boolean + inherit: <T>(original: T, ...args: Record<string, any>[]) => T + addPlugin: (plugin: HLJSPlugin) => void + removePlugin: (plugin: HLJSPlugin) => void + debugMode: () => void + safeMode: () => void + versionString: string + vuePlugin: () => VuePlugin + regex: { + concat: (...args: (RegExp | string)[]) => string + lookahead: (re: RegExp | string) => string + either: ( + ...args: + | (RegExp | string)[] + | [...(RegExp | string)[], RegexEitherOptions] + ) => string + optional: (re: RegExp | string) => string + anyNumberOfTimes: (re: RegExp | string) => string + } + newInstance: () => HLJSApi + } + + interface ModesAPI { + SHEBANG: (mode?: Partial<Mode> & { binary?: string | RegExp }) => Mode + BACKSLASH_ESCAPE: Mode + QUOTE_STRING_MODE: Mode + APOS_STRING_MODE: Mode + PHRASAL_WORDS_MODE: Mode + COMMENT: ( + begin: string | RegExp, + end: string | RegExp, + modeOpts?: Mode | {} + ) => Mode + C_LINE_COMMENT_MODE: Mode + C_BLOCK_COMMENT_MODE: Mode + HASH_COMMENT_MODE: Mode + NUMBER_MODE: Mode + C_NUMBER_MODE: Mode + BINARY_NUMBER_MODE: Mode + REGEXP_MODE: Mode + TITLE_MODE: Mode + UNDERSCORE_TITLE_MODE: Mode + METHOD_GUARD: Mode + END_SAME_AS_BEGIN: (mode: Mode) => Mode + // built in regex + IDENT_RE: string + UNDERSCORE_IDENT_RE: string + MATCH_NOTHING_RE: string + NUMBER_RE: string + C_NUMBER_RE: string + BINARY_NUMBER_RE: string + RE_STARTERS_RE: string + } + + export type LanguageFn = (hljs: HLJSApi) => Language + export type CompilerExt = (mode: Mode, parent: Mode | Language | null) => void + + export interface HighlightResult { + code?: string + relevance: number + value: string + language?: string + illegal: boolean + errorRaised?: Error + // * for auto-highlight + secondBest?: Omit<HighlightResult, 'second_best'> + // private + _illegalBy?: illegalData + _emitter: Emitter + _top?: Language | CompiledMode + } + export interface AutoHighlightResult extends HighlightResult {} + + export interface illegalData { + message: string + context: string + index: number + resultSoFar: string + mode: CompiledMode + } + + export type BeforeHighlightContext = { + code: string + language: string + result?: HighlightResult + } + export type PluginEvent = keyof HLJSPlugin + export type HLJSPlugin = { + 'after:highlight'?: (result: HighlightResult) => void + 'before:highlight'?: (context: BeforeHighlightContext) => void + 'after:highlightElement'?: (data: { + el: Element + result: HighlightResult + text: string + }) => void + 'before:highlightElement'?: (data: { + el: Element + language: string + }) => void + // TODO: Old API, remove with v12 + 'after:highlightBlock'?: (data: { + block: Element + result: HighlightResult + text: string + }) => void + 'before:highlightBlock'?: (data: { + block: Element + language: string + }) => void + } + + interface EmitterConstructor { + new (opts: any): Emitter + } + + export interface HighlightOptions { + language: string + ignoreIllegals?: boolean + } + + export interface HLJSOptions { + noHighlightRe: RegExp + languageDetectRe: RegExp + classPrefix: string + cssSelector: string + languages?: string[] + __emitter: EmitterConstructor + ignoreUnescapedHTML?: boolean + throwUnescapedHTML?: boolean + } + + export interface CallbackResponse { + data: Record<string, any> + ignoreMatch: () => void + isMatchIgnored: boolean + } + + export type ModeCallback = ( + match: RegExpMatchArray, + response: CallbackResponse + ) => void + export type Language = LanguageDetail & Partial<Mode> + export interface Mode extends ModeCallbacks, ModeDetails {} + + export interface LanguageDetail { + name?: string + unicodeRegex?: boolean + rawDefinition?: () => Language + aliases?: string[] + disableAutodetect?: boolean + contains: Mode[] + case_insensitive?: boolean + keywords?: string | string[] | Record<string, string | string[]> + isCompiled?: boolean + exports?: any + classNameAliases?: Record<string, string> + compilerExtensions?: CompilerExt[] + supersetOf?: string + } + + // technically private, but exported for convenience as this has + // been a pretty stable API and is quite useful + export interface Emitter { + startScope(name: string): void + endScope(): void + addText(text: string): void + toHTML(): string + finalize(): void + __addSublanguage(emitter: Emitter, subLanguageName: string): void + } + + export type HighlightedHTMLElement = HTMLElement & { + result?: object + secondBest?: object + parentNode: HTMLElement + } + + /* modes */ + + interface ModeCallbacks { + 'on:end'?: Function + 'on:begin'?: ModeCallback + } + + export interface CompiledLanguage extends LanguageDetail, CompiledMode { + isCompiled: true + contains: CompiledMode[] + keywords: Record<string, any> + } + + export type CompiledScope = Record<number, string> & { + _emit?: Record<number, boolean> + _multi?: boolean + _wrap?: string + } + + export type CompiledMode = Omit<Mode, 'contains'> & { + begin?: RegExp | string + end?: RegExp | string + scope?: string + contains: CompiledMode[] + keywords: KeywordDict + data: Record<string, any> + terminatorEnd: string + keywordPatternRe: RegExp + beginRe: RegExp + endRe: RegExp + illegalRe: RegExp + matcher: any + isCompiled: true + starts?: CompiledMode + parent?: CompiledMode + beginScope?: CompiledScope + endScope?: CompiledScope + } + + interface ModeDetails { + begin?: RegExp | string | (RegExp | string)[] + match?: RegExp | string | (RegExp | string)[] + end?: RegExp | string | (RegExp | string)[] + // deprecated in favor of `scope` + className?: string + scope?: string | Record<number, string> + beginScope?: string | Record<number, string> + endScope?: string | Record<number, string> + contains?: ('self' | Mode)[] + endsParent?: boolean + endsWithParent?: boolean + endSameAsBegin?: boolean + skip?: boolean + excludeBegin?: boolean + excludeEnd?: boolean + returnBegin?: boolean + returnEnd?: boolean + __beforeBegin?: Function + parent?: Mode + starts?: Mode + lexemes?: string | RegExp + keywords?: string | string[] | Record<string, string | string[]> + beginKeywords?: string + relevance?: number + illegal?: string | RegExp | Array<string | RegExp> + variants?: Mode[] + cachedVariants?: Mode[] + // parsed + subLanguage?: string | string[] + isCompiled?: boolean + label?: string + } + + const hljs: HLJSApi + export default hljs +} + +declare module 'highlight.js/lib/languages/*' { + import { LanguageFn } from 'highlight.js' + const defineLanguage: LanguageFn + export default defineLanguage +} |