library-ts/browser/templates/styles-processor/StylesProcessorLexer.ts

168 lines
5.1 KiB
TypeScript
Raw Normal View History

2025-03-08 08:16:54 +00:00
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 =
2025-09-06 11:33:04 +00:00
new LexerMatcher( StylesProcessorLexer.ROOT_ELEMENT_REPLACER, /#_/ );
2025-03-08 08:16:54 +00:00
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( "" );
}
}