1+ /// Processes all unity log messages and converts unity rich text to css styled console messages
2+ /// from https://github.com/JohannesDeml/UnityWebGL-LoadingTest
3+
4+ function setupConsoleLogPipe ( ) {
5+ // Store actual console log functions
6+ let defaultConsoleLog = console . log ;
7+ let defaultConsoleInfo = console . info ;
8+ let defaultConsoleDebug = console . debug ;
9+ let defaultConsoleWarn = console . warn ;
10+ let defaultConsoleError = console . error ;
11+
12+ // Overwrite log functions to parse and pipe to debug html console
13+ console . log = ( message ) => { parseMessageAndLog ( message , defaultConsoleLog ) ; } ;
14+ console . info = ( message ) => { parseMessageAndLog ( message , defaultConsoleInfo ) ; } ;
15+ console . debug = ( message ) => { parseMessageAndLog ( message , defaultConsoleDebug ) ; } ;
16+ console . warn = ( message ) => { parseMessageAndLog ( message , defaultConsoleWarn ) ; } ;
17+ console . error = ( message ) => { parseMessageAndLog ( message , defaultConsoleError ) ; } ;
18+
19+
20+ parseMessageAndLog = ( message , consoleLogFunction ) => {
21+ let styledTextParts = parseUnityRichText ( message ) ;
22+ let consoleText = '' ;
23+ let consoleStyle = [ ] ;
24+ styledTextParts . forEach ( textPart => {
25+ consoleText += textPart . toConsoleTextString ( ) ;
26+ consoleStyle . push ( textPart . toConsoleStyleString ( ) ) ;
27+ } ) ;
28+ consoleLogFunction ( consoleText , ...consoleStyle ) ;
29+ } ;
30+ }
31+
32+ class StyledTextPart {
33+ constructor ( text , styles ) {
34+ this . text = text ;
35+ this . styles = styles ;
36+ }
37+
38+ toHTML ( ) {
39+ if ( this . styles . length > 0 ) {
40+ return `<span style="${ this . styles . join ( ';' ) } ">${ this . text } </span>` ;
41+ }
42+ return this . text ;
43+ }
44+
45+ toConsoleStyleString ( ) {
46+ if ( this . styles . length > 0 ) {
47+ return this . styles . join ( ';' ) ;
48+ }
49+ return 'color:inherit' ;
50+ }
51+
52+ toConsoleTextString ( ) {
53+ return `%c${ this . text } ` ;
54+ }
55+ }
56+
57+ function parseUnityRichText ( message ) {
58+ // Mapping for unity tags to css style tags
59+ const tagMap = {
60+ 'color' : { startTag : '<color=' , closeTag : '</color>' , styleTag : 'color:' , postfix : '' , hasParameter : true } ,
61+ 'size' : { startTag : '<size=' , closeTag : '</size>' , styleTag : 'font-size:' , postfix : 'px' , hasParameter : true } ,
62+ 'bold' : { startTag : '<b' , closeTag : '</b>' , styleTag : 'font-weight:' , styleValue : 'bold' , hasParameter : false } ,
63+ 'italic' : { startTag : '<i' , closeTag : '</i>' , styleTag : 'font-style:' , styleValue : 'italic' , hasParameter : false }
64+ } ;
65+
66+ let index = 0 ;
67+ const styledTextParts = [ ] ;
68+
69+ // Stack of applied styles, so we can also nest styling
70+ let styleStack = [ ] ;
71+ // next start index for each tag
72+ let nextStartIndex = [ ] ;
73+ // next end index for each tag
74+ let nextEndIndex = [ ] ;
75+ Object . keys ( tagMap ) . forEach ( key => {
76+ nextStartIndex [ key ] = message . indexOf ( tagMap [ key ] . startTag , index ) ;
77+ nextEndIndex [ key ] = message . indexOf ( tagMap [ key ] . closeTag , index ) ;
78+ } ) ;
79+
80+ while ( index < message . length ) {
81+ let nextTagFound = false ;
82+ let nextKey ;
83+ let fromArray = [ ] ;
84+ let nextIndex = message . length ;
85+
86+ // find the next tag start or end
87+ Object . keys ( tagMap ) . forEach ( key => {
88+ if ( nextStartIndex [ key ] >= 0 && nextStartIndex [ key ] < nextIndex ) {
89+ nextIndex = nextStartIndex [ key ] ;
90+ nextKey = key ;
91+ fromArray = nextStartIndex ;
92+ nextTagFound = true ;
93+ }
94+
95+ if ( nextEndIndex [ key ] >= 0 && nextEndIndex [ key ] < nextIndex ) {
96+ nextIndex = nextEndIndex [ key ] ;
97+ nextKey = key ;
98+ fromArray = nextEndIndex ;
99+ nextTagFound = true ;
100+ }
101+ } ) ;
102+
103+ // write the text in before the next tag to our style text part array
104+ if ( nextIndex > index ) {
105+ let messageToNextTag = message . substring ( index , nextIndex ) ;
106+ let styles = [ ...styleStack ] ;
107+ styledTextParts . push ( new StyledTextPart ( messageToNextTag , styles ) ) ;
108+ }
109+
110+ // end if no more tags exist
111+ if ( nextTagFound === false ) {
112+ index = message . length ;
113+ break ;
114+ }
115+
116+ // Process start tag
117+ if ( fromArray === nextStartIndex ) {
118+ nextStartIndex [ nextKey ] = message . indexOf ( tagMap [ nextKey ] . startTag , nextIndex + 1 ) ;
119+ let closeTagIndex = message . indexOf ( '>' , nextIndex + 1 ) ;
120+ let styleValue ;
121+ if ( tagMap [ nextKey ] . hasParameter ) {
122+ styleValue = message . substring ( nextIndex + tagMap [ nextKey ] . startTag . length , closeTagIndex ) ;
123+ styleValue += tagMap [ nextKey ] . postfix ;
124+ } else {
125+ styleValue = tagMap [ nextKey ] . styleValue ;
126+ }
127+ styleStack . push ( `${ tagMap [ nextKey ] . styleTag } ${ styleValue } ` ) ;
128+ index = closeTagIndex + 1 ;
129+ }
130+ // process end tag
131+ else if ( fromArray === nextEndIndex ) {
132+ nextEndIndex [ nextKey ] = message . indexOf ( tagMap [ nextKey ] . closeTag , nextIndex + 1 ) ;
133+ let closeTagIndex = message . indexOf ( '>' , nextIndex + 1 ) ;
134+ styleStack . pop ( ) ;
135+ index = closeTagIndex + 1 ;
136+ }
137+ }
138+ return styledTextParts ;
139+ }
140+
141+ setupConsoleLogPipe ( ) ;
0 commit comments