1- import { Plugin , TFile } from 'obsidian' ;
2- import { type BundledLanguage , bundledLanguages , getHighlighter , type Highlighter , type TokensResult } from 'shiki' ;
1+ import { loadPrism , Plugin , TFile } from 'obsidian' ;
2+ import { bundledLanguages , getHighlighter , type Highlighter , type TokensResult } from 'shiki' ;
33import { ExpressiveCodeEngine , ExpressiveCodeTheme } from '@expressive-code/core' ;
44import { pluginShiki } from '@expressive-code/plugin-shiki' ;
55import { pluginTextMarkers } from '@expressive-code/plugin-text-markers' ;
66import { pluginCollapsibleSections } from '@expressive-code/plugin-collapsible-sections' ;
77import { pluginLineNumbers } from '@expressive-code/plugin-line-numbers' ;
88import { pluginFrames } from '@expressive-code/plugin-frames' ;
9- import { ThemeMapper } from 'src/ThemeMapper' ;
10- import { EC_THEME } from 'src/ECTheme' ;
9+ import { ThemeMapper } from 'src/themes/ ThemeMapper' ;
10+ import { EC_THEME } from 'src/themes/ ECTheme' ;
1111import { CodeBlock } from 'src/CodeBlock' ;
12- import { OBSIDIAN_THEME } from 'src/ObsidianTheme' ;
13- import { createCm6Plugin } from 'src/Cm6_ViewPlugin' ;
12+ import { OBSIDIAN_THEME } from 'src/themes/ObsidianTheme' ;
13+ import { createCm6Plugin } from 'src/codemirror/Cm6_ViewPlugin' ;
14+ import { DEFAULT_SETTINGS , type Settings } from 'src/settings/Settings' ;
15+ import { ShikiSettingsTab } from 'src/settings/SettingsTab' ;
16+ import { filterHighlightAllPlugin } from 'src/PrismPlugin' ;
17+ import { LoadedLanguage } from 'src/LoadedLanguage' ;
1418
1519// some languages break obsidian's `registerMarkdownCodeBlockProcessor`, so we blacklist them
16- const languageNameBlacklist = new Set ( [ 'c++' , 'c#' , 'f#' ] ) ;
20+ const languageNameBlacklist = new Set ( [ 'c++' , 'c#' , 'f#' , 'mermaid' ] ) ;
1721
1822export default class ShikiPlugin extends Plugin {
1923 // @ts -expect-error TS2564
@@ -25,23 +29,25 @@ export default class ShikiPlugin extends Plugin {
2529 // @ts -expect-error TS2564
2630 activeCodeBlocks : Map < string , CodeBlock [ ] > ;
2731 // @ts -expect-error TS2564
28- loadedLanguages : Map < string , string > ;
32+ loadedLanguages : Map < string , LoadedLanguage > ;
2933 // @ts -expect-error TS2564
3034 shiki : Highlighter ;
35+ // @ts -expect-error TS2564
36+ settings : Settings ;
3137
3238 async onload ( ) : Promise < void > {
39+ await this . loadSettings ( ) ;
40+
41+ this . addSettingTab ( new ShikiSettingsTab ( this ) ) ;
42+
3343 this . themeMapper = new ThemeMapper ( ) ;
3444 this . activeCodeBlocks = new Map ( ) ;
3545 this . loadedLanguages = new Map ( ) ;
3646
3747 await this . loadLanguages ( ) ;
3848
39- this . shiki = await getHighlighter ( {
40- themes : [ OBSIDIAN_THEME ] ,
41- langs : Object . keys ( bundledLanguages ) ,
42- } ) ;
43-
4449 await this . loadEC ( ) ;
50+ await this . loadShiki ( ) ;
4551
4652 this . registerCodeBlockProcessors ( ) ;
4753
@@ -69,17 +75,45 @@ export default class ShikiPlugin extends Plugin {
6975 for ( const [ shikiLanguage , registration ] of Object . entries ( bundledLanguages ) ) {
7076 // the last element of the array is seemingly the most recent version of the language
7177 const language = ( await registration ( ) ) . default . at ( - 1 ) ;
78+ const shikiLanguageName = shikiLanguage as keyof typeof bundledLanguages ;
7279
7380 if ( language === undefined ) {
7481 continue ;
7582 }
7683
7784 for ( const alias of [ language . name , ...( language . aliases ?? [ ] ) ] ) {
78- if ( ! this . loadedLanguages . has ( alias ) && ! languageNameBlacklist . has ( alias ) ) {
79- this . loadedLanguages . set ( alias , shikiLanguage ) ;
85+ if ( languageNameBlacklist . has ( alias ) ) {
86+ continue ;
87+ }
88+
89+ if ( ! this . loadedLanguages . has ( alias ) ) {
90+ const newLanguage = new LoadedLanguage ( alias ) ;
91+ newLanguage . addLanguage ( shikiLanguageName ) ;
92+
93+ this . loadedLanguages . set ( alias , newLanguage ) ;
94+ }
95+
96+ this . loadedLanguages . get ( alias ) ! . addLanguage ( shikiLanguageName ) ;
97+ }
98+ }
99+
100+ for ( const [ alias , language ] of this . loadedLanguages ) {
101+ if ( language . languages . length === 1 ) {
102+ language . setDefaultLanguage ( language . languages [ 0 ] ) ;
103+ } else {
104+ const defaultLanguage = language . languages . find ( lang => lang === alias ) ;
105+ if ( defaultLanguage !== undefined ) {
106+ language . setDefaultLanguage ( defaultLanguage ) ;
107+ } else {
108+ console . warn ( `No default language found for ${ alias } , using the first language in the list` ) ;
109+ language . setDefaultLanguage ( language . languages [ 0 ] ) ;
80110 }
81111 }
82112 }
113+
114+ for ( const disabledLanguage of this . settings . disabledLanguages ) {
115+ this . loadedLanguages . delete ( disabledLanguage ) ;
116+ }
83117 }
84118
85119 async loadEC ( ) : Promise < void > {
@@ -113,17 +147,38 @@ export default class ShikiPlugin extends Plugin {
113147 }
114148 }
115149
150+ async loadShiki ( ) : Promise < void > {
151+ this . shiki = await getHighlighter ( {
152+ themes : [ OBSIDIAN_THEME ] ,
153+ langs : Object . keys ( bundledLanguages ) ,
154+ } ) ;
155+ }
156+
157+ async registerPrismPlugin ( ) : Promise < void > {
158+ /* eslint-disable */
159+
160+ await loadPrism ( ) ;
161+
162+ const prism = await loadPrism ( ) ;
163+ filterHighlightAllPlugin ( prism ) ;
164+ prism . plugins . filterHighlightAll . reject . addSelector ( 'div.expressive-code pre code' ) ;
165+ }
166+
116167 registerCodeBlockProcessors ( ) : void {
117168 for ( const [ alias , language ] of this . loadedLanguages ) {
118- this . registerMarkdownCodeBlockProcessor (
119- alias ,
120- async ( source , el , ctx ) => {
121- const codeBlock = new CodeBlock ( this , el , source , language , alias , ctx ) ;
122-
123- ctx . addChild ( codeBlock ) ;
124- } ,
125- - 1 ,
126- ) ;
169+ try {
170+ this . registerMarkdownCodeBlockProcessor (
171+ alias ,
172+ async ( source , el , ctx ) => {
173+ const codeBlock = new CodeBlock ( this , el , source , language . getDefaultLanguage ( ) , alias , ctx ) ;
174+
175+ ctx . addChild ( codeBlock ) ;
176+ } ,
177+ - 1 ,
178+ ) ;
179+ } catch ( e ) {
180+ console . warn ( `Failed to register code block processor for ${ alias } ` , e ) ;
181+ }
127182 }
128183 }
129184
@@ -167,8 +222,16 @@ export default class ShikiPlugin extends Plugin {
167222 }
168223
169224 return this . shiki . codeToTokens ( code , {
170- lang : shikiLanguage as BundledLanguage ,
225+ lang : shikiLanguage . getDefaultLanguage ( ) ,
171226 theme : 'obsidian-theme' ,
172227 } ) ;
173228 }
229+
230+ async loadSettings ( ) : Promise < void > {
231+ this . settings = Object . assign ( { } , DEFAULT_SETTINGS , await this . loadData ( ) ) as Settings ;
232+ }
233+
234+ async saveSettings ( ) : Promise < void > {
235+ await this . saveData ( this . settings ) ;
236+ }
174237}
0 commit comments