├── .gitignore
├── LICENSE
├── README.md
├── bin
├── forever.sh
└── pub.sh
├── index.js
├── lib
├── fetch-cache.js
└── static.js
├── package.json
├── routes
├── about.js
├── block.js
├── raw.js
└── user.js
├── static
├── github-gist.min.css
├── highlight.min.js
└── style.css
└── usercache
└── .gitkeep
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | /node_modules/
3 | /src/node_modules/@sapper/
4 | yarn-error.log
5 | /cypress/screenshots/
6 | /__sapper__/
7 | usercache/
8 | yarn.lock
9 | package-lock.json
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 chart-code
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Open source clone of [bl.ocks.org](https://bl.ocks.org/), hosted at [blocks.roadtolarissa.com](https://blocks.roadtolarissa.com).
2 |
3 | # dev
4 |
5 | `yarn && yarn dev`
6 |
7 | If you've installed [gistup](https://github.com/mbostock/gistup), http://localhost:3002/$yourUsername will include your private gists.
8 |
9 | To view your private gists without running locally, run `cat ~/.gistup.json` to get your token, and go to `https://blocks.roadtolarissa.com/$yourUsername?token=$token`
--------------------------------------------------------------------------------
/bin/forever.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # kill previous forever instance
4 | kill -9 $(pgrep -f ${BASH_SOURCE[0]} | grep -v $$)
5 |
6 | # kill previous server instance
7 | kill -9 $(lsof -t -i:3002 -sTCP:LISTEN)
8 |
9 | # restart server on error
10 | while true
11 | do
12 | node index.js
13 | sleep 1
14 | done
--------------------------------------------------------------------------------
/bin/pub.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | cd .. && rsync -a --omit-dir-times --no-perms --exclude node_modules --exclude usercache --exclude .git blocks/ demo@roadtolarissa.com:blocks/
4 |
5 | ssh demo@roadtolarissa.com <<'ENDSSH'
6 | #commands to run on remote host
7 | cd blocks/ \
8 | && yarn \
9 | && bin/forever.sh
10 | ENDSSH
11 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | var _ = require('underscore')
2 | var polka = require('polka')
3 |
4 | var about = require('./routes/about')
5 | var user = require('./routes/user')
6 | var block = require('./routes/block')
7 | var raw = require('./routes/raw')
8 | var static = require('./lib/static')
9 | var fetchCache = require('./lib/fetch-cache')
10 |
11 | var exec = require('await-exec')
12 | var argv = require('minimist')(process.argv.slice(2))
13 | var PORT = argv.port || 3002
14 | var DEV = argv.dev
15 |
16 |
17 | async function init(){
18 | polka()
19 | .use((req, res, next) => {
20 | if (req.query.cachebust) fetchCache.bust()
21 | next()
22 | })
23 | .get('/static/:file', (req, res) => {
24 | if (DEV) static = requireUncached('./lib/static')
25 | static(req, res)
26 | })
27 | .get('/cachebust', (req, res) => {
28 | fetchCache.bust()
29 | res.writeHead(301, {Location: '/'})
30 | })
31 | .get('/', (req, res) => {
32 | if (DEV) about = requireUncached('./routes/about')
33 | about(req, res)
34 | })
35 | .get('/:user', (req, res) => {
36 | if (DEV) user = requireUncached('./routes/user')
37 | user(req, res)
38 | })
39 | .get('/:user/:id', (req, res) => {
40 | if (DEV) block = requireUncached('./routes/block')
41 | block(req, res)
42 | })
43 | .get('/:user/raw/:id/:file?', (req, res) => {
44 | // redirect to add a slash
45 | if (!req.file && req.url.at(-1) != '/' && !req.url.includes('index.html')){
46 | res.statusCode = 302
47 | res.setHeader('Location', `${req.url}/`)
48 | res.end()
49 | } else {
50 | if (DEV) raw = requireUncached('./routes/raw')
51 | raw(req, res)
52 | }
53 | })
54 | .listen(PORT, err => {
55 | if (err) throw err
56 | console.log(`http://localhost:${PORT}`)
57 | // exec(`open http://localhost:${PORT}`)
58 | })
59 | }
60 |
61 | init()
62 |
63 |
64 | function requireUncached(module){
65 | delete require.cache[require.resolve(module)]
66 | return require(module)
67 | }
68 |
69 |
--------------------------------------------------------------------------------
/lib/fetch-cache.js:
--------------------------------------------------------------------------------
1 | var fetch = require('node-fetch')
2 | var io = require('indian-ocean')
3 |
4 | var cache = {}
5 |
6 | var defaultAuthorization = "";
7 |
8 | try{
9 | console.log(process.env.HOME + '/.gistup.json')
10 | var token = io.readDataSync(process.env.HOME + '/.gistup.json').token
11 | defaultAuthorization = 'token ' + token
12 | } catch (e){
13 | console.log('.gistup.json not found. create one to view your private gists https://github.com/mbostock/gistup')
14 | }
15 |
16 | module.exports = async function(url, type, token=''){
17 | var key = [url, type, token].join(' ')
18 |
19 | // Caching disabled - low traffic and OOM errors
20 | if (cache[key]) return cache[key].res
21 | console.log(key)
22 |
23 | var Authorization = token ? 'token ' + token : defaultAuthorization
24 | var res = await (await fetch(url, {headers: {Authorization}}))[type]()
25 | cache[key] = {res, time: new Date()}
26 |
27 | return res
28 | }
29 |
30 | module.exports.bust = () => {
31 | cache = {}
32 | console.log('cache bust')
33 | }
34 |
35 | !(async function(){
36 | // return // disable cache cleaning
37 | while (true){
38 | await sleep(60*1000)
39 | var time = new Date()
40 | for (key in cache){
41 | if (time - cache[key].time > 15*60*1000) delete cache[key]
42 | }
43 | }
44 | })()
45 |
46 | function sleep(ms) {
47 | return new Promise(resolve => setTimeout(resolve, ms))
48 | }
49 |
50 |
--------------------------------------------------------------------------------
/lib/static.js:
--------------------------------------------------------------------------------
1 | var io = require('indian-ocean')
2 | var fs = require('fs')
3 | var mime = require('mime-types')
4 |
5 | var rootdir = __dirname + '/../static/'
6 |
7 | var staticFiles = {}
8 | io.readdirFilterSync(rootdir).forEach(d => {
9 | if (d.includes('DS_Store')) return
10 | staticFiles[d] = fs.readFileSync(rootdir + d, 'utf8')
11 | })
12 |
13 | module.exports = async function get(req, res, next) {
14 | var {file} = req.params
15 |
16 | res.writeHead('200', {
17 | 'Content-Type': mime.lookup(file),
18 | 'Cache-Control': 'public, max-age=' + 1000*60,
19 | })
20 | res.end(staticFiles[file])
21 | }
22 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bl.ocks",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "repository": "git@github.com:chart-code/bl.ocks.git",
6 | "license": "MIT",
7 | "dependencies": {
8 | "await-exec": "^0.1.2",
9 | "compression": "^1.7.4",
10 | "d3": "^5.12.0",
11 | "highlight.js": "^9.15.10",
12 | "indian-ocean": "^4.0.0",
13 | "marked": "^0.7.0",
14 | "polka": "^0.5.2",
15 | "r2": "^2.0.1",
16 | "minimist": "1",
17 | "underscore": "^1.9.1"
18 | },
19 | "scripts": {
20 | "dev": "node index.js --dev=true",
21 | "start": "node index.js",
22 | "pub": "bin/pub.sh"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/routes/about.js:
--------------------------------------------------------------------------------
1 | function generateHTML(){
2 | var people = [
3 | '1wheel',
4 | 'Azgaar',
5 | 'Chi-Loong',
6 | 'EE2dev',
7 | 'EfratVil',
8 | 'Fil',
9 | 'GerHobbelt',
10 | 'Golodhros',
11 | 'GordyD',
12 | 'Gouayave',
13 | 'HarryStevens',
14 | 'Hypercubed',
15 | 'IPWright',
16 | 'IanHopkinson',
17 | 'JaapSuter',
18 | 'Jay-Oh-eN',
19 | 'JulienAssouline',
20 | 'Kcnarf',
21 | 'KristinHenry',
22 | 'LonRiesberg',
23 | 'Marithia',
24 | 'MartynJones87',
25 | 'MatthewSchumwinger',
26 | 'MikeCostelloe',
27 | 'NPashaP',
28 | 'Nastasi7',
29 | 'NelsonMinar',
30 | 'NickDiakopoulos',
31 | 'PatMartin',
32 | 'PatrickStotz',
33 | 'RandomEtc',
34 | 'ResidentMario',
35 | 'Rich-Harris',
36 | 'Rnhatch',
37 | 'SkiWether',
38 | 'SpaceActuary',
39 | 'StewartNoyce',
40 | 'Sumbera',
41 | 'TennisVisuals',
42 | 'TheNeuralBit',
43 | 'ThomasG77',
44 | 'VizzzHu',
45 | 'ZJONSSON',
46 | 'aaizemberg',
47 | 'adewes',
48 | 'aemkei',
49 | 'aendrew',
50 | 'ajzeigert',
51 | 'alandunning',
52 | 'alanmclean',
53 | 'alansmithy',
54 | 'alexandersimoes',
55 | 'alexmacy',
56 | 'alignedleft',
57 | 'almccon',
58 | 'amccartney',
59 | 'amundo',
60 | 'anatolyg',
61 | 'andrew12',
62 | 'andrewthornton',
63 | 'andrewxhill',
64 | 'annabsmylie',
65 | 'anonymous',
66 | 'ariaz',
67 | 'armollica',
68 | 'arnicas',
69 | 'arrayjam',
70 | 'arthurwelle',
71 | 'asielen',
72 | 'asparagino',
73 | 'atmccann',
74 | 'aubergene',
75 | 'awoodruff',
76 | 'badraufran',
77 | 'bdilday',
78 | 'bdon',
79 | 'bessiec',
80 | 'bherr2',
81 | 'bhvaleri',
82 | 'bill-kidwell',
83 | 'biovisualize',
84 | 'bjtucker',
85 | 'blacki',
86 | 'blob',
87 | 'bmershon',
88 | 'boeric',
89 | 'bollwyvl',
90 | 'bowmanmc',
91 | 'bradoyler',
92 | 'brattonc',
93 | 'bricedev',
94 | 'bricof',
95 | 'bryankennedy',
96 | 'brylie',
97 | 'bumbu',
98 | 'bunkat',
99 | 'burritojustice',
100 | 'bvancil',
101 | 'bycoffe',
102 | 'c-johnson',
103 | 'carlvlewis',
104 | 'cavedave',
105 | 'chantalgo',
106 | 'chemplexity',
107 | 'cherdarchuk',
108 | 'chriscanipe',
109 | 'christophermanning',
110 | 'chule',
111 | 'cjrd',
112 | 'ckuijjer',
113 | 'cmackay',
114 | 'cmgiven',
115 | 'cmpolis',
116 | 'corykendrick',
117 | 'couchand',
118 | 'cpbotha',
119 | 'curran',
120 | 'd3noob',
121 | 'dabos',
122 | 'danharr',
123 | 'daniarleagk',
124 | 'dannyko',
125 | 'danroberts',
126 | 'dansabo',
127 | 'darshit-shah',
128 | 'datummm',
129 | 'davidbeijinho',
130 | 'davidwatkins73',
131 | 'davo',
132 | 'dcabo',
133 | 'dehuszar',
134 | 'denisemauldin',
135 | 'devgru',
136 | 'dhoboy',
137 | 'djokicx',
138 | 'dlwjiang',
139 | 'dmann99',
140 | 'dmijalkovic',
141 | 'dnomadb',
142 | 'dnprock',
143 | 'domitry',
144 | 'dougdowson',
145 | 'dribnet',
146 | 'drifkin',
147 | 'drzax',
148 | 'duhaime',
149 | 'duhoang',
150 | 'dwtkns',
151 | 'ee2dev',
152 | 'eesur',
153 | 'eglassman',
154 | 'eins78',
155 | 'ejb',
156 | 'ekerstein',
157 | 'emacgillavry',
158 | 'emarschner',
159 | 'emeeks',
160 | 'emi-lp',
161 | 'enjalot',
162 | 'enoex',
163 | 'epmoyer',
164 | 'ericcitaire',
165 | 'erikhazzard',
166 | 'erlenstar',
167 | 'erohinaelena',
168 | 'esjewett',
169 | 'estk',
170 | 'etpinard',
171 | 'faniepotgieter',
172 | 'fernoftheandes',
173 | 'fil',
174 | 'finiterank',
175 | 'fogleman',
176 | 'fogonwater',
177 | 'gabrielflorit',
178 | 'gelicia',
179 | 'gengisb',
180 | 'georgemurphy',
181 | 'georules',
182 | 'geraldarthur',
183 | 'giorgi-ghviniashvili',
184 | 'gisminister',
185 | 'gka',
186 | 'guilhermesimoes',
187 | 'harasaki',
188 | 'harrystevens',
189 | 'hashcacher',
190 | 'heavysixer',
191 | 'helderdarocha',
192 | 'herrstucki',
193 | 'hlvoorhees',
194 | 'hobbes7878',
195 | 'hollasch',
196 | 'howarddd',
197 | 'hsuh',
198 | 'hugolpz',
199 | 'hwangmoretime',
200 | 'igb',
201 | 'ilyabo',
202 | 'inspired12',
203 | 'iros',
204 | 'ivyywang',
205 | 'jacquestardie',
206 | 'jalapic',
207 | 'jamescwaters',
208 | 'jarandaf',
209 | 'jasondavies',
210 | 'javidhsueh',
211 | 'jckr',
212 | 'jcnesci',
213 | 'jczaplew',
214 | 'jdarling',
215 | 'jeffcatania',
216 | 'jensgrub',
217 | 'jensgrubert',
218 | 'jeremybuis',
219 | 'jeremycflin',
220 | 'jermspeaks',
221 | 'jeromefroe',
222 | 'jessihamel',
223 | 'jfsiii',
224 | 'jhellier',
225 | 'jieqianzhang',
226 | 'jkutianski',
227 | 'jm3',
228 | 'jmahabal',
229 | 'jmuyskens',
230 | 'john-guerra',
231 | 'johnburnmurdoch',
232 | 'jonolave',
233 | 'jonsadka',
234 | 'joyrexus',
235 | 'jrbalsano',
236 | 'jrrickard',
237 | 'jsanch',
238 | 'jsundram',
239 | 'jtibbutt',
240 | 'jtremblay',
241 | 'jugglingnutcase',
242 | 'justlebeau',
243 | 'jwilber',
244 | 'k-izzo',
245 | 'karenpeng',
246 | 'katirg',
247 | 'kcsluis',
248 | 'kedarvaidya',
249 | 'kennelliott',
250 | 'kenpenn',
251 | 'kerryrodden',
252 | 'kevmo',
253 | 'kforeman',
254 | 'khoomeister',
255 | 'kiddphunk',
256 | 'koalaboy808',
257 | 'kpq',
258 | 'kristw',
259 | 'krsanford',
260 | 'larskotthoff',
261 | 'lelandlee',
262 | 'lewis500',
263 | 'lightjs',
264 | 'lindep',
265 | 'littletitans',
266 | 'maartenzam',
267 | 'madelfio',
268 | 'magrawala',
269 | 'majomo',
270 | 'malgarianirudh',
271 | 'mapearlson',
272 | 'mapsam',
273 | 'maptastik',
274 | 'martgnz',
275 | 'matt81m',
276 | 'mattdh666',
277 | 'mbostock',
278 | 'mccannf',
279 | 'melalj',
280 | 'meveritt',
281 | 'mgold',
282 | 'mhkeller',
283 | 'micahstubbs',
284 | 'michaeljules',
285 | 'michalskop',
286 | 'migurski',
287 | 'mikeyao',
288 | 'milroc',
289 | 'mimno',
290 | 'mitchparker',
291 | 'mjhoy',
292 | 'mkfreeman',
293 | 'mmazanec22',
294 | 'mmmatthew',
295 | 'monfera',
296 | 'mox-1',
297 | 'mpmckenna8',
298 | 'mr23',
299 | 'mrchrisadams',
300 | 'mstanaland',
301 | 'muratabur',
302 | 'mushon',
303 | 'mza',
304 | 'n1n9-jp',
305 | 'nascif',
306 | 'natebates',
307 | 'nbremer',
308 | 'ngopal',
309 | 'nikcub',
310 | 'ninjaPixel',
311 | 'nitaku',
312 | 'nivas8292',
313 | 'njvack',
314 | 'nmu',
315 | 'noahvelman',
316 | 'nsonnad',
317 | 'nstawski',
318 | 'nstrayer',
319 | 'nthitz',
320 | 'nydame',
321 | 'ofutondaisuki',
322 | 'oikonang',
323 | 'oluckyman',
324 | 'owen-dall',
325 | 'palewire',
326 | 'patricksurry',
327 | 'paulgovan',
328 | 'paulirish',
329 | 'pberden',
330 | 'pbogden',
331 | 'pcj',
332 | 'peatroot',
333 | 'peterbsmith2',
334 | 'petercook',
335 | 'petulla',
336 | 'phil-pedruco',
337 | 'phillipadsmith',
338 | 'phoebebright',
339 | 'pierrelorioux',
340 | 'pjsier',
341 | 'playwellsteve',
342 | 'plmrry',
343 | 'pnavarrc',
344 | 'podviaznikov',
345 | 'poezn',
346 | 'prabhasp',
347 | 'proclamo',
348 | 'pstuffa',
349 | 'ptrikutam',
350 | 'ptvans',
351 | 'quinnhj',
352 | 'ramnathv',
353 | 'raw',
354 | 'rcrocker13',
355 | 'redblobgames',
356 | 'renecnielsen',
357 | 'rflow',
358 | 'rfrankel',
359 | 'riccardoscalco',
360 | 'rickdg',
361 | 'rkirsling',
362 | 'rmarimon',
363 | 'roachhd',
364 | 'robinhouston',
365 | 'rogerfischer',
366 | 'romsson',
367 | 'roundrobin',
368 | 'rpgove',
369 | 'rveciana',
370 | 'sampathweb',
371 | 'samselikoff',
372 | 'samuelleach',
373 | 'saraquigley',
374 | 'sathomas',
375 | 'seemantk',
376 | 'seliopou',
377 | 'sethkontny',
378 | 'shancarter',
379 | 'shaundunne',
380 | 'shawnbot',
381 | 'shimizu',
382 | 'shobhitg',
383 | 'shrego',
384 | 'shreshthmohan',
385 | 'shubhgo',
386 | 'simonbreton',
387 | 'simzou',
388 | 'smilli',
389 | 'soccermatics',
390 | 'sorcereral',
391 | 'srinivashavanur',
392 | 'ssdatar',
393 | 'stephanieguo',
394 | 'steveharoz',
395 | 'stuwilmur',
396 | 'sugi2000',
397 | 'susielu',
398 | 'sxv',
399 | 'sxywu',
400 | 'syntagmatic',
401 | 'tanykim',
402 | 'tarekrached',
403 | 'thadk',
404 | 'thomasgwatson',
405 | 'thomasthoren',
406 | 'thordav',
407 | 'thrakt',
408 | 'timelyportfolio',
409 | 'tmcw',
410 | 'tomgp',
411 | 'tomstove',
412 | 'tomswisher',
413 | 'tonyhschu',
414 | 'tophtucker',
415 | 'treboresque',
416 | 'trinary',
417 | 'tvirot',
418 | 'upphiminn',
419 | 'vanceingalls',
420 | 'vanshady',
421 | 'vasturiano',
422 | 'veltman',
423 | 'veritas1uxmea',
424 | 'vicapow',
425 | 'vijithassar',
426 | 'vlandham',
427 | 'walkerjeffd',
428 | 'wardcunningham',
429 | 'wazaahhh',
430 | 'wboykinm',
431 | 'wereHamster',
432 | 'whatsthebeef',
433 | 'widged',
434 | 'wiinci',
435 | 'wilson428',
436 | 'wmerrow',
437 | 'xaranke',
438 | 'xiaonaitong',
439 | 'yelper',
440 | 'yesoreyeram',
441 | 'yonitru',
442 | 'zachmargolis',
443 | 'zanarmstrong',
444 | 'zeffii',
445 | 'zjhiphop',
446 | 'zjonsson',
447 | 'zuzap',
448 | ]
449 |
450 | return `
451 |
452 |
453 |
454 |
455 |
456 |
blocks
457 |
458 |
459 | Open source
460 | clone of
461 | bl.ocks.org
462 | — get started with Let’s Make a Block and d3-init.
463 |
464 |
${people.map(d => `${d} `).join('')}
465 |
466 |
Add your username!
467 | `
468 | }
469 |
470 | module.exports = async function get(req, res, next) {
471 | var html = generateHTML()
472 | res.writeHead(200, {'Content-Type': 'text/html'})
473 | res.end(html)
474 | }
475 |
476 |
477 | if (require.main === module){
478 | }
479 |
--------------------------------------------------------------------------------
/routes/block.js:
--------------------------------------------------------------------------------
1 | var fetchCache = require('./../lib/fetch-cache')
2 | var _ = require('underscore')
3 | var d3 = require('d3')
4 |
5 | var e = _.escape
6 |
7 | var hljs = require('highlight.js')
8 | var marked = require('marked')
9 | marked.setOptions({
10 | highlight: (code, lang) => {
11 | try{
12 | var obj = lang ? hljs.highlight(lang, code) : hljs.highlightAuto(code)
13 | } catch(e){
14 | console.log(e)
15 | var obj = hljs.highlightAuto(code)
16 | }
17 | return obj.value
18 | },
19 | smartypants: true
20 | })
21 |
22 | async function generateHTML(user, id, gist, query){
23 | if (!gist || !gist.files) return console.log('missing files')
24 |
25 | d3.keys(gist.files).forEach(key => {
26 | if (key.toLowerCase() != 'readme.md' || gist.files['README.md']) return
27 |
28 | gist.files['README.md'] = gist.files[key]
29 | delete gist.files[key]
30 | })
31 |
32 | var description = e(gist.description || id.substr(0, 20))
33 | var title = `${description} by ${e(user)}`
34 | var titleURL = `
35 | block by
36 | ${e(user)}
37 | ${id}`
38 |
39 | var files = d3.entries(gist.files)
40 | .filter(d => d.value.size < 20000)
41 | .filter(d => d.key[0] != '.')
42 | .filter(d => d.key != 'README.md')
43 | .filter(d => !d.key.includes('.png'))
44 |
45 | files = _.sortBy(files, d => d.key.includes('index.js') || d.key.includes('script.js') ? -2 : d.key.includes('index.html') ? -1 : 1)
46 |
47 | if (!gist.files) console.log('ERROR', gist)
48 |
49 | var iframeURL = `/${user}/raw/${id}/index.html`
50 | var rootURL = iframeURL.replace('index.html', '')
51 |
52 | // README.md is sometimes trucated; load seperately if it is
53 | if (gist.files['README.md'] && gist.files['README.md'].truncated){
54 | var url =`https://gist.githubusercontent.com/${user}/${id}/raw/README.md`
55 | gist.files['README.md'].content = await fetchCache(url, 'text')
56 | }
57 |
58 | var settings = {
59 | height: 500,
60 | scrolling: false,
61 | border: true,
62 | redirect: '',
63 | }
64 | if (gist.files['.block']){
65 | if (gist.files['.block'].truncated){
66 | var url =`https://gist.githubusercontent.com/${user}/${id}/raw/.block`
67 | gist.files['.block'].content = await fetchCache(url, 'text')
68 | }
69 |
70 | gist.files['.block'].content.split('\n')
71 | .filter(d => d && d.includes(': '))
72 | .forEach(line => {
73 | var [key, value] = line.split(': ')
74 | settings[key] = value == 'no' ? false : value
75 | })
76 | }
77 |
78 | d3.entries(query).forEach(({key, value}) => {
79 | if (value == 'no' || value == 'false' || value == '0') value = false
80 | settings[key] = value
81 | })
82 |
83 | return `
84 |
85 |
86 |
87 |
88 | ${
89 | gist.files['preview.png'] ?
90 | `
91 | `
92 | : ''
93 | }
94 |
95 |
96 |
97 |
98 |
99 |
100 |
${title}
101 | ${titleURL}
102 |
103 | ${description}
104 |
105 | ${gist.files['index.html'] ?
106 | `
107 | Full Screen
108 | `
115 | : ''
116 | }
117 |
118 |
119 | ${gist.files['README.md'] ? marked(gist.files['README.md'].content) : ''}
120 |
121 |
122 | ${settings.redirect ?
123 | ``
124 | : ''
125 | }
126 |
127 | ${files.map(d =>
128 | `
129 |
${d.key}
130 |
131 |
`
132 | ).join('')}
133 |
134 |
146 | `
147 | }
148 |
149 | module.exports = async function get(req, res, next) {
150 | var {user, id} = req.params
151 | var url = `https://api.github.com/gists/${id}`
152 | var gist = await fetchCache(url, 'json')
153 | var html = await generateHTML(user, id, gist, req.query)
154 |
155 | res.writeHead(200, {'Content-Type': 'text/html'})
156 | res.end(html)
157 | }
158 |
--------------------------------------------------------------------------------
/routes/raw.js:
--------------------------------------------------------------------------------
1 | const fetch = require("node-fetch");
2 | const fetchCache = require("./../lib/fetch-cache");
3 | const mime = require("mime-types");
4 |
5 | module.exports = async function get(req, res, next) {
6 | const { user, id } = req.params;
7 | const file = req.params.file || 'index.html';
8 |
9 | const url = `https://gist.githubusercontent.com/${user}/${id}/raw/${file}`;
10 | try {
11 | const type = mime.lookup(file) || '';
12 | if (type.match(/^image/)) {
13 | fetch(url).then(async (resp) => {
14 | resp.headers.forEach((v, n) => res.setHeader(n, v));
15 | resp.body.pipe(res);
16 | });
17 | } else {
18 | let text = await fetchCache(url, "text");
19 | if (file.includes(".html")) text = text.replace(/http:\/\//g, "//");
20 |
21 | res.writeHead("200", {
22 | "Content-Type": type,
23 | "Cache-Control": "public, max-age=" + 1000 * 60,
24 | });
25 | res.end(text);
26 | }
27 | } catch (e) {
28 | console.log("missing", e);
29 | res.writeHead("404");
30 | res.end("");
31 | }
32 | };
33 |
--------------------------------------------------------------------------------
/routes/user.js:
--------------------------------------------------------------------------------
1 | var fetchCache = require('./../lib/fetch-cache')
2 | var io = require('indian-ocean')
3 | var _ = require('underscore')
4 | var d3 = require('d3')
5 |
6 | var e = _.escape
7 |
8 | async function dlGists(user, token='', maxPages=11){
9 | var responces = []
10 | var responce = null
11 | var page = 1
12 | var perPage = maxPages == 11 ? 100 : 10
13 | do {
14 | var url = `https://api.github.com/users/${user}/gists?page=${page}&per_page=${perPage}`
15 | var responce = await fetchCache(url, 'json', token)
16 | responces.push(responce)
17 | page++
18 | } while (responce.length == 100 && page < maxPages)
19 |
20 | return _.flatten(responces)
21 | .map(({id, description, public}) => ({id, description, public}))
22 | .filter(d => d.id)
23 | .filter((d) => !d.description?.match(/unlisted/i));
24 | }
25 |
26 | async function getGists(user, token){
27 | var path = __dirname + '/../usercache/' + user + token + '.csv'
28 |
29 | var cachedGists = []
30 | var maxPages = 0
31 | try {
32 | cachedGists = io.readDataSync(path)
33 | cachedGists.forEach(d => d.public = d.public == 'true')
34 | } catch (e) {
35 | maxPages = 11
36 | }
37 |
38 | // misses gists if someone makes a 10+ gists between caches
39 | var gists = await dlGists(user, token, maxPages)
40 |
41 | var isId = {}
42 | gists.forEach(d => isId[d.id] = true)
43 |
44 | cachedGists.forEach(d => isId[d.id] ? '' : gists.push(d))
45 |
46 | // download & save full list of gists after making request
47 | !(async function(){
48 | var currentGists = await dlGists(user, token)
49 | if (currentGists.length > 0) io.writeData(path, currentGists, d => d)
50 | })()
51 |
52 | return gists
53 | }
54 |
55 | function generateHTML(user, gists){
56 | var title = `blocks by ${e(user)}`
57 | var titleURL = `blocks by ${e(user)}`
58 |
59 | return `
60 |
61 |
62 |
63 |
64 | ${title}
65 | ${titleURL}
66 |
67 |
76 | `
77 | }
78 |
79 | module.exports = async function get(req, res, next) {
80 | var user = req.params.user
81 | var token = req.query.token || ''
82 | var gists = await getGists(req.params.user, token)
83 |
84 | // redirect if user doesn't exist and there's a gist id with their user name
85 | // /397f1b0905400b83fcea4008fb4ccdb1 -> /1wheel/397f1b0905400b83fcea4008fb4ccdb1
86 | if (!gists.length){
87 | var url = `https://api.github.com/gists/${user}`
88 | var gist = await fetchCache(url, 'json')
89 |
90 | if (gist && gist.owner){
91 | res.writeHead(301, {Location: `/${gist.owner.login}/${user}`})
92 | return res.end('')
93 | }
94 | }
95 |
96 | var html = generateHTML(user, gists)
97 | res.writeHead(200, {'Content-Type': 'text/html'})
98 | res.end(html)
99 | }
100 |
--------------------------------------------------------------------------------
/static/github-gist.min.css:
--------------------------------------------------------------------------------
1 | .hljs{display:block;background:white;padding:.5em;color:#333333;overflow-x:auto}.hljs-comment,.hljs-meta{color:#969896}.hljs-variable,.hljs-template-variable,.hljs-strong,.hljs-emphasis,.hljs-quote{color:#df5000}.hljs-keyword,.hljs-selector-tag,.hljs-type{color:#d73a49}.hljs-literal,.hljs-symbol,.hljs-bullet,.hljs-attribute{color:#0086b3}.hljs-section,.hljs-name{color:#63a35c}.hljs-tag{color:#333333}.hljs-title,.hljs-attr,.hljs-selector-id,.hljs-selector-class,.hljs-selector-attr,.hljs-selector-pseudo{color:#6f42c1}.hljs-addition{color:#55a532;background-color:#eaffea}.hljs-deletion{color:#bd2c00;background-color:#ffecec}.hljs-link{text-decoration:underline}.hljs-number{color:#005cc5}.hljs-string{color:#032f62}
--------------------------------------------------------------------------------
/static/highlight.min.js:
--------------------------------------------------------------------------------
1 | /*! highlight.js v9.15.10 | BSD3 License | git.io/hljslicense */
2 | !function(e){var t="object"==typeof window&&window||"object"==typeof self&&self;"undefined"==typeof exports||exports.nodeType?t&&(t.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return t.hljs})):e(exports)}(function(n){var d=[],o=Object.keys,h={},c={},t=/^(no-?highlight|plain|text)$/i,l=/\blang(?:uage)?-([\w-]+)\b/i,r=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,a={case_insensitive:"cI",lexemes:"l",contains:"c",keywords:"k",subLanguage:"sL",className:"cN",begin:"b",beginKeywords:"bK",end:"e",endsWithParent:"eW",illegal:"i",excludeBegin:"eB",excludeEnd:"eE",returnBegin:"rB",returnEnd:"rE",relevance:"r",variants:"v",IDENT_RE:"IR",UNDERSCORE_IDENT_RE:"UIR",NUMBER_RE:"NR",C_NUMBER_RE:"CNR",BINARY_NUMBER_RE:"BNR",RE_STARTERS_RE:"RSR",BACKSLASH_ESCAPE:"BE",APOS_STRING_MODE:"ASM",QUOTE_STRING_MODE:"QSM",PHRASAL_WORDS_MODE:"PWM",C_LINE_COMMENT_MODE:"CLCM",C_BLOCK_COMMENT_MODE:"CBCM",HASH_COMMENT_MODE:"HCM",NUMBER_MODE:"NM",C_NUMBER_MODE:"CNM",BINARY_NUMBER_MODE:"BNM",CSS_NUMBER_MODE:"CSSNM",REGEXP_MODE:"RM",TITLE_MODE:"TM",UNDERSCORE_TITLE_MODE:"UTM",COMMENT:"C",beginRe:"bR",endRe:"eR",illegalRe:"iR",lexemesRe:"lR",terminators:"t",terminator_end:"tE"},N="",v={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0};function y(e){return e.replace(/&/g,"&").replace(//g,">")}function b(e){return e.nodeName.toLowerCase()}function w(e,t){var r=e&&e.exec(t);return r&&0===r.index}function u(e){return t.test(e)}function p(e){var t,r={},a=Array.prototype.slice.call(arguments,1);for(t in e)r[t]=e[t];return a.forEach(function(e){for(t in e)r[t]=e[t]}),r}function m(e){var n=[];return function e(t,r){for(var a=t.firstChild;a;a=a.nextSibling)3===a.nodeType?r+=a.nodeValue.length:1===a.nodeType&&(n.push({event:"start",offset:r,node:a}),r=e(a,r),b(a).match(/br|hr|img|input/)||n.push({event:"stop",offset:r,node:a}));return r}(e,0),n}function i(e){if(a&&!e.langApiRestored){for(var t in e.langApiRestored=!0,a)e[t]&&(e[a[t]]=e[t]);(e.c||[]).concat(e.v||[]).forEach(i)}}function E(s){function l(e){return e&&e.source||e}function c(e,t){return new RegExp(l(e),"m"+(s.cI?"i":"")+(t?"g":""))}!function t(r,e){if(!r.compiled){if(r.compiled=!0,r.k=r.k||r.bK,r.k){function a(r,e){s.cI&&(e=e.toLowerCase()),e.split(" ").forEach(function(e){var t=e.split("|");n[t[0]]=[r,t[1]?Number(t[1]):1]})}var n={};"string"==typeof r.k?a("keyword",r.k):o(r.k).forEach(function(e){a(e,r.k[e])}),r.k=n}r.lR=c(r.l||/\w+/,!0),e&&(r.bK&&(r.b="\\b("+r.bK.split(" ").join("|")+")\\b"),r.b||(r.b=/\B|\b/),r.bR=c(r.b),r.endSameAsBegin&&(r.e=r.b),r.e||r.eW||(r.e=/\B|\b/),r.e&&(r.eR=c(r.e)),r.tE=l(r.e)||"",r.eW&&e.tE&&(r.tE+=(r.e?"|":"")+e.tE)),r.i&&(r.iR=c(r.i)),null==r.r&&(r.r=1),r.c||(r.c=[]),r.c=Array.prototype.concat.apply([],r.c.map(function(e){return function(t){return t.v&&!t.cached_variants&&(t.cached_variants=t.v.map(function(e){return p(t,{v:null},e)})),t.cached_variants||t.eW&&[p(t)]||[t]}("self"===e?r:e)})),r.c.forEach(function(e){t(e,r)}),r.starts&&t(r.starts,e);var i=r.c.map(function(e){return e.bK?"\\.?(?:"+e.b+")\\.?":e.b}).concat([r.tE,r.i]).map(l).filter(Boolean);r.t=i.length?c(function(e,t){for(var r=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./,a=0,n="",i=0;i')+t+(r?"":N):t}function s(){b+=null!=u.sL?function(){var e="string"==typeof u.sL;if(e&&!h[u.sL])return y(p);var t=e?k(u.sL,p,!0,d[u.sL]):x(p,u.sL.length?u.sL:void 0);return 0")+'"');return p+=t,t.length||1}var l=M(e);if(!l)throw new Error('Unknown language: "'+e+'"');E(l);var n,u=r||l,d={},b="";for(n=u;n!==l;n=n.parent)n.cN&&(b=c(n.cN,"",!0)+b);var p="",m=0;try{for(var f,g,_=0;u.t.lastIndex=_,f=u.t.exec(t);)g=a(t.substring(_,f.index),f[0]),_=f.index+g;for(a(t.substr(_)),n=u;n.parent;n=n.parent)n.cN&&(b+=N);return{r:m,value:b,language:e,top:u}}catch(e){if(e.message&&-1!==e.message.indexOf("Illegal"))return{r:0,value:y(t)};throw e}}function x(r,e){e=e||v.languages||o(h);var a={r:0,value:y(r)},n=a;return e.filter(M).filter(_).forEach(function(e){var t=k(e,r,!1);t.language=e,t.r>n.r&&(n=t),t.r>a.r&&(n=a,a=t)}),n.language&&(a.second_best=n),a}function f(e){return v.tabReplace||v.useBR?e.replace(r,function(e,t){return v.useBR&&"\n"===e?"
":v.tabReplace?t.replace(/\t/g,v.tabReplace):""}):e}function s(e){var t,r,a,n,i,s=function(e){var t,r,a,n,i=e.className+" ";if(i+=e.parentNode?e.parentNode.className:"",r=l.exec(i))return M(r[1])?r[1]:"no-highlight";for(t=0,a=(i=i.split(/\s+/)).length;t/g,"\n"):t=e,i=t.textContent,a=s?k(s,i,!0):x(i),(r=m(t)).length&&((n=document.createElementNS("http://www.w3.org/1999/xhtml","div")).innerHTML=a.value,a.value=function(e,t,r){var a=0,n="",i=[];function s(){return e.length&&t.length?e[0].offset!==t[0].offset?e[0].offset"}function o(e){n+=""+b(e)+">"}function l(e){("start"===e.event?c:o)(e.node)}for(;e.length||t.length;){var u=s();if(n+=y(r.substring(a,u[0].offset)),a=u[0].offset,u===e){for(i.reverse().forEach(o);l(u.splice(0,1)[0]),(u=s())===e&&u.length&&u[0].offset===a;);i.reverse().forEach(c)}else"start"===u[0].event?i.push(u[0].node):i.pop(),l(u.splice(0,1)[0])}return n+y(r.substr(a))}(r,m(n),i)),a.value=f(a.value),e.innerHTML=a.value,e.className=function(e,t,r){var a=t?c[t]:r,n=[e.trim()];return e.match(/\bhljs\b/)||n.push("hljs"),-1===e.indexOf(a)&&n.push(a),n.join(" ").trim()}(e.className,s,a.language),e.result={language:a.language,re:a.r},a.second_best&&(e.second_best={language:a.second_best.language,re:a.second_best.r}))}function g(){if(!g.called){g.called=!0;var e=document.querySelectorAll("pre code");d.forEach.call(e,s)}}function M(e){return e=(e||"").toLowerCase(),h[e]||h[c[e]]}function _(e){var t=M(e);return t&&!t.disableAutodetect}return n.highlight=k,n.highlightAuto=x,n.fixMarkup=f,n.highlightBlock=s,n.configure=function(e){v=p(v,e)},n.initHighlighting=g,n.initHighlightingOnLoad=function(){addEventListener("DOMContentLoaded",g,!1),addEventListener("load",g,!1)},n.registerLanguage=function(t,e){var r=h[t]=e(n);i(r),r.aliases&&r.aliases.forEach(function(e){c[e]=t})},n.listLanguages=function(){return o(h)},n.getLanguage=M,n.autoDetection=_,n.inherit=p,n.IR=n.IDENT_RE="[a-zA-Z]\\w*",n.UIR=n.UNDERSCORE_IDENT_RE="[a-zA-Z_]\\w*",n.NR=n.NUMBER_RE="\\b\\d+(\\.\\d+)?",n.CNR=n.C_NUMBER_RE="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",n.BNR=n.BINARY_NUMBER_RE="\\b(0b[01]+)",n.RSR=n.RE_STARTERS_RE="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",n.BE=n.BACKSLASH_ESCAPE={b:"\\\\[\\s\\S]",r:0},n.ASM=n.APOS_STRING_MODE={cN:"string",b:"'",e:"'",i:"\\n",c:[n.BE]},n.QSM=n.QUOTE_STRING_MODE={cN:"string",b:'"',e:'"',i:"\\n",c:[n.BE]},n.PWM=n.PHRASAL_WORDS_MODE={b:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},n.C=n.COMMENT=function(e,t,r){var a=n.inherit({cN:"comment",b:e,e:t,c:[]},r||{});return a.c.push(n.PWM),a.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),a},n.CLCM=n.C_LINE_COMMENT_MODE=n.C("//","$"),n.CBCM=n.C_BLOCK_COMMENT_MODE=n.C("/\\*","\\*/"),n.HCM=n.HASH_COMMENT_MODE=n.C("#","$"),n.NM=n.NUMBER_MODE={cN:"number",b:n.NR,r:0},n.CNM=n.C_NUMBER_MODE={cN:"number",b:n.CNR,r:0},n.BNM=n.BINARY_NUMBER_MODE={cN:"number",b:n.BNR,r:0},n.CSSNM=n.CSS_NUMBER_MODE={cN:"number",b:n.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},n.RM=n.REGEXP_MODE={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[n.BE,{b:/\[/,e:/\]/,r:0,c:[n.BE]}]},n.TM=n.TITLE_MODE={cN:"title",b:n.IR,r:0},n.UTM=n.UNDERSCORE_TITLE_MODE={cN:"title",b:n.UIR,r:0},n.METHOD_GUARD={b:"\\.\\s*"+n.UIR,r:0},n.registerLanguage("apache",function(e){var t={cN:"number",b:"[\\$%]\\d+"};return{aliases:["apacheconf"],cI:!0,c:[e.HCM,{cN:"section",b:"?",e:">"},{cN:"attribute",b:/\w+/,r:0,k:{nomarkup:"order deny allow setenv rewriterule rewriteengine rewritecond documentroot sethandler errordocument loadmodule options header listen serverroot servername"},starts:{e:/$/,r:0,k:{literal:"on off all"},c:[{cN:"meta",b:"\\s\\[",e:"\\]$"},{cN:"variable",b:"[\\$%]\\{",e:"\\}",c:["self",t]},t,e.QSM]}}],i:/\S/}}),n.registerLanguage("bash",function(e){var t={cN:"variable",v:[{b:/\$[\w\d#@][\w\d_]*/},{b:/\$\{(.*?)}/}]},r={cN:"string",b:/"/,e:/"/,c:[e.BE,t,{cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]}]};return{aliases:["sh","zsh"],l:/\b-?[a-z\._]+\b/,k:{keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp",_:"-ne -eq -lt -gt -f -d -e -s -l -a"},c:[{cN:"meta",b:/^#![^\n]+sh\s*$/,r:10},{cN:"function",b:/\w[\w\d_]*\s*\(\s*\)\s*\{/,rB:!0,c:[e.inherit(e.TM,{b:/\w[\w\d_]*/})],r:0},e.HCM,r,{cN:"",b:/\\"/},{cN:"string",b:/'/,e:/'/},t]}}),n.registerLanguage("coffeescript",function(e){var t={keyword:"in if for while finally new do return else break catch instanceof throw try this switch continue typeof delete debugger super yield import export from as default await then unless until loop of by when and or is isnt not",literal:"true false null undefined yes no on off",built_in:"npm require console print module global window document"},r="[A-Za-z$_][0-9A-Za-z$_]*",a={cN:"subst",b:/#\{/,e:/}/,k:t},n=[e.BNM,e.inherit(e.CNM,{starts:{e:"(\\s*/)?",r:0}}),{cN:"string",v:[{b:/'''/,e:/'''/,c:[e.BE]},{b:/'/,e:/'/,c:[e.BE]},{b:/"""/,e:/"""/,c:[e.BE,a]},{b:/"/,e:/"/,c:[e.BE,a]}]},{cN:"regexp",v:[{b:"///",e:"///",c:[a,e.HCM]},{b:"//[gim]*",r:0},{b:/\/(?![ *])(\\\/|.)*?\/[gim]*(?=\W|$)/}]},{b:"@"+r},{sL:"javascript",eB:!0,eE:!0,v:[{b:"```",e:"```"},{b:"`",e:"`"}]}];a.c=n;var i=e.inherit(e.TM,{b:r}),s="(\\(.*\\))?\\s*\\B[-=]>",c={cN:"params",b:"\\([^\\(]",rB:!0,c:[{b:/\(/,e:/\)/,k:t,c:["self"].concat(n)}]};return{aliases:["coffee","cson","iced"],k:t,i:/\/\*/,c:n.concat([e.C("###","###"),e.HCM,{cN:"function",b:"^\\s*"+r+"\\s*=\\s*"+s,e:"[-=]>",rB:!0,c:[i,c]},{b:/[:\(,=]\s*/,r:0,c:[{cN:"function",b:s,e:"[-=]>",rB:!0,c:[c]}]},{cN:"class",bK:"class",e:"$",i:/[:="\[\]]/,c:[{bK:"extends",eW:!0,i:/[:="\[\]]/,c:[i]},i]},{b:r+":",e:":",rB:!0,rE:!0,r:0}])}}),n.registerLanguage("cpp",function(e){var t={cN:"keyword",b:"\\b[a-z\\d_]*_t\\b"},r={cN:"string",v:[{b:'(u8?|U|L)?"',e:'"',i:"\\n",c:[e.BE]},{b:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\((?:.|\n)*?\)\1"/},{b:"'\\\\?.",e:"'",i:"."}]},a={cN:"number",v:[{b:"\\b(0b[01']+)"},{b:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{b:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],r:0},n={cN:"meta",b:/#\s*[a-z]+\b/,e:/$/,k:{"meta-keyword":"if else elif endif define undef warning error line pragma ifdef ifndef include"},c:[{b:/\\\n/,r:0},e.inherit(r,{cN:"meta-string"}),{cN:"meta-string",b:/<[^\n>]*>/,e:/$/,i:"\\n"},e.CLCM,e.CBCM]},i=e.IR+"\\s*\\(",s={keyword:"int float while private char catch import module export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using asm case typeid short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignof constexpr decltype noexcept static_assert thread_local restrict _Bool complex _Complex _Imaginary atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong new throw return and or not",built_in:"std string cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap array shared_ptr abort abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr",literal:"true false nullptr NULL"},c=[t,e.CLCM,e.CBCM,a,r];return{aliases:["c","cc","h","c++","h++","hpp","hh","hxx","cxx"],k:s,i:"",c:c.concat([n,{b:"\\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\s*<",e:">",k:s,c:["self",t]},{b:e.IR+"::",k:s},{v:[{b:/=/,e:/;/},{b:/\(/,e:/\)/},{bK:"new throw return else",e:/;/}],k:s,c:c.concat([{b:/\(/,e:/\)/,k:s,c:c.concat(["self"]),r:0}]),r:0},{cN:"function",b:"("+e.IR+"[\\*&\\s]+)+"+i,rB:!0,e:/[{;=]/,eE:!0,k:s,i:/[^\w\s\*&]/,c:[{b:i,rB:!0,c:[e.TM],r:0},{cN:"params",b:/\(/,e:/\)/,k:s,r:0,c:[e.CLCM,e.CBCM,r,a,t,{b:/\(/,e:/\)/,k:s,r:0,c:["self",e.CLCM,e.CBCM,r,a,t]}]},e.CLCM,e.CBCM,n]},{cN:"class",bK:"class struct",e:/[{;:]/,c:[{b:/,e:/>/,c:["self"]},e.TM]}]),exports:{preprocessor:n,strings:r,k:s}}}),n.registerLanguage("cs",function(e){var t={keyword:"abstract as base bool break byte case catch char checked const continue decimal default delegate do double enum event explicit extern finally fixed float for foreach goto if implicit in int interface internal is lock long nameof object operator out override params private protected public readonly ref sbyte sealed short sizeof stackalloc static string struct switch this try typeof uint ulong unchecked unsafe ushort using virtual void volatile while add alias ascending async await by descending dynamic equals from get global group into join let on orderby partial remove select set value var where yield",literal:"null false true"},r={cN:"number",v:[{b:"\\b(0b[01']+)"},{b:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{b:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],r:0},a={cN:"string",b:'@"',e:'"',c:[{b:'""'}]},n=e.inherit(a,{i:/\n/}),i={cN:"subst",b:"{",e:"}",k:t},s=e.inherit(i,{i:/\n/}),c={cN:"string",b:/\$"/,e:'"',i:/\n/,c:[{b:"{{"},{b:"}}"},e.BE,s]},o={cN:"string",b:/\$@"/,e:'"',c:[{b:"{{"},{b:"}}"},{b:'""'},i]},l=e.inherit(o,{i:/\n/,c:[{b:"{{"},{b:"}}"},{b:'""'},s]});i.c=[o,c,a,e.ASM,e.QSM,r,e.CBCM],s.c=[l,c,n,e.ASM,e.QSM,r,e.inherit(e.CBCM,{i:/\n/})];var u={v:[o,c,a,e.ASM,e.QSM]},d=e.IR+"(<"+e.IR+"(\\s*,\\s*"+e.IR+")*>)?(\\[\\])?";return{aliases:["csharp","c#"],k:t,i:/::/,c:[e.C("///","$",{rB:!0,c:[{cN:"doctag",v:[{b:"///",r:0},{b:"\x3c!--|--\x3e"},{b:"?",e:">"}]}]}),e.CLCM,e.CBCM,{cN:"meta",b:"#",e:"$",k:{"meta-keyword":"if else elif endif define undef warning error line region endregion pragma checksum"}},u,r,{bK:"class interface",e:/[{;=]/,i:/[^\s:,]/,c:[e.TM,e.CLCM,e.CBCM]},{bK:"namespace",e:/[{;=]/,i:/[^\s:]/,c:[e.inherit(e.TM,{b:"[a-zA-Z](\\.?\\w)*"}),e.CLCM,e.CBCM]},{cN:"meta",b:"^\\s*\\[",eB:!0,e:"\\]",eE:!0,c:[{cN:"meta-string",b:/"/,e:/"/}]},{bK:"new return throw await else",r:0},{cN:"function",b:"("+d+"\\s+)+"+e.IR+"\\s*\\(",rB:!0,e:/\s*[{;=]/,eE:!0,k:t,c:[{b:e.IR+"\\s*\\(",rB:!0,c:[e.TM],r:0},{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,k:t,r:0,c:[u,r,e.CBCM]},e.CLCM,e.CBCM]}]}}),n.registerLanguage("css",function(e){var t={b:/(?:[A-Z\_\.\-]+|--[a-zA-Z0-9_-]+)\s*:/,rB:!0,e:";",eW:!0,c:[{cN:"attribute",b:/\S/,e:":",eE:!0,starts:{eW:!0,eE:!0,c:[{b:/[\w-]+\(/,rB:!0,c:[{cN:"built_in",b:/[\w-]+/},{b:/\(/,e:/\)/,c:[e.ASM,e.QSM]}]},e.CSSNM,e.QSM,e.ASM,e.CBCM,{cN:"number",b:"#[0-9A-Fa-f]+"},{cN:"meta",b:"!important"}]}}]};return{cI:!0,i:/[=\/|'\$]/,c:[e.CBCM,{cN:"selector-id",b:/#[A-Za-z0-9_-]+/},{cN:"selector-class",b:/\.[A-Za-z0-9_-]+/},{cN:"selector-attr",b:/\[/,e:/\]/,i:"$"},{cN:"selector-pseudo",b:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{b:"@(font-face|page)",l:"[a-z-]+",k:"font-face page"},{b:"@",e:"[{;]",i:/:/,c:[{cN:"keyword",b:/\w+/},{b:/\s/,eW:!0,eE:!0,r:0,c:[e.ASM,e.QSM,e.CSSNM]}]},{cN:"selector-tag",b:"[a-zA-Z-][a-zA-Z0-9_-]*",r:0},{b:"{",e:"}",i:/\S/,c:[e.CBCM,t]}]}}),n.registerLanguage("diff",function(e){return{aliases:["patch"],c:[{cN:"meta",r:10,v:[{b:/^@@ +\-\d+,\d+ +\+\d+,\d+ +@@$/},{b:/^\*\*\* +\d+,\d+ +\*\*\*\*$/},{b:/^\-\-\- +\d+,\d+ +\-\-\-\-$/}]},{cN:"comment",v:[{b:/Index: /,e:/$/},{b:/={3,}/,e:/$/},{b:/^\-{3}/,e:/$/},{b:/^\*{3} /,e:/$/},{b:/^\+{3}/,e:/$/},{b:/\*{5}/,e:/\*{5}$/}]},{cN:"addition",b:"^\\+",e:"$"},{cN:"deletion",b:"^\\-",e:"$"},{cN:"addition",b:"^\\!",e:"$"}]}}),n.registerLanguage("http",function(e){var t="HTTP/[0-9\\.]+";return{aliases:["https"],i:"\\S",c:[{b:"^"+t,e:"$",c:[{cN:"number",b:"\\b\\d{3}\\b"}]},{b:"^[A-Z]+ (.*?) "+t+"$",rB:!0,e:"$",c:[{cN:"string",b:" ",e:" ",eB:!0,eE:!0},{b:t},{cN:"keyword",b:"[A-Z]+"}]},{cN:"attribute",b:"^\\w",e:": ",eE:!0,i:"\\n|\\s|=",starts:{e:"$",r:0}},{b:"\\n\\n",starts:{sL:[],eW:!0}}]}}),n.registerLanguage("ini",function(e){var t={cN:"string",c:[e.BE],v:[{b:"'''",e:"'''",r:10},{b:'"""',e:'"""',r:10},{b:'"',e:'"'},{b:"'",e:"'"}]};return{aliases:["toml"],cI:!0,i:/\S/,c:[e.C(";","$"),e.HCM,{cN:"section",b:/^\s*\[+/,e:/\]+/},{b:/^[a-z0-9\[\]_\.-]+\s*=\s*/,e:"$",rB:!0,c:[{cN:"attr",b:/[a-z0-9\[\]_\.-]+/},{b:/=/,eW:!0,r:0,c:[e.C(";","$"),e.HCM,{cN:"literal",b:/\bon|off|true|false|yes|no\b/},{cN:"variable",v:[{b:/\$[\w\d"][\w\d_]*/},{b:/\$\{(.*?)}/}]},t,{cN:"number",b:/([\+\-]+)?[\d]+_[\d_]+/},e.NM]}]}]}}),n.registerLanguage("java",function(e){var t="false synchronized int abstract float private char boolean var static null if const for true while long strictfp finally protected import native final void enum else break transient catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private module requires exports do",r={cN:"number",b:"\\b(0[bB]([01]+[01_]+[01]+|[01]+)|0[xX]([a-fA-F0-9]+[a-fA-F0-9_]+[a-fA-F0-9]+|[a-fA-F0-9]+)|(([\\d]+[\\d_]+[\\d]+|[\\d]+)(\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))?|\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))([eE][-+]?\\d+)?)[lLfF]?",r:0};return{aliases:["jsp"],k:t,i:/<\/|#/,c:[e.C("/\\*\\*","\\*/",{r:0,c:[{b:/\w+@/,r:0},{cN:"doctag",b:"@[A-Za-z]+"}]}),e.CLCM,e.CBCM,e.ASM,e.QSM,{cN:"class",bK:"class interface",e:/[{;=]/,eE:!0,k:"class interface",i:/[:"\[\]]/,c:[{bK:"extends implements"},e.UTM]},{bK:"new throw return else",r:0},{cN:"function",b:"([À-ʸa-zA-Z_$][À-ʸa-zA-Z_$0-9]*(<[À-ʸa-zA-Z_$][À-ʸa-zA-Z_$0-9]*(\\s*,\\s*[À-ʸa-zA-Z_$][À-ʸa-zA-Z_$0-9]*)*>)?\\s+)+"+e.UIR+"\\s*\\(",rB:!0,e:/[{;=]/,eE:!0,k:t,c:[{b:e.UIR+"\\s*\\(",rB:!0,r:0,c:[e.UTM]},{cN:"params",b:/\(/,e:/\)/,k:t,r:0,c:[e.ASM,e.QSM,e.CNM,e.CBCM]},e.CLCM,e.CBCM]},r,{cN:"meta",b:"@[A-Za-z]+"}]}}),n.registerLanguage("javascript",function(e){var t="[A-Za-z$_][0-9A-Za-z$_]*",r={keyword:"in of if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const export super debugger as async await static import from as",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect Promise"},a={cN:"number",v:[{b:"\\b(0[bB][01]+)"},{b:"\\b(0[oO][0-7]+)"},{b:e.CNR}],r:0},n={cN:"subst",b:"\\$\\{",e:"\\}",k:r,c:[]},i={b:"html`",e:"",starts:{e:"`",rE:!1,c:[e.BE,n],sL:"xml"}},s={b:"css`",e:"",starts:{e:"`",rE:!1,c:[e.BE,n],sL:"css"}},c={cN:"string",b:"`",e:"`",c:[e.BE,n]};n.c=[e.ASM,e.QSM,i,s,c,a,e.RM];var o=n.c.concat([e.CBCM,e.CLCM]);return{aliases:["js","jsx"],k:r,c:[{cN:"meta",r:10,b:/^\s*['"]use (strict|asm)['"]/},{cN:"meta",b:/^#!/,e:/$/},e.ASM,e.QSM,i,s,c,e.CLCM,e.CBCM,a,{b:/[{,]\s*/,r:0,c:[{b:t+"\\s*:",rB:!0,r:0,c:[{cN:"attr",b:t,r:0}]}]},{b:"("+e.RSR+"|\\b(case|return|throw)\\b)\\s*",k:"return throw case",c:[e.CLCM,e.CBCM,e.RM,{cN:"function",b:"(\\(.*?\\)|"+t+")\\s*=>",rB:!0,e:"\\s*=>",c:[{cN:"params",v:[{b:t},{b:/\(\s*\)/},{b:/\(/,e:/\)/,eB:!0,eE:!0,k:r,c:o}]}]},{cN:"",b:/\s/,e:/\s*/,skip:!0},{b:/,e:/(\/[A-Za-z0-9\\._:-]+|[A-Za-z0-9\\._:-]+\/)>/,sL:"xml",c:[{b:/<[A-Za-z0-9\\._:-]+\s*\/>/,skip:!0},{b:/<[A-Za-z0-9\\._:-]+/,e:/(\/[A-Za-z0-9\\._:-]+|[A-Za-z0-9\\._:-]+\/)>/,skip:!0,c:[{b:/<[A-Za-z0-9\\._:-]+\s*\/>/,skip:!0},"self"]}]}],r:0},{cN:"function",bK:"function",e:/\{/,eE:!0,c:[e.inherit(e.TM,{b:t}),{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,c:o}],i:/\[|%/},{b:/\$[(.]/},e.METHOD_GUARD,{cN:"class",bK:"class",e:/[{;=]/,eE:!0,i:/[:"\[\]]/,c:[{bK:"extends"},e.UTM]},{bK:"constructor get set",e:/\{/,eE:!0}],i:/#(?!!)/}}),n.registerLanguage("json",function(e){var t={literal:"true false null"},r=[e.QSM,e.CNM],a={e:",",eW:!0,eE:!0,c:r,k:t},n={b:"{",e:"}",c:[{cN:"attr",b:/"/,e:/"/,c:[e.BE],i:"\\n"},e.inherit(a,{b:/:/})],i:"\\S"},i={b:"\\[",e:"\\]",c:[e.inherit(a)],i:"\\S"};return r.splice(r.length,0,n,i),{c:r,k:t,i:"\\S"}}),n.registerLanguage("makefile",function(e){var t={cN:"variable",v:[{b:"\\$\\("+e.UIR+"\\)",c:[e.BE]},{b:/\$[@%\^\+\*]/}]},r={cN:"string",b:/"/,e:/"/,c:[e.BE,t]},a={cN:"variable",b:/\$\([\w-]+\s/,e:/\)/,k:{built_in:"subst patsubst strip findstring filter filter-out sort word wordlist firstword lastword dir notdir suffix basename addsuffix addprefix join wildcard realpath abspath error warning shell origin flavor foreach if or and call eval file value"},c:[t]},n={b:"^"+e.UIR+"\\s*[:+?]?=",i:"\\n",rB:!0,c:[{b:"^"+e.UIR,e:"[:+?]?=",eE:!0}]},i={cN:"section",b:/^[^\s]+:/,e:/$/,c:[t]};return{aliases:["mk","mak"],k:"define endef undefine ifdef ifndef ifeq ifneq else endif include -include sinclude override export unexport private vpath",l:/[\w-]+/,c:[e.HCM,t,r,a,n,{cN:"meta",b:/^\.PHONY:/,e:/$/,k:{"meta-keyword":".PHONY"},l:/[\.\w]+/},i]}}),n.registerLanguage("xml",function(e){var t={eW:!0,i:/,r:0,c:[{cN:"attr",b:"[A-Za-z0-9\\._:-]+",r:0},{b:/=\s*/,r:0,c:[{cN:"string",endsParent:!0,v:[{b:/"/,e:/"/},{b:/'/,e:/'/},{b:/[^\s"'=<>`]+/}]}]}]};return{aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf"],cI:!0,c:[{cN:"meta",b:"",r:10,c:[{b:"\\[",e:"\\]"}]},e.C("\x3c!--","--\x3e",{r:10}),{b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{cN:"meta",b:/<\?xml/,e:/\?>/,r:10},{b:/<\?(php)?/,e:/\?>/,sL:"php",c:[{b:"/\\*",e:"\\*/",skip:!0},{b:'b"',e:'"',skip:!0},{b:"b'",e:"'",skip:!0},e.inherit(e.ASM,{i:null,cN:null,c:null,skip:!0}),e.inherit(e.QSM,{i:null,cN:null,c:null,skip:!0})]},{cN:"tag",b:"",rE:!0,sL:["css","xml"]}},{cN:"tag",b:"