@@ -16,60 +16,44 @@ import { Controller } from '@hotwired/stimulus'
1616import mermaid from 'mermaid'
1717
1818export class ReadmeController extends Controller {
19- onThemeChange ( darkMode ) {
20- // If `darkMode` isn't passed, get the current value
21- if ( darkMode == undefined ) {
22- darkMode = window . matchMedia ( '(prefers-color-scheme: dark)' ) . matches
23- console . log ( 'actually dark mode is' , darkMode )
24- }
19+ frameLoaded ( ) {
20+ this . navigateToAnchorFromLocation ( )
21+ this . renderMermaidDiagrams ( )
22+ }
2523
26- // Get all mermaid diagrams
27- const mermaidDivs = document . querySelectorAll ( 'pre[lang="mermaid"]' )
24+ async renderMermaidDiagrams ( ) {
25+ // Replace all Mermaid chart sources with rendered diagrams.
26+ const mermaidSectionElements = document . querySelectorAll ( 'section[data-type="mermaid"]' )
27+ for ( const [ index , mermaidSectionElement ] of Array . from ( mermaidSectionElements ) . entries ( ) ) {
28+ // No need to parse the JSON, the chart source is in a `data-plain` attribute.
29+ const mermaidDataElement = mermaidSectionElement . querySelector ( '[data-plain]' )
30+ if ( ! mermaidDataElement ) continue
31+ const chartDefinition = mermaidDataElement . getAttribute ( 'data-plain' )
32+ if ( ! chartDefinition ) continue
2833
29- for ( const div of Array . from ( mermaidDivs ) ) {
30- // Get the diagram code
31- const json = div . parentElement . parentElement . getAttribute ( 'data-json' )
32- if ( ! json ) {
33- continue
34- }
35- const diagramCode = JSON . parse ( json ) . data
36- if ( diagramCode ) {
37- try {
38- // Clear the existing diagram
39- div . innerHTML = diagramCode
40- div . removeAttribute ( 'data-processed' )
41- } catch ( error ) {
42- console . error ( 'Error re-rendering mermaid diagram:' , error )
43- }
44- }
45- }
34+ // Make a container with *both* light and dark charts.
35+ const chartContainer = document . createElement ( 'div' )
36+ chartContainer . classList . add ( 'mermaid-chart' )
37+ mermaidDataElement . appendChild ( chartContainer )
4638
47- mermaid . initialize ( {
48- theme : darkMode ? 'dark' : undefined ,
49- nodeSpacing : 50 ,
50- rankSpacing : 50 ,
51- curve : 'basis' ,
52- } )
39+ // The documentation says not to call `initialize` more than once, but it is the
40+ // only way to switch themes and it's the only way to get this working.
41+ mermaid . initialize ( { theme : 'default' , nodeSpacing : 50 , rankSpacing : 50 , curve : 'basis' } )
42+ const lightRenderResult = await mermaid . render ( `mermaid-chart-light-${ index } ` , chartDefinition )
43+ chartContainer . insertAdjacentHTML ( 'beforeend' , lightRenderResult . svg )
5344
54- // Rather then preprocess the HTML in Swift we just change the selector to use `lang` attribute instead of `class`
55- mermaid . run ( {
56- querySelector : 'pre[lang="mermaid"]' ,
57- } )
58- }
59- navigateToAnchorFromLocation ( ) {
60- // listen for changes to color scheme
61- if ( typeof window !== 'undefined' ) {
62- const mediaQuery = window . matchMedia ( '(prefers-color-scheme: dark)' )
45+ mermaid . initialize ( { theme : 'dark' , nodeSpacing : 50 , rankSpacing : 50 , curve : 'basis' } )
46+ const darkRenderResult = await mermaid . render ( `mermaid-chart-dark-${ index } ` , chartDefinition )
47+ chartContainer . insertAdjacentHTML ( 'beforeend' , darkRenderResult . svg )
6348
64- // Add listener for system preference changes
65- mediaQuery . addEventListener ( 'change' , ( e ) => {
66- this . onThemeChange ( e . matches )
67- } )
49+ // Clean up the superfluous loading element.
50+ const loadingElement = mermaidSectionElement . querySelector ( '.js-render-enrichment-loader' )
51+ if ( ! loadingElement ) continue
52+ loadingElement . remove ( )
6853 }
54+ }
6955
70- // setup mermaid diagrams
71- this . onThemeChange ( )
72-
56+ navigateToAnchorFromLocation ( ) {
7357 // If the browser has an anchor in the URL that may be inside the README then
7458 // we should attempt to scroll it into view once the README is loaded.
7559 const hash = window . location . hash
0 commit comments