@@ -28,22 +28,10 @@ const myTheme = createCssVariablesTheme({
28
28
* @param {DataFixture } data - The state object containing the necessary data for HTML generation.
29
29
* @returns {Promise<string> } A promise that resolves to the generated HTML content.
30
30
*/
31
- export async function generateHtml ( {
32
- stateName,
33
- state,
34
- languageId : lang ,
35
- command,
36
- ide,
37
- raw
38
- } : {
39
- stateName : string ;
40
- state : TestCaseSnapshot ;
41
- languageId : BundledLanguage ;
42
- command ?: any ; // Replace `any` with the appropriate type if with
43
- ide ?: any ; // Replace `any` with the appropriate type if known
44
- raw : any ;
45
- } ) {
46
- return new HTMLGenerator ( { state, lang, command, ide, raw } ) . generate ( ) ;
31
+ export async function generateHtml ( data : DataFixture ) {
32
+ const HTMLOBject = await new HTMLGenerator ( data )
33
+ const returnObject = HTMLOBject . generateAll ( )
34
+ return returnObject ;
47
35
}
48
36
49
37
const highlighter = createHighlighter ( {
@@ -61,63 +49,146 @@ type ExtendedTestCaseSnapshot = TestCaseSnapshot &
61
49
} ;
62
50
63
51
class HTMLGenerator {
64
- private state : TestCaseSnapshot ;
52
+ private testCaseStates : {
53
+ before : ExtendedTestCaseSnapshot | undefined ;
54
+ during : ExtendedTestCaseSnapshot | undefined ;
55
+ after : ExtendedTestCaseSnapshot | undefined ;
56
+ }
65
57
private lang : Lang ;
66
- private command ?: any ;
67
- private ide ?: any ;
68
- private raw : any ;
69
-
70
- constructor ( {
71
- state,
72
- lang,
73
- command,
74
- ide,
75
- raw
76
- } : {
77
- state : TestCaseSnapshot ,
78
- lang : Lang ,
79
- command ?: any ,
80
- ide ?: any ,
81
- raw ?: any
82
- } ) {
83
- this . state = state ;
84
- this . lang = lang ;
58
+ private command ?: CommandLatest | Command ;
59
+ private raw : TestCaseFixture ;
60
+ private rendered : {
61
+ before : string ;
62
+ during : string ;
63
+ after : string ;
64
+ }
65
+
66
+ constructor ( data : DataFixture ) {
67
+ const { languageId, command } = data ;
68
+ this . lang = languageId as BundledLanguage ;
85
69
this . command = command ; // Optional command parameter
86
- this . ide = ide ; // Optional ide parameter
87
- this . raw = raw
70
+ this . raw = data
71
+ this . rendered = {
72
+ before : "" ,
73
+ during : "" ,
74
+ after : "" ,
75
+ }
76
+ this . testCaseStates = {
77
+ before : data . initialState ,
78
+ during : {
79
+ ...(
80
+ /**
81
+ * Spread the document state with more lines (finalState vs initialState),
82
+ * so Shiki decorations stay in bounds and don't go out of range.
83
+ */
84
+ data . finalState &&
85
+ ( data . finalState . documentContents ?. split ( "\n" ) . length > data . initialState . documentContents ?. split ( "\n" ) . length )
86
+ ? data . finalState
87
+ : data . initialState
88
+ ) ,
89
+ ...data . ide ,
90
+ finalStateMarkHelpers : {
91
+ thatMark : data ?. finalState ?. thatMark ,
92
+ sourceMark : data ?. finalState ?. sourceMark
93
+ }
94
+ } ,
95
+ after : data . finalState
96
+ }
88
97
}
89
98
99
+ async generate ( stepName : StepNameType ) {
100
+ const state = this . testCaseStates [ stepName ]
101
+
102
+ if ( ! state ) {
103
+ console . error ( `Error in ${ stepName } ${ this . raw . command . spokenForm } ` )
104
+ return "Error"
105
+ }
106
+
107
+ const decorations = await this . getDecorations ( state ) ;
108
+
109
+ const { documentContents } = state
110
+
111
+ const htmlArray : string [ ] = [ ]
112
+ let codeBody ;
113
+
114
+ const errorLevels = [
115
+ "excludes thatMarks sourceMarks selectionRanges ideFlashes" ,
116
+ "excludes thatMarks sourceMarks selectionRanges" ,
117
+ "excludes thatMarks sourceMarks" ,
118
+ "excludes thatMarks" ,
119
+ "success" ,
120
+ ]
121
+
122
+ let errorLevel = errorLevels . length - 1
90
123
91
- async generate ( ) {
92
- const decorations = await this . getDecorations ( ) ;
93
- const options = {
94
- theme : "css-variables" ,
95
- lang : this . lang ,
96
- decorations
97
- } ;
124
+ for ( let i = decorations . length - 1 ; i >= 0 ; i -- ) {
125
+ const fallbackDecoration = decorations . slice ( 0 , i ) . flat ( ) ;
126
+ errorLevel = i
127
+ try {
128
+ const marker = await highlighter ;
129
+ const options = {
130
+ theme : "css-variables" ,
131
+ lang : this . lang ,
132
+ decorations : fallbackDecoration
133
+ } ;
134
+ codeBody = marker . codeToHtml ( documentContents , options ) ;
135
+ htmlArray . push ( codeBody )
136
+ break ; // Exit loop if successful
137
+ } catch ( error ) {
138
+ console . warn ( "Failed with decorations level:" , fallbackDecoration , error ) ;
139
+ // Continue to the next fallback level
140
+ }
141
+ }
142
+
143
+ if ( ! codeBody ) {
144
+ console . error ( "All fallback levels failed. Unable to generate code body." ) ;
145
+ codeBody = "" ; // Provide a default empty string or handle as needed
146
+ }
147
+
148
+ let clipboardRendered = ""
149
+ if ( state . clipboard ) {
150
+ clipboardRendered = `<pre><code>clipboard: ${ state . clipboard } </pre></code>`
151
+ if ( clipboardRendered !== "" ) {
152
+ htmlArray . push ( clipboardRendered )
153
+ }
154
+ }
155
+
156
+ let error = ""
157
+ if ( errorLevel !== errorLevels . length - 1 ) {
158
+ error = errorLevels [ errorLevel ]
159
+ const errorRendered = `<pre><code>Omitted due to errors: ${ error } </pre></code>`
160
+ htmlArray . push ( errorRendered )
161
+ }
162
+ return htmlArray . join ( "" )
163
+ }
164
+
165
+ async generateAll ( ) {
98
166
99
- const marker = await highlighter
100
- const codeBody = marker . codeToHtml ( this . state . documentContents , options )
101
- let clipboard = ""
102
- if ( this . state . clipboard ) {
103
- clipboard = `<pre><code>clipboard: ${ this . state . clipboard } </pre></code>`
167
+ const output = {
168
+ before : await this . generate ( "before" ) ,
169
+ during : await this . generate ( "during" ) ,
170
+ after : await this . generate ( "after" ) ,
104
171
}
105
- const output = clipboard !== "" ? codeBody + clipboard : codeBody
106
172
return output
107
173
}
108
174
109
- async getDecorations ( ) {
110
- const potentialMarks = this . state . marks || { }
111
- const lines = this . state . documentContents . split ( "\n" )
112
- console . log ( "💎" , this . state . thatMark )
113
- const decorations = createDecorations ( {
175
+ async getDecorations ( testCaseState : ExtendedTestCaseSnapshot ) {
176
+ const { messages, flashes, highlights, finalStateMarkHelpers } = testCaseState
177
+
178
+ const potentialMarks = testCaseState . marks || { }
179
+ const lines = testCaseState . documentContents . split ( "\n" )
180
+ const obj = {
114
181
marks : potentialMarks ,
115
- ide : this . ide ,
182
+ ide : { messages , flashes , highlights } ,
116
183
command : this . command ,
117
184
lines,
118
- selections : this . state . selections ,
119
- thatMark : this . state . thatMark
120
- } )
185
+ selections : testCaseState . selections ,
186
+ thatMark : testCaseState . thatMark ,
187
+ sourceMark : testCaseState . sourceMark ,
188
+ finalStateMarkHelpers
189
+ }
190
+
191
+ const decorations = createDecorations ( obj )
121
192
return decorations
122
193
}
123
194
}
0 commit comments