import { Lexer } from "../../text/lexer/Lexer"; import { LexerEvent } from "../../text/lexer/LexerEvent"; import { LexerMatcher } from "../../text/lexer/LexerMatcher"; import { LexerMatcherLibrary } from "../../text/lexer/LexerMatcherLibrary"; import { LexerType, LexerTypes } from "../../text/lexer/LexerType"; import { LexerQuery } from "../../text/lexer/LexerQuery"; import { LiteralLexerEventTypeMatcher } from "../../text/lexer/LexerEventMatcher"; import { StylesProcessor } from "./StylesProcessor"; export type PORTRAIT_MARKER = "PORTRAIT_MARKER"; export type LANDSCAPE_MARKER = "LANDSCAPE_MARKER"; export type ROOT_ELEMENT_REPLACER = "ROOT_ELEMENT_REPLACER"; export type StylesProcessorLexerType = LexerType | ROOT_ELEMENT_REPLACER | PORTRAIT_MARKER | LANDSCAPE_MARKER; export class StylesProcessorLexer extends Lexer { static readonly PORTRAIT_MARKER:PORTRAIT_MARKER = "PORTRAIT_MARKER"; static readonly PORTRAIT_MARKER_MATCHER = new LexerMatcher( StylesProcessorLexer.PORTRAIT_MARKER, /#portrait/i ); static readonly LANDSCAPE_MARKER:LANDSCAPE_MARKER = "LANDSCAPE_MARKER"; static readonly LANDSCAPE_MARKER_MATCHER = new LexerMatcher( StylesProcessorLexer.LANDSCAPE_MARKER, /#landscape/i ); static readonly ROOT_ELEMENT_REPLACER:ROOT_ELEMENT_REPLACER = "ROOT_ELEMENT_REPLACER"; static readonly ROOT_ELEMENT_REPLACER_MATCHER = new LexerMatcher( StylesProcessorLexer.ROOT_ELEMENT_REPLACER, /#_/ ); constructor() { super(); this.addAllMatchers( LexerMatcherLibrary.SINGLE_LINE_COMMENT_MATCHER, LexerMatcherLibrary.MULTI_LINE_COMMENT_MATCHER, LexerMatcherLibrary.DOUBLE_QUOTED_STRING_MATCHER, LexerMatcherLibrary.SINGLE_QUOTED_STRING_MATCHER, LexerMatcherLibrary.WHITESPACE_MATCHER, LexerMatcherLibrary.BLOCKSTART_MATCHER, LexerMatcherLibrary.BLOCKEND_MATCHER, StylesProcessorLexer.PORTRAIT_MARKER_MATCHER, StylesProcessorLexer.LANDSCAPE_MARKER_MATCHER, StylesProcessorLexer.ROOT_ELEMENT_REPLACER_MATCHER, LexerMatcherLibrary.CSS_CLASS_SELECTOR_MATCHER, LexerMatcherLibrary.CSS_ID_SELECTOR_MATCHER, LexerMatcherLibrary.CSS_WORD_MATCHER, LexerMatcherLibrary.ANY_SYMBOL_MATCHER ); } getCompressedTokens( source:string ) { let events = this.lexToList( source ); let types = new Set(); types.add( LexerMatcherLibrary.WHITESPACE_MATCHER.type ); types.add( LexerMatcherLibrary.ANY_SYMBOL_MATCHER.type ); events = this.compress( events, types ); return events; } convert( source:string ) { let tokens = this.getCompressedTokens( source ); this.resolveMatches( source, tokens ); let query = new LexerQuery(); query.source = source; query.tokens = tokens; let rootElement = ""; query.forAllWithType( LexerTypes.CSS_WORD, ( t ) => { if ( rootElement !== "" ) { return; } let isCustomElement = LexerMatcherLibrary.HTML_CUSTOM_ELEMENT_MATCHER.isMatching( t.match ); console.log( "IsCustom:", t.match, isCustomElement ); if ( ! isCustomElement ) { return; } rootElement = t.match; } ); let emptyRootElementMessage = false; query.forAllWithType( StylesProcessorLexer.ROOT_ELEMENT_REPLACER, ( t )=> { if ( rootElement == "" && ! emptyRootElementMessage ) { emptyRootElementMessage = true; console.log( "No root element detected for [] replacements!" ); } t.setMatch( rootElement ); } ); let output:string[] = []; let markerReplacements = { [ StylesProcessorLexer.PORTRAIT_MARKER ]: "@media ( orientation:portrait )", [ StylesProcessorLexer.LANDSCAPE_MARKER ]: "@media ( orientation:landscape )", } let start = new LiteralLexerEventTypeMatcher( LexerTypes.BLOCKSTART ); let end = new LiteralLexerEventTypeMatcher( LexerTypes.BLOCKEND ); for ( let i = 0; i < tokens.length; i++ ) { let token = tokens[ i ]; if ( token.isType( StylesProcessorLexer.PORTRAIT_MARKER ) || token.isType( StylesProcessorLexer.LANDSCAPE_MARKER ) ) { let blockIndices = query.searchBlockIndices( i, start, end ); if ( blockIndices == null ) { output.push( token.match ); } else { let markerType = token.type as ( PORTRAIT_MARKER | LANDSCAPE_MARKER ); let replacement = markerReplacements[ markerType ]; output.push( replacement ); output.push( "{" ); query.forAllMatches( i + 1 , blockIndices.endIndex, ( match ) => { output.push( match ); } ); output.push( "}" ); i = blockIndices.endIndex; } } else { output.push( token.match ); } } return output.join( "" ); } }