import xml from 'xml-string' ; import Tag from 'xml-string/dist/Tag' ; import { readFile } from 'fs' ; import { promisify } from 'util' ; import { resolve } from 'path' ; import { Slide } from '../types' ; import createSlide from './createSlide' ; const getFile = ( file ) => promisify ( readFile ) ( resolve ( __dirname , '..' , '..' , 'assets' , file ) , 'utf-8' ) ; const getTitle = ( slides ) => slides && slides [ 0 ] && slides [ 0 ] [ 0 ] && slides [ 0 ] [ 0 ] . value ? slides [ 0 ] [ 0 ] . value . replace ( /\W/g , '' ) : 'Presentation' ; const isString = ( d ) : d is string => typeof d === 'string' || d instanceof String ; const getAllCodeLangs = ( slides ) => slides . map ( el => el . filter ( d => d . type === 'code' && d . lang ) . map ( d => d . lang ) ) . reduce ( ( r , list ) => { const toAdd = Array . from ( new Set ( list . filter ( d => ! r . includes ( d ) ) ) ) ; return [ ... r , ... toAdd ] ; } , [ ] ) . filter ( isString ) ; const createHead = ( html , title , cssFiles ) => { const head = html . child ( 'head' ) ; head . child ( 'meta' ) . attr ( { charset : 'utf-8' } ) ; head . child ( 'title' ) . data ( title ) ; cssFiles . forEach ( css => head . child ( 'style' ) . data ( css ) ) ; } ; const createBody = ( html , slides , jsFiles ) => { const body = html . child ( 'body' ) ; const presentation = body . child ( 'div' ) . attr ( { 'class' : 'presentation' } ) ; slides . map ( createSlide ( presentation ) ) ; jsFiles . forEach ( js => body . child ( 'script' ) . data ( js ) ) ; } ; const needsPrism = ( langs ) => langs . length > 0 ; const allowedThemes = [ 'dark' , 'light' , 'paper' , ] ; const prismByTheme = { 'dark' : 'prism-okaidia.css' , 'light' : 'prism-solarizedlight.css' , 'paper' : 'prism-solarizedlight.css' , } ; const getThemeCss = ( theme ) => allowedThemes . includes ( theme ) ? `${ theme }.css` : 'dark.css' ; const getPrismCss = ( theme , langs ) : string | undefined => { if ( ! needsPrism ( langs ) ) { return undefined ; } return prismByTheme [ allowedThemes . includes ( theme ) ? theme : 'dark' ] ; } ; export default async ( slides , theme ) => { const langs = getAllCodeLangs ( slides ) ; const html = xml . create ( 'html' ) ; const cssFileNames = [ getThemeCss ( theme ) , getPrismCss ( theme , langs ) , ] . filter ( isString ) ; const cssFiles = await Promise . all ( cssFileNames . map ( getFile ) ) ; createHead ( html , getTitle ( slides ) , cssFiles ) ; const jsFileNames = [ 'main.js' , ] ; const jsFiles = await Promise . all ( jsFileNames . map ( getFile ) ) ; createBody ( html , slides , jsFiles ) ; return `<!DOCTYPE html>
${ html . outer ( ) }
  ` ; } ;