33// together with the solution code.
44
55const PJSON = require ( "./pseudo_json" )
6- var fs = require ( "fs" ) ;
6+ let fs = require ( "fs" ) ;
77
8- var output = [ ] , failed = false ;
8+ let output = [ ] , failed = false ;
99
10- var allSolutions = fs . readdirSync ( "code/solutions/" ) . filter ( function ( file ) { return ! / ^ 2 [ 0 1 2 ] / . test ( file ) ; } ) ;
10+ let allSolutions = fs . readdirSync ( "code/solutions/" ) . filter ( file => ! / ^ 2 [ 0 1 2 ] / . test ( file ) ) ;
1111
12- var dir = fs . readdirSync ( "." ) ;
13- dir . sort ( ) ;
14- dir . forEach ( function ( file ) {
15- var match = / ^ ( ( \d + ) .* ) .m d $ / . exec ( file ) , chapNum = match && match [ 2 ] ;
16- if ( ! match ) return ;
17- var text = fs . readFileSync ( file , "utf8" ) ;
12+ for ( let file of fs . readdirSync ( "." ) . sort ( ) ) {
13+ let match = / ^ ( ( \d + ) .* ) .m d $ / . exec ( file ) , chapNum = match && match [ 2 ] ;
14+ if ( ! match || chapNum == 22 ) continue ;
15+ let text = fs . readFileSync ( file , "utf8" ) ;
1816
1917 let meta = ( / { { meta ( .* ) } } / . exec ( text ) || { 1 : "{}" } ) [ 1 ]
20- var includes = / \b l o a d _ f i l e s : ( \[ .* ?\] ) / . exec ( meta )
18+ let includes = / \b l o a d _ f i l e s : ( \[ .* ?\] ) / . exec ( meta )
2119 if ( includes ) includes = JSON . parse ( includes [ 1 ] ) ;
22- var chapter = { number : + chapNum ,
20+ let chapter = { number : + chapNum ,
2321 id : match [ 1 ] ,
2422 title : text . match ( / (?: ^ | \n ) # ( .* ?) \n / ) [ 1 ] ,
2523 start_code : getStartCode ( text , includes ) ,
2624 exercises : [ ] ,
2725 include : includes } ;
28- var zip = chapterZipFile ( text , chapter ) ;
29- var extraLinks = meta . match ( / \b c o d e _ l i n k s : ( \[ .* ?\] ) / ) ;
26+ let zip = chapterZipFile ( text , chapter ) ;
27+ let extraLinks = meta . match ( / \b c o d e _ l i n k s : ( \[ .* ?\] ) / ) ;
3028 if ( extraLinks ) extraLinks = JSON . parse ( extraLinks [ 1 ] ) ;
3129 if ( extraLinks || zip )
3230 chapter . links = ( zip ? [ zip ] : [ ] ) . concat ( extraLinks || [ ] ) ;
3331
34- var exerciseSection = text . indexOf ( "\n## Exercises\n" ) ;
35- var exerciseBlock = exerciseSection >= 0 ? text . slice ( exerciseSection ) : "" ;
36- var header = / \n # # # ( .* ?) \n / g, nextHeader = / \n # # + \w / g;
37- var num = 1 ;
32+ let exerciseSection = text . indexOf ( "\n## Exercises\n" ) ;
33+ let exerciseBlock = exerciseSection >= 0 ? text . slice ( exerciseSection ) : "" ;
34+ let header = / \n # # # ( .* ?) \n / g, nextHeader = / \n # # + \w / g;
35+ let num = 1 ;
3836 while ( match = header . exec ( exerciseBlock ) ) {
3937 nextHeader . lastIndex = header . lastIndex
4038 let foundNext = nextHeader . exec ( exerciseBlock )
41- var nextsection = foundNext ? foundNext . index : - 1
42- for ( var pos = header . lastIndex ; ; ) {
43- var ifdef = exerciseBlock . indexOf ( "{{if interactive" , pos ) ;
39+ let nextsection = foundNext ? foundNext . index : - 1
40+ for ( let pos = header . lastIndex ; ; ) {
41+ let ifdef = exerciseBlock . indexOf ( "{{if interactive" , pos ) ;
4442 if ( ifdef == - 1 || nextsection > 0 && nextsection < ifdef ) break ;
45- var indef = exerciseBlock . slice ( pos = ifdef + 15 , exerciseBlock . indexOf ( "if}}" , ifdef ) ) ;
46- var sourceBlock = indef . match ( / ` ` ` ( .* ) \n ( [ ^ ] + ?) \n ` ` ` / ) ;
43+ let indef = exerciseBlock . slice ( pos = ifdef + 15 , exerciseBlock . indexOf ( "if}}" , ifdef ) ) ;
44+ let sourceBlock = indef . match ( / ` ` ` ( .* ) \n ( [ ^ ] + ?) \n ` ` ` / ) ;
4745 if ( ! sourceBlock || sourceBlock [ 1 ] . indexOf ( "null" ) > - 1 ) continue ;
48- var type = sourceBlock [ 1 ] . indexOf ( "html" ) > - 1 ? "html" : "js" ;
49- var file = chapNum + "_" + num + "_" + match [ 1 ] . toLowerCase ( ) . replace ( / [ ^ \- \s \w ] / g, "" ) . replace ( / \s / g, "_" ) + "." + type ;
46+ let type = sourceBlock [ 1 ] . indexOf ( "html" ) > - 1 ? "html" : "js" ;
47+ let file = chapNum + "_" + num + "_" + match [ 1 ] . toLowerCase ( ) . replace ( / [ ^ \- \s \w ] / g, "" ) . replace ( / \s / g, "_" ) + "." + type ;
48+ let solution , extra
5049 try {
51- var solution = fs . readFileSync ( "code/solutions/" + file , "utf8" ) ;
52- var extra = / ^ \s * < ! d o c t y p e h t m l > \s * ( < b a s e .* \n ( < s c r i p t s r c = .* \n ) * ) ? / . exec ( solution ) ;
50+ solution = fs . readFileSync ( "code/solutions/" + file , "utf8" ) ;
51+ extra = / ^ \s * < ! d o c t y p e h t m l > \s * ( < b a s e .* \n ( < s c r i p t s r c = .* \n ) * ) ? / . exec ( solution ) ;
5352 if ( extra ) solution = solution . slice ( extra [ 0 ] . length ) ;
5453 allSolutions . splice ( allSolutions . indexOf ( file ) , 1 ) ;
5554 } catch ( e ) {
@@ -71,7 +70,7 @@ dir.forEach(function(file) {
7170 ++ num ;
7271 }
7372
74- var nodeInfo = "// Node exercises can not be ran in the browser,\n// but you can look at their solution here.\n" ;
73+ let nodeInfo = "// Node exercises can not be ran in the browser,\n// but you can look at their solution here.\n" ;
7574 if ( chapter . number == 20 ) chapter . exercises = [
7675 { name : "Search tool" ,
7776 file : "code/solutions/20_1_search_tool.js" ,
@@ -113,6 +112,36 @@ dir.forEach(function(file) {
113112 ] ;
114113
115114 output . push ( chapter ) ;
115+ }
116+
117+ output . push ( {
118+ title : "JavaScript and Performance" ,
119+ number : 22 ,
120+ start_code : "<!-- This chapter exists in the paper book, not in the online version -->\n\n<script>\n runLayout(forceDirected_simple, treeGraph(4, 4));\n</script>\n" ,
121+ include : [ "code/draw_layout.js" , "code/chapter/22_fast.js" ] ,
122+ exercises : [
123+ { name : "Pathfinding" ,
124+ file : "code/solutions/22_1_pathfinding.js" ,
125+ number : 1 ,
126+ type : "js" ,
127+ code : "function findPath(a, b) {\n // Your code here...\n}\n\nlet graph = treeGraph(4, 4);\nlet root = graph[0], leaf = graph[graph.length - 1];\nconsole.log(findPath(root, leaf).length);\n// → 4\n\nleaf.connect(root);\nconsole.log(findPath(root, leaf).length);\n// → 2\n" ,
128+ solution : fs . readFileSync ( "code/solutions/22_1_pathfinding.js" , "utf8" )
129+ } ,
130+ { name : "Timing" ,
131+ file : "code/solutions/22_2_timing.js" ,
132+ number : 2 ,
133+ type : "js" ,
134+ code : "" ,
135+ solution : fs . readFileSync ( "code/solutions/22_2_timing.js" , "utf8" )
136+ } ,
137+ { name : "Optimizing" ,
138+ file : "code/solutions/22_3_optimizing.js" ,
139+ number : 3 ,
140+ type : "js" ,
141+ code : "" ,
142+ solution : fs . readFileSync ( "code/solutions/22_3_optimizing.js" , "utf8" )
143+ }
144+ ]
116145} ) ;
117146
118147if ( allSolutions . length ) {
@@ -126,25 +155,23 @@ else
126155 process . exit ( 1 ) ;
127156
128157function prepareHTML ( code , include ) {
129- return "<!doctype html>\n" + ( include || [ ] ) . map ( function ( s ) {
130- return "<script src=\"" + s + "\"></script>\n" ;
131- } ) . join ( "" ) + "\n" + code ;
158+ return "<!doctype html>\n" + ( include || [ ] ) . map ( s => "<script src=\"" + s + "\"></script>\n" ) . join ( "" ) + "\n" + code ;
132159}
133160
134161function guessType ( code ) {
135162 return / ^ [ \s \w \n : ] * < / . test ( code ) ? "html" : "js" ;
136163}
137164
138165function getStartCode ( text , includes ) {
139- var found = / \n ` ` ` ( .* ?\b s t a r t C o d e : .* ) \n ( [ ^ ] * ?\n ) ` ` ` / . exec ( text ) ;
166+ let found = / \n ` ` ` ( .* ?\b s t a r t C o d e : .* ) \n ( [ ^ ] * ?\n ) ` ` ` / . exec ( text ) ;
140167 if ( ! found ) return ""
141168
142- var snippet = found [ 2 ] . replace ( / ( \n | ^ ) \s * \/ \/ → .* \n / g, "$1" ) ;
143- var directive = String ( PJSON . parse ( found [ 1 ] ) . startCode ) , m ;
169+ let snippet = found [ 2 ] . replace ( / ( \n | ^ ) \s * \/ \/ → .* \n / g, "$1" ) ;
170+ let directive = String ( PJSON . parse ( found [ 1 ] ) . startCode ) , m ;
144171 if ( m = directive . match ( / t o p _ l i n e s : \s * ( \d + ) / ) )
145172 snippet = snippet . split ( "\n" ) . slice ( 0 , Number ( m [ 1 ] ) ) . join ( "\n" ) + "\n" ;
146173 if ( m = directive . match ( / b o t t o m _ l i n e s : \s * ( \d + ) / ) ) {
147- var lines = snippet . trimRight ( ) . split ( "\n" ) ;
174+ let lines = snippet . trimRight ( ) . split ( "\n" ) ;
148175 snippet = lines . slice ( lines . length - Number ( m [ 1 ] ) ) . join ( "\n" ) + "\n" ;
149176 }
150177 if ( guessType ( snippet ) == "html" )
@@ -154,28 +181,28 @@ function getStartCode(text, includes) {
154181}
155182
156183function chapterZipFile ( text , chapter ) {
157- var spec = text . match ( / \n : z i p : ( \S + ) (?: i n c l u d e = ( .* ) ) ? / ) ;
184+ let spec = text . match ( / \n : z i p : ( \S + ) (?: i n c l u d e = ( .* ) ) ? / ) ;
158185 if ( ! spec ) return null ;
159186 if ( ! chapter . start_code ) throw new Error ( "zip but no start code" ) ;
160- var name = "code/chapter/" + chapter . id + ".zip" ;
161- var files = ( chapter . include || [ ] ) . concat ( spec [ 2 ] ? JSON . parse ( spec [ 2 ] ) : [ ] ) ;
162- var exists = fs . existsSync ( name ) && fs . statSync ( name ) . mtime ;
163- if ( exists && files . every ( function ( file ) { return fs . statSync ( "html/" + file ) . mtime < exists ; } ) )
187+ let name = "code/chapter/" + chapter . id + ".zip" ;
188+ let files = ( chapter . include || [ ] ) . concat ( spec [ 2 ] ? JSON . parse ( spec [ 2 ] ) : [ ] ) ;
189+ let exists = fs . existsSync ( name ) && fs . statSync ( name ) . mtime ;
190+ if ( exists && files . every ( file => fs . statSync ( "html/" + file ) . mtime < exists ) )
164191 return name ;
165192
166- var zip = new ( require ( "jszip" ) ) ;
167- files . forEach ( function ( file ) {
193+ let zip = new ( require ( "jszip" ) ) ;
194+ for ( let file of files ) {
168195 zip . file ( chapter . id + "/" + file , fs . readFileSync ( "html/" + file ) ) ;
169- } ) ;
196+ }
170197 if ( spec [ 1 ] . indexOf ( "html" ) != - 1 ) {
171- var html = chapter . start_code ;
198+ let html = chapter . start_code ;
172199 if ( guessType ( html ) != "html" )
173200 html = prepareHTML ( "<body><script>\n" + html . trim ( ) + "\n</script></body>" , chapter . include ) ;
174201 zip . file ( chapter . id + "/index.html" , html ) ;
175202 }
176203 if ( spec [ 1 ] . indexOf ( "node" ) != - 1 ) {
177204 zip . file ( chapter . id + "/code/load.js" , fs . readFileSync ( "code/load.js" , "utf8" ) ) ;
178- var js = chapter . start_code ;
205+ let js = chapter . start_code ;
179206 if ( chapter . include ) js = "// load dependencies\nrequire(\"./code/load\")(" + chapter . include . map ( JSON . stringify ) . join ( ", " ) + ");\n\n" + js ;
180207 zip . file ( chapter . id + "/run_with_node.js" , js ) ;
181208 }
0 commit comments