168 lines
5.1 KiB
TypeScript
168 lines
5.1 KiB
TypeScript
![]() |
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<string>();
|
||
|
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( "" );
|
||
|
}
|
||
|
}
|