1
1
/* eslint-disable react/jsx-no-comment-textnodes */
2
2
import React , { Component , useState } from "react" ;
3
+ import { docco } from "react-syntax-highlighter/dist/esm/styles/hljs" ;
3
4
import copyToClipboard from "clipboard-copy" ;
5
+ import SyntaxHighlighter from "react-syntax-highlighter" ;
4
6
5
7
import "normalize.css/normalize.css" ;
6
8
import "./index.css" ;
@@ -44,6 +46,35 @@ function readInDirectives() {
44
46
}
45
47
}
46
48
49
+ const libraryCode = {
50
+ express : directives => {
51
+ let setHeaderCode = "res.set('Cache-Control', '" ;
52
+ for ( let i = 0 ; i < directives . length ; i ++ ) {
53
+ const directive = directives [ i ] ;
54
+ setHeaderCode +=
55
+ directive . name +
56
+ ( directive . args && directive . args . length
57
+ ? " " + directive . args . join ( " " )
58
+ : "" ) ;
59
+ if ( directives . length > 1 && i !== directives . length - 1 ) {
60
+ setHeaderCode += ", " ;
61
+ }
62
+ }
63
+ setHeaderCode += "');" ;
64
+ let code = "// for all responses\n" ;
65
+ code += "app.use((req, res, next) => {\n" ;
66
+ code += " " + setHeaderCode + "\n" ;
67
+ code += " next();\n" ;
68
+ code += "});\n\n" ;
69
+ code += "// for single response\n" ;
70
+ code += setHeaderCode ;
71
+ return code ;
72
+ } ,
73
+ koa : directives => {
74
+ return "" ;
75
+ }
76
+ } ;
77
+
47
78
function Directive ( { name, args = [ ] } ) {
48
79
return (
49
80
< span className = "HeaderDirective" >
@@ -54,7 +85,7 @@ function Directive({ name, args = [] }) {
54
85
) ;
55
86
}
56
87
57
- function Fieldset ( { title, description, active, fields } ) {
88
+ function Fieldset ( { title, description, active, fields = ( ) => { } } ) {
58
89
const [ open , setOpen ] = useState ( initialOpenDirectives . includes ( title ) ) ;
59
90
60
91
return (
@@ -73,6 +104,8 @@ function Fieldset({ title, description, active, fields }) {
73
104
74
105
export default class App extends Component {
75
106
state = {
107
+ showLibraryCode : true ,
108
+ codeLibrary : "express" ,
76
109
directives : readInDirectives ( )
77
110
} ;
78
111
@@ -128,6 +161,7 @@ export default class App extends Component {
128
161
< ul className = "Menu" >
129
162
< li className = "Menu__item" >
130
163
< a
164
+ title = "Copy a shareable link for this header configuration"
131
165
href = { shareUrl }
132
166
onClick = { evt => {
133
167
evt . preventDefault ( ) ;
@@ -139,6 +173,7 @@ export default class App extends Component {
139
173
</ li >
140
174
< li className = "Menu__item" >
141
175
< a
176
+ title = "Copy the header text to your clipboard"
142
177
href = "#"
143
178
onClick = { evt => {
144
179
evt . preventDefault ( ) ;
@@ -368,90 +403,135 @@ export default class App extends Component {
368
403
</ label >
369
404
] }
370
405
/>
371
- < fieldset >
372
- < legend > no-cache</ legend >
373
- < div >
406
+ < Fieldset
407
+ title = { Directives [ " no-cache" ] }
408
+ description = {
374
409
< p >
375
410
Forces caches to submit the request to the origin server for
376
411
validation before releasing a cached copy.
377
412
</ p >
378
- </ div >
379
- </ fieldset >
380
- < fieldset >
381
- < legend > only-if-cached</ legend >
382
- < div >
413
+ }
414
+ / >
415
+ < Fieldset
416
+ title = { Directives [ " only-if-cached" ] }
417
+ description = {
383
418
< p >
384
419
Indicates to not retrieve new data. This being the case, the
385
420
server wishes the client to obtain a response only once and
386
421
then cache. From this moment the client should keep releasing
387
422
a cached copy and avoid contacting the origin-server to see if
388
423
a newer copy exists.
389
424
</ p >
390
- </ div >
391
- </ fieldset >
392
- < fieldset >
393
- < legend > must-revalidate</ legend >
394
- < div >
395
- < p >
396
- Where no-cache will immediately revalidate with the server,
397
- and only use a cached copy if the server says it may,
398
- must-revalidate is like no-cache with a grace period.
399
- </ p >
400
- < p >
401
- must-revalidate needs an associated max-age directive; above,
402
- we’ve set it to ten minutes.
403
- </ p >
404
- </ div >
405
- </ fieldset >
406
- < fieldset >
407
- < legend > proxy-revalidate</ legend >
408
- < div >
425
+ }
426
+ />
427
+ < Fieldset
428
+ title = { Directives [ "must-revalidate" ] }
429
+ description = {
430
+ < >
431
+ < p >
432
+ Where no-cache will immediately revalidate with the server,
433
+ and only use a cached copy if the server says it may,
434
+ must-revalidate is like no-cache with a grace period.
435
+ </ p >
436
+ < p >
437
+ must-revalidate needs an associated max-age directive;
438
+ above, we’ve set it to ten minutes.
439
+ </ p >
440
+ </ >
441
+ }
442
+ />
443
+ < Fieldset
444
+ title = { Directives [ "proxy-revalidate" ] }
445
+ description = {
409
446
< p >
410
447
In a similar vein to s-maxage, proxy-revalidate is the
411
448
public-cache specific version of must-revalidate. It is simply
412
449
ignored by private caches.
413
450
</ p >
414
- </ div >
415
- </ fieldset >
416
- < fieldset >
417
- < legend > immutable</ legend >
418
- < div >
451
+ }
452
+ / >
453
+ < Fieldset
454
+ title = { Directives [ " immutable" ] }
455
+ description = {
419
456
< p >
420
457
immutable is a way of telling the browser that a file will
421
458
never change—it’s immutable—and therefore never to bother
422
459
revalidating it. We can completely cut out the overhead of a
423
460
roundtrip of latency.
424
461
</ p >
425
- </ div >
426
- </ fieldset >
427
- < fieldset >
428
- < legend > stale-while-revalidate</ legend >
429
- < div >
462
+ }
463
+ / >
464
+ < Fieldset
465
+ title = { Directives [ " stale-while-revalidate" ] }
466
+ description = {
430
467
< p >
431
468
Indicates that the client is willing to accept a stale
432
469
response while asynchronously checking in the background for a
433
470
fresh one. The seconds value indicates for how long the client
434
471
is willing to accept a stale response.
435
472
</ p >
436
- </ div >
437
- </ fieldset >
473
+ }
474
+ / >
438
475
</ form >
439
476
< div className = "Result" onClick = { ( ) => this . copyToClipboard ( ) } >
440
- < pre className = "Result__header" >
441
- Cache-Control:{ `\n` }
442
- { this . state . directives . map ( directive => {
443
- return < Directive key = { directive . name } { ...directive } /> ;
444
- } ) }
445
- { ! this . state . directives . length ? (
446
- < span className = "Result__placeholder" >
447
- { " " } // configure directives
448
- < br />
449
- { " " } // using the panel
450
- < br />
451
- { " " } // on the left
452
- </ span >
453
- ) : null }
454
- </ pre >
477
+ < div className = "ResultHeader" >
478
+ < pre className = "ResultHeader__header" >
479
+ Cache-Control:{ `\n` }
480
+ { this . state . directives . map ( directive => {
481
+ return < Directive key = { directive . name } { ...directive } /> ;
482
+ } ) }
483
+ { ! this . state . directives . length ? (
484
+ < span className = "ResultHeader__placeholder" >
485
+ { " " } // configure directives
486
+ < br />
487
+ { " " } // using the panel
488
+ < br />
489
+ { " " } // on the left
490
+ </ span >
491
+ ) : null }
492
+ </ pre >
493
+ </ div >
494
+ < div className = "ResultCode" >
495
+ < div className = "ResultCode__header" >
496
+ < div
497
+ className = "ResultCode__header-toggle"
498
+ onClick = { ( ) =>
499
+ this . setState ( {
500
+ showLibraryCode : ! this . state . showLibraryCode
501
+ } )
502
+ }
503
+ >
504
+ Library Code{ " " }
505
+ < span > ({ this . state . showLibraryCode ? "hide" : "show" } )</ span >
506
+ </ div >
507
+ < div >
508
+ < select
509
+ className = "ResultCode__header-select"
510
+ value = { this . state . codeLibrary }
511
+ onChange = { evt => {
512
+ evt . preventDefault ( ) ;
513
+ this . setState ( {
514
+ showLibraryCode : true ,
515
+ codeLibrary : evt . target . value
516
+ } ) ;
517
+ } }
518
+ >
519
+ { Object . keys ( libraryCode ) . map ( lib => {
520
+ return < option key = { lib } > { lib } </ option > ;
521
+ } ) }
522
+ </ select >
523
+ </ div >
524
+ </ div >
525
+ < div style = { styles . hide ( ! this . state . showLibraryCode ) } >
526
+ < SyntaxHighlighter
527
+ className = "ResultCode__code"
528
+ language = "javascript"
529
+ style = { docco }
530
+ >
531
+ { libraryCode [ this . state . codeLibrary ] ( this . state . directives ) }
532
+ </ SyntaxHighlighter >
533
+ </ div >
534
+ </ div >
455
535
</ div >
456
536
</ main >
457
537
< footer className = "Footer" >
0 commit comments