import { stores } from '../stores' ; import axios from 'axios' ; import yaml from 'js-yaml' ; import OptionalUtils from '../util/OptionalUtils' ; import { validateToc } from '../validation/tocValidators' ; import log from '../util/LoggerFactory' ; import path from 'path-browserify' ; import Optional from 'optional-js' ; import hljs from 'highlight.js' ; import marked from 'marked' ; const { docsStore } = stores ; const docCache = new Map ( ) ; const renderer = new marked . Renderer ( ) ; renderer . image = function ( src , title , alt ) { const curPath = window . location . pathname . replace ( /(.*\/).*/ , '$1' ) ; const subbedPath = curPath . replace ( 'docs' , 'static/docs' ) ; const resolvedSrc = path . resolve ( subbedPath , src ) ; const finalSrc = window . location . origin + resolvedSrc ; log . debug ( `src: ${ src }, curPath: ${ curPath }, subbedPath: ${ subbedPath }, resolvedSrc: ${ resolvedSrc } \nResolved image to load: ${ finalSrc }` ) ; console . log ( title ) ; let res = '<img src="' + finalSrc + '" alt="' + alt ; Optional . ofNullable ( /height=&#39;(.*?)&#39;/ . exec ( title ) ) . ifPresent ( matches => { log . debug ( `Calculated height: ${ matches [ 1 ] }` ) ; res += '" height="' + matches [ 1 ] ; } ) ; Optional . ofNullable ( /width=&#39;(.*?)&#39;/ . exec ( title ) ) . ifPresent ( matches => { log . debug ( `Calculated width: ${ matches [ 1 ] }` ) ; res += '" width="' + matches [ 1 ] ; } ) ; Optional . ofNullable ( /class=&#39;(.*?)&#39;/ . exec ( title ) ) . ifPresent ( matches => { log . debug ( `Calculated class: ${ matches [ 1 ] }` ) ; res += '" class="' + matches [ 1 ] ; } ) ; return res + '">' ; } ; marked . setOptions ( { renderer : renderer , highlight : function ( code ) { return hljs . highlightAuto ( code ) . value ; } } ) ; export default class DocsService { async fetchAndUpdateToc ( ) { if ( docsStore . tableOfContents == null ) { try { const data = await this . fetchToc ( ) ; const tocData = yaml . load ( data ) ; const validationResults = validateToc ( tocData ) ; if ( ! validationResults . isValid ) { throw new Error ( `docs/table-of-contents.yaml was not valid errors: ${ JSON . stringify ( validationResults . errors ) }` ) ; } docsStore . updateToc ( tocData ) ; } catch ( e ) { log . error ( 'Failed to load table of contents for docs, dont worry, docs are probably not enabled' ) ; } } } async fetchToc ( ) { try { const response = await axios . get ( `${ process . env . PUBLIC_URL }/docs/table-of-contents.yaml` ) ; return response . data ; } catch ( e ) { throw e ; } } fetchAndUpdateDocContent ( path ) { const resolvedPath = OptionalUtils . trimToEmpty ( path ) . orElse ( OptionalUtils . safeGet ( ( ) => docsStore . tableOfContents ! . home ) . orElse ( 'index' ) ) ; const markdown = resolvedPath . endsWith ( '.md' ) ? resolvedPath : `${ resolvedPath }.md` ; if ( docCache . has ( markdown ) ) { log . debug ( `${ markdown } - in mem cache hit, using that` ) ; docsStore . updateContent ( docCache . get ( markdown ) as string ) ; } else { this . fetchDocContent ( markdown ) . then ( data => { const renderedContent = marked . parse ( Optional . ofNullable ( data ) . orElse ( ' ' ) ) ; docCache . set ( markdown , renderedContent ) ; docsStore . updateContent ( renderedContent ) ; } ) ; } } async fetchDocContent ( markdown ) { try { const response = await axios . get ( `${ process . env . PUBLIC_URL }/docs/${ markdown }` ) ; return response . data ; } catch ( e ) { throw e ; } } }