From 9ab86458a14561b41800754c3f1a360e96690630 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ari=20Perkki=C3=B6?= Date: Thu, 8 Aug 2024 14:14:16 +0300 Subject: [PATCH] feat(runtime): add `preview.pathname` --- .../content/docs/reference/configuration.mdx | 20 +- packages/runtime/coverage/base.css | 224 +++ packages/runtime/coverage/block-navigation.js | 87 + packages/runtime/coverage/clover.xml | 1565 +++++++++++++++ packages/runtime/coverage/coverage-final.json | 20 + packages/runtime/coverage/favicon.png | Bin 0 -> 445 bytes packages/runtime/coverage/index.html | 176 ++ packages/runtime/coverage/prettify.css | 1 + packages/runtime/coverage/prettify.js | 2 + .../runtime/coverage/sort-arrow-sprite.png | Bin 0 -> 138 bytes packages/runtime/coverage/sorter.js | 196 ++ packages/runtime/coverage/src/index.html | 161 ++ packages/runtime/coverage/src/index.ts.html | 100 + .../runtime/coverage/src/lesson-files.ts.html | 613 ++++++ .../runtime/coverage/src/store/editor.ts.html | 499 +++++ .../runtime/coverage/src/store/index.html | 161 ++ .../runtime/coverage/src/store/index.ts.html | 1174 ++++++++++++ .../coverage/src/store/previews.ts.html | 400 ++++ .../coverage/src/store/terminal.ts.html | 571 ++++++ packages/runtime/coverage/src/tasks.ts.html | 262 +++ .../coverage/src/tutorial-runner.ts.html | 1690 +++++++++++++++++ .../runtime/coverage/src/utils/index.html | 146 ++ .../coverage/src/utils/promises.ts.html | 187 ++ .../coverage/src/utils/support.ts.html | 163 ++ .../coverage/src/utils/terminal.ts.html | 157 ++ .../coverage/src/webcontainer/command.ts.html | 337 ++++ .../coverage/src/webcontainer/index.html | 206 ++ .../coverage/src/webcontainer/index.ts.html | 97 + .../src/webcontainer/on-demand-boot.ts.html | 247 +++ .../src/webcontainer/preview-info.ts.html | 208 ++ .../coverage/src/webcontainer/shell.ts.html | 313 +++ .../coverage/src/webcontainer/steps.ts.html | 250 +++ .../src/webcontainer/terminal-config.ts.html | 859 +++++++++ .../src/webcontainer/utils/files.ts.html | 403 ++++ .../src/webcontainer/utils/index.html | 116 ++ packages/runtime/src/store/previews.ts | 25 +- .../src/webcontainer/preview-info.spec.ts | 39 +- .../runtime/src/webcontainer/preview-info.ts | 6 + .../1-basics/1-introduction/2-foo/content.mdx | 5 +- .../src/templates/default/src/index.js | 2 +- packages/types/src/schemas/common.ts | 7 +- 41 files changed, 11670 insertions(+), 25 deletions(-) create mode 100644 packages/runtime/coverage/base.css create mode 100644 packages/runtime/coverage/block-navigation.js create mode 100644 packages/runtime/coverage/clover.xml create mode 100644 packages/runtime/coverage/coverage-final.json create mode 100644 packages/runtime/coverage/favicon.png create mode 100644 packages/runtime/coverage/index.html create mode 100644 packages/runtime/coverage/prettify.css create mode 100644 packages/runtime/coverage/prettify.js create mode 100644 packages/runtime/coverage/sort-arrow-sprite.png create mode 100644 packages/runtime/coverage/sorter.js create mode 100644 packages/runtime/coverage/src/index.html create mode 100644 packages/runtime/coverage/src/index.ts.html create mode 100644 packages/runtime/coverage/src/lesson-files.ts.html create mode 100644 packages/runtime/coverage/src/store/editor.ts.html create mode 100644 packages/runtime/coverage/src/store/index.html create mode 100644 packages/runtime/coverage/src/store/index.ts.html create mode 100644 packages/runtime/coverage/src/store/previews.ts.html create mode 100644 packages/runtime/coverage/src/store/terminal.ts.html create mode 100644 packages/runtime/coverage/src/tasks.ts.html create mode 100644 packages/runtime/coverage/src/tutorial-runner.ts.html create mode 100644 packages/runtime/coverage/src/utils/index.html create mode 100644 packages/runtime/coverage/src/utils/promises.ts.html create mode 100644 packages/runtime/coverage/src/utils/support.ts.html create mode 100644 packages/runtime/coverage/src/utils/terminal.ts.html create mode 100644 packages/runtime/coverage/src/webcontainer/command.ts.html create mode 100644 packages/runtime/coverage/src/webcontainer/index.html create mode 100644 packages/runtime/coverage/src/webcontainer/index.ts.html create mode 100644 packages/runtime/coverage/src/webcontainer/on-demand-boot.ts.html create mode 100644 packages/runtime/coverage/src/webcontainer/preview-info.ts.html create mode 100644 packages/runtime/coverage/src/webcontainer/shell.ts.html create mode 100644 packages/runtime/coverage/src/webcontainer/steps.ts.html create mode 100644 packages/runtime/coverage/src/webcontainer/terminal-config.ts.html create mode 100644 packages/runtime/coverage/src/webcontainer/utils/files.ts.html create mode 100644 packages/runtime/coverage/src/webcontainer/utils/index.html diff --git a/docs/tutorialkit.dev/src/content/docs/reference/configuration.mdx b/docs/tutorialkit.dev/src/content/docs/reference/configuration.mdx index dbf7af7b..ee8b6e1b 100644 --- a/docs/tutorialkit.dev/src/content/docs/reference/configuration.mdx +++ b/docs/tutorialkit.dev/src/content/docs/reference/configuration.mdx @@ -91,18 +91,32 @@ Configure whether or not the editor should be rendered. If an object is provided ##### `previews` Configure which ports should be used for the previews allowing you to align the behavior with your demo application's dev server setup. If not specified, the lowest port will be used. -You can optionally provide these as an array of tuples where the first element is the port number and the second is the title of the preview, or as an object. The `Preview` type has the following shape: ```ts -type Preview = string +type Preview = + | number + | string | [port: number, title: string] - | { port: number, title: string } + | [port: number, title: string, pathname: string] + | { port: number, title: string, pathname?: string } ``` +Example value: + +```yaml +previews: + - 3000 # Preview is on :3000/ + - "3001/docs" # Preview is on :3001/docs/ + - [3002, "Dev Server"] # Preview is on :3002/. Displayed title is "Dev Server". + - [3003, "Dev Server", "/docs"] # Preview is on :3003/docs/. Displayed title is "Dev Server". + - { port: 3004, title: "Dev Server" } # Preview is on :3004/. Displayed title is "Dev Server". + - { port: 3005, title: "Dev Server", pathname: "/docs" } # Preview is on :3005/docs/. Displayed title is "Dev Server". +``` + ##### `mainCommand` The main command to be executed. This command will run after the `prepareCommands`. diff --git a/packages/runtime/coverage/base.css b/packages/runtime/coverage/base.css new file mode 100644 index 00000000..f418035b --- /dev/null +++ b/packages/runtime/coverage/base.css @@ -0,0 +1,224 @@ +body, html { + margin:0; padding: 0; + height: 100%; +} +body { + font-family: Helvetica Neue, Helvetica, Arial; + font-size: 14px; + color:#333; +} +.small { font-size: 12px; } +*, *:after, *:before { + -webkit-box-sizing:border-box; + -moz-box-sizing:border-box; + box-sizing:border-box; + } +h1 { font-size: 20px; margin: 0;} +h2 { font-size: 14px; } +pre { + font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; + margin: 0; + padding: 0; + -moz-tab-size: 2; + -o-tab-size: 2; + tab-size: 2; +} +a { color:#0074D9; text-decoration:none; } +a:hover { text-decoration:underline; } +.strong { font-weight: bold; } +.space-top1 { padding: 10px 0 0 0; } +.pad2y { padding: 20px 0; } +.pad1y { padding: 10px 0; } +.pad2x { padding: 0 20px; } +.pad2 { padding: 20px; } +.pad1 { padding: 10px; } +.space-left2 { padding-left:55px; } +.space-right2 { padding-right:20px; } +.center { text-align:center; } +.clearfix { display:block; } +.clearfix:after { + content:''; + display:block; + height:0; + clear:both; + visibility:hidden; + } +.fl { float: left; } +@media only screen and (max-width:640px) { + .col3 { width:100%; max-width:100%; } + .hide-mobile { display:none!important; } +} + +.quiet { + color: #7f7f7f; + color: rgba(0,0,0,0.5); +} +.quiet a { opacity: 0.7; } + +.fraction { + font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; + font-size: 10px; + color: #555; + background: #E8E8E8; + padding: 4px 5px; + border-radius: 3px; + vertical-align: middle; +} + +div.path a:link, div.path a:visited { color: #333; } +table.coverage { + border-collapse: collapse; + margin: 10px 0 0 0; + padding: 0; +} + +table.coverage td { + margin: 0; + padding: 0; + vertical-align: top; +} +table.coverage td.line-count { + text-align: right; + padding: 0 5px 0 20px; +} +table.coverage td.line-coverage { + text-align: right; + padding-right: 10px; + min-width:20px; +} + +table.coverage td span.cline-any { + display: inline-block; + padding: 0 5px; + width: 100%; +} +.missing-if-branch { + display: inline-block; + margin-right: 5px; + border-radius: 3px; + position: relative; + padding: 0 4px; + background: #333; + color: yellow; +} + +.skip-if-branch { + display: none; + margin-right: 10px; + position: relative; + padding: 0 4px; + background: #ccc; + color: white; +} +.missing-if-branch .typ, .skip-if-branch .typ { + color: inherit !important; +} +.coverage-summary { + border-collapse: collapse; + width: 100%; +} +.coverage-summary tr { border-bottom: 1px solid #bbb; } +.keyline-all { border: 1px solid #ddd; } +.coverage-summary td, .coverage-summary th { padding: 10px; } +.coverage-summary tbody { border: 1px solid #bbb; } +.coverage-summary td { border-right: 1px solid #bbb; } +.coverage-summary td:last-child { border-right: none; } +.coverage-summary th { + text-align: left; + font-weight: normal; + white-space: nowrap; +} +.coverage-summary th.file { border-right: none !important; } +.coverage-summary th.pct { } +.coverage-summary th.pic, +.coverage-summary th.abs, +.coverage-summary td.pct, +.coverage-summary td.abs { text-align: right; } +.coverage-summary td.file { white-space: nowrap; } +.coverage-summary td.pic { min-width: 120px !important; } +.coverage-summary tfoot td { } + +.coverage-summary .sorter { + height: 10px; + width: 7px; + display: inline-block; + margin-left: 0.5em; + background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; +} +.coverage-summary .sorted .sorter { + background-position: 0 -20px; +} +.coverage-summary .sorted-desc .sorter { + background-position: 0 -10px; +} +.status-line { height: 10px; } +/* yellow */ +.cbranch-no { background: yellow !important; color: #111; } +/* dark red */ +.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 } +.low .chart { border:1px solid #C21F39 } +.highlighted, +.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{ + background: #C21F39 !important; +} +/* medium red */ +.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE } +/* light red */ +.low, .cline-no { background:#FCE1E5 } +/* light green */ +.high, .cline-yes { background:rgb(230,245,208) } +/* medium green */ +.cstat-yes { background:rgb(161,215,106) } +/* dark green */ +.status-line.high, .high .cover-fill { background:rgb(77,146,33) } +.high .chart { border:1px solid rgb(77,146,33) } +/* dark yellow (gold) */ +.status-line.medium, .medium .cover-fill { background: #f9cd0b; } +.medium .chart { border:1px solid #f9cd0b; } +/* light yellow */ +.medium { background: #fff4c2; } + +.cstat-skip { background: #ddd; color: #111; } +.fstat-skip { background: #ddd; color: #111 !important; } +.cbranch-skip { background: #ddd !important; color: #111; } + +span.cline-neutral { background: #eaeaea; } + +.coverage-summary td.empty { + opacity: .5; + padding-top: 4px; + padding-bottom: 4px; + line-height: 1; + color: #888; +} + +.cover-fill, .cover-empty { + display:inline-block; + height: 12px; +} +.chart { + line-height: 0; +} +.cover-empty { + background: white; +} +.cover-full { + border-right: none !important; +} +pre.prettyprint { + border: none !important; + padding: 0 !important; + margin: 0 !important; +} +.com { color: #999 !important; } +.ignore-none { color: #999; font-weight: normal; } + +.wrapper { + min-height: 100%; + height: auto !important; + height: 100%; + margin: 0 auto -48px; +} +.footer, .push { + height: 48px; +} diff --git a/packages/runtime/coverage/block-navigation.js b/packages/runtime/coverage/block-navigation.js new file mode 100644 index 00000000..cc121302 --- /dev/null +++ b/packages/runtime/coverage/block-navigation.js @@ -0,0 +1,87 @@ +/* eslint-disable */ +var jumpToCode = (function init() { + // Classes of code we would like to highlight in the file view + var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no']; + + // Elements to highlight in the file listing view + var fileListingElements = ['td.pct.low']; + + // We don't want to select elements that are direct descendants of another match + var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > ` + + // Selecter that finds elements on the page to which we can jump + var selector = + fileListingElements.join(', ') + + ', ' + + notSelector + + missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b` + + // The NodeList of matching elements + var missingCoverageElements = document.querySelectorAll(selector); + + var currentIndex; + + function toggleClass(index) { + missingCoverageElements + .item(currentIndex) + .classList.remove('highlighted'); + missingCoverageElements.item(index).classList.add('highlighted'); + } + + function makeCurrent(index) { + toggleClass(index); + currentIndex = index; + missingCoverageElements.item(index).scrollIntoView({ + behavior: 'smooth', + block: 'center', + inline: 'center' + }); + } + + function goToPrevious() { + var nextIndex = 0; + if (typeof currentIndex !== 'number' || currentIndex === 0) { + nextIndex = missingCoverageElements.length - 1; + } else if (missingCoverageElements.length > 1) { + nextIndex = currentIndex - 1; + } + + makeCurrent(nextIndex); + } + + function goToNext() { + var nextIndex = 0; + + if ( + typeof currentIndex === 'number' && + currentIndex < missingCoverageElements.length - 1 + ) { + nextIndex = currentIndex + 1; + } + + makeCurrent(nextIndex); + } + + return function jump(event) { + if ( + document.getElementById('fileSearch') === document.activeElement && + document.activeElement != null + ) { + // if we're currently focused on the search input, we don't want to navigate + return; + } + + switch (event.which) { + case 78: // n + case 74: // j + goToNext(); + break; + case 66: // b + case 75: // k + case 80: // p + goToPrevious(); + break; + } + }; +})(); +window.addEventListener('keydown', jumpToCode); diff --git a/packages/runtime/coverage/clover.xml b/packages/runtime/coverage/clover.xml new file mode 100644 index 00000000..a55afc60 --- /dev/null +++ b/packages/runtime/coverage/clover.xml @@ -0,0 +1,1565 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/runtime/coverage/coverage-final.json b/packages/runtime/coverage/coverage-final.json new file mode 100644 index 00000000..780fda3f --- /dev/null +++ b/packages/runtime/coverage/coverage-final.json @@ -0,0 +1,20 @@ +{"/Users/ari/Git/tutorialkit/packages/runtime/src/index.ts": {"path":"/Users/ari/Git/tutorialkit/packages/runtime/src/index.ts","all":true,"statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":55}}},"s":{"0":0},"branchMap":{"0":{"type":"branch","line":1,"loc":{"start":{"line":1,"column":304},"end":{"line":5,"column":49}},"locations":[{"start":{"line":1,"column":304},"end":{"line":5,"column":49}}]}},"b":{"0":[0]},"fnMap":{"0":{"name":"(empty-report)","decl":{"start":{"line":1,"column":304},"end":{"line":5,"column":49}},"loc":{"start":{"line":1,"column":304},"end":{"line":5,"column":49}},"line":1}},"f":{"0":0}} +,"/Users/ari/Git/tutorialkit/packages/runtime/src/lesson-files.ts": {"path":"/Users/ari/Git/tutorialkit/packages/runtime/src/lesson-files.ts","all":false,"statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":70}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":48}},"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":43}},"11":{"start":{"line":12,"column":0},"end":{"line":12,"column":33}},"12":{"start":{"line":13,"column":0},"end":{"line":13,"column":42}},"13":{"start":{"line":14,"column":0},"end":{"line":14,"column":42}},"14":{"start":{"line":15,"column":0},"end":{"line":15,"column":46}},"16":{"start":{"line":17,"column":0},"end":{"line":17,"column":52}},"17":{"start":{"line":18,"column":0},"end":{"line":18,"column":44}},"18":{"start":{"line":19,"column":0},"end":{"line":19,"column":52}},"19":{"start":{"line":20,"column":0},"end":{"line":20,"column":5}},"20":{"start":{"line":21,"column":0},"end":{"line":21,"column":3}},"22":{"start":{"line":23,"column":0},"end":{"line":23,"column":67}},"23":{"start":{"line":24,"column":0},"end":{"line":24,"column":35}},"24":{"start":{"line":25,"column":0},"end":{"line":25,"column":30}},"25":{"start":{"line":26,"column":0},"end":{"line":26,"column":5}},"27":{"start":{"line":28,"column":0},"end":{"line":28,"column":47}},"29":{"start":{"line":30,"column":0},"end":{"line":30,"column":21}},"31":{"start":{"line":32,"column":0},"end":{"line":32,"column":44}},"32":{"start":{"line":33,"column":0},"end":{"line":33,"column":58}},"33":{"start":{"line":34,"column":0},"end":{"line":34,"column":12}},"34":{"start":{"line":35,"column":0},"end":{"line":35,"column":47}},"35":{"start":{"line":36,"column":0},"end":{"line":36,"column":5}},"37":{"start":{"line":38,"column":0},"end":{"line":38,"column":12}},"38":{"start":{"line":39,"column":0},"end":{"line":39,"column":11}},"39":{"start":{"line":40,"column":0},"end":{"line":40,"column":12}},"40":{"start":{"line":41,"column":0},"end":{"line":41,"column":6}},"41":{"start":{"line":42,"column":0},"end":{"line":42,"column":3}},"43":{"start":{"line":44,"column":0},"end":{"line":44,"column":59}},"44":{"start":{"line":45,"column":0},"end":{"line":45,"column":69}},"46":{"start":{"line":47,"column":0},"end":{"line":47,"column":42}},"47":{"start":{"line":48,"column":0},"end":{"line":48,"column":46}},"48":{"start":{"line":49,"column":0},"end":{"line":49,"column":5}},"50":{"start":{"line":51,"column":0},"end":{"line":51,"column":78}},"51":{"start":{"line":52,"column":0},"end":{"line":52,"column":44}},"52":{"start":{"line":53,"column":0},"end":{"line":53,"column":5}},"54":{"start":{"line":55,"column":0},"end":{"line":55,"column":55}},"56":{"start":{"line":57,"column":0},"end":{"line":57,"column":24}},"57":{"start":{"line":58,"column":0},"end":{"line":58,"column":3}},"59":{"start":{"line":60,"column":0},"end":{"line":60,"column":50}},"60":{"start":{"line":61,"column":0},"end":{"line":61,"column":56}},"61":{"start":{"line":62,"column":0},"end":{"line":62,"column":3}},"63":{"start":{"line":64,"column":0},"end":{"line":64,"column":53}},"64":{"start":{"line":65,"column":0},"end":{"line":65,"column":59}},"65":{"start":{"line":66,"column":0},"end":{"line":66,"column":3}},"67":{"start":{"line":68,"column":0},"end":{"line":68,"column":52}},"68":{"start":{"line":69,"column":0},"end":{"line":69,"column":37}},"70":{"start":{"line":71,"column":0},"end":{"line":71,"column":44}},"71":{"start":{"line":72,"column":0},"end":{"line":72,"column":91}},"73":{"start":{"line":74,"column":0},"end":{"line":74,"column":25}},"74":{"start":{"line":75,"column":0},"end":{"line":75,"column":70}},"75":{"start":{"line":76,"column":0},"end":{"line":76,"column":7}},"77":{"start":{"line":78,"column":0},"end":{"line":78,"column":57}},"79":{"start":{"line":80,"column":0},"end":{"line":80,"column":44}},"81":{"start":{"line":82,"column":0},"end":{"line":82,"column":30}},"83":{"start":{"line":84,"column":0},"end":{"line":84,"column":18}},"84":{"start":{"line":85,"column":0},"end":{"line":85,"column":7}},"86":{"start":{"line":87,"column":0},"end":{"line":87,"column":34}},"87":{"start":{"line":88,"column":0},"end":{"line":88,"column":44}},"89":{"start":{"line":90,"column":0},"end":{"line":90,"column":16}},"90":{"start":{"line":91,"column":0},"end":{"line":91,"column":3}},"92":{"start":{"line":93,"column":0},"end":{"line":93,"column":87}},"94":{"start":{"line":95,"column":0},"end":{"line":95,"column":39}},"95":{"start":{"line":96,"column":0},"end":{"line":96,"column":16}},"96":{"start":{"line":97,"column":0},"end":{"line":97,"column":5}},"98":{"start":{"line":99,"column":0},"end":{"line":99,"column":37}},"100":{"start":{"line":101,"column":0},"end":{"line":101,"column":34}},"101":{"start":{"line":102,"column":0},"end":{"line":102,"column":38}},"102":{"start":{"line":103,"column":0},"end":{"line":103,"column":5}},"104":{"start":{"line":105,"column":0},"end":{"line":105,"column":47}},"106":{"start":{"line":107,"column":0},"end":{"line":107,"column":19}},"107":{"start":{"line":108,"column":0},"end":{"line":108,"column":3}},"109":{"start":{"line":110,"column":0},"end":{"line":110,"column":63}},"110":{"start":{"line":111,"column":0},"end":{"line":111,"column":18}},"112":{"start":{"line":113,"column":0},"end":{"line":113,"column":18}},"113":{"start":{"line":114,"column":0},"end":{"line":114,"column":11}},"114":{"start":{"line":115,"column":0},"end":{"line":115,"column":73}},"116":{"start":{"line":117,"column":0},"end":{"line":117,"column":27}},"117":{"start":{"line":118,"column":0},"end":{"line":118,"column":100}},"118":{"start":{"line":119,"column":0},"end":{"line":119,"column":9}},"120":{"start":{"line":121,"column":0},"end":{"line":121,"column":59}},"122":{"start":{"line":123,"column":0},"end":{"line":123,"column":38}},"124":{"start":{"line":125,"column":0},"end":{"line":125,"column":20}},"125":{"start":{"line":126,"column":0},"end":{"line":126,"column":23}},"126":{"start":{"line":127,"column":0},"end":{"line":127,"column":25}},"127":{"start":{"line":128,"column":0},"end":{"line":128,"column":73}},"128":{"start":{"line":129,"column":0},"end":{"line":129,"column":31}},"130":{"start":{"line":131,"column":0},"end":{"line":131,"column":20}},"131":{"start":{"line":132,"column":0},"end":{"line":132,"column":9}},"132":{"start":{"line":133,"column":0},"end":{"line":133,"column":7}},"134":{"start":{"line":135,"column":0},"end":{"line":135,"column":17}},"136":{"start":{"line":137,"column":0},"end":{"line":137,"column":23}},"137":{"start":{"line":138,"column":0},"end":{"line":138,"column":5}},"138":{"start":{"line":139,"column":0},"end":{"line":139,"column":3}},"139":{"start":{"line":140,"column":0},"end":{"line":140,"column":1}},"141":{"start":{"line":142,"column":0},"end":{"line":142,"column":83}},"142":{"start":{"line":143,"column":0},"end":{"line":143,"column":27}},"144":{"start":{"line":145,"column":0},"end":{"line":145,"column":33}},"145":{"start":{"line":146,"column":0},"end":{"line":146,"column":18}},"146":{"start":{"line":147,"column":0},"end":{"line":147,"column":3}},"148":{"start":{"line":149,"column":0},"end":{"line":149,"column":32}},"149":{"start":{"line":150,"column":0},"end":{"line":150,"column":33}},"151":{"start":{"line":152,"column":0},"end":{"line":152,"column":25}},"153":{"start":{"line":154,"column":0},"end":{"line":154,"column":36}},"154":{"start":{"line":155,"column":0},"end":{"line":155,"column":91}},"155":{"start":{"line":156,"column":0},"end":{"line":156,"column":12}},"156":{"start":{"line":157,"column":0},"end":{"line":157,"column":31}},"157":{"start":{"line":158,"column":0},"end":{"line":158,"column":5}},"159":{"start":{"line":160,"column":0},"end":{"line":160,"column":40}},"160":{"start":{"line":161,"column":0},"end":{"line":161,"column":3}},"162":{"start":{"line":163,"column":0},"end":{"line":163,"column":16}},"163":{"start":{"line":164,"column":0},"end":{"line":164,"column":1}},"165":{"start":{"line":166,"column":0},"end":{"line":166,"column":83}},"166":{"start":{"line":167,"column":0},"end":{"line":167,"column":41}},"167":{"start":{"line":168,"column":0},"end":{"line":168,"column":22}},"168":{"start":{"line":169,"column":0},"end":{"line":169,"column":3}},"170":{"start":{"line":171,"column":0},"end":{"line":171,"column":40}},"171":{"start":{"line":172,"column":0},"end":{"line":172,"column":19}},"172":{"start":{"line":173,"column":0},"end":{"line":173,"column":3}},"174":{"start":{"line":175,"column":0},"end":{"line":175,"column":20}},"175":{"start":{"line":176,"column":0},"end":{"line":176,"column":1}}},"s":{"0":1,"1":1,"2":1,"11":1,"12":6,"13":6,"14":6,"16":6,"17":6,"18":1,"19":1,"20":6,"22":6,"23":2,"24":1,"25":1,"27":1,"29":1,"31":2,"32":0,"33":2,"34":1,"35":1,"37":1,"38":1,"39":1,"40":1,"41":2,"43":6,"44":2,"46":2,"47":0,"48":0,"50":2,"51":0,"52":0,"54":2,"56":2,"57":2,"59":6,"60":2,"61":2,"63":6,"64":1,"65":1,"67":6,"68":2,"70":2,"71":2,"73":2,"74":0,"75":0,"77":2,"79":2,"81":2,"83":2,"84":2,"86":2,"87":2,"89":2,"90":2,"92":6,"94":3,"95":0,"96":0,"98":3,"100":3,"101":0,"102":0,"104":3,"106":3,"107":3,"109":6,"110":4,"112":4,"113":4,"114":4,"116":4,"117":0,"118":0,"120":4,"122":4,"124":4,"125":4,"126":0,"127":0,"128":0,"130":0,"131":0,"132":0,"134":0,"136":0,"137":0,"138":4,"139":6,"141":6,"142":6,"144":6,"145":0,"146":0,"148":6,"149":6,"151":6,"153":6,"154":0,"155":6,"156":6,"157":6,"159":6,"160":6,"162":6,"163":6,"165":1,"166":1,"167":0,"168":0,"170":1,"171":1,"172":1,"174":0,"175":0},"branchMap":{"0":{"type":"branch","line":12,"loc":{"start":{"line":12,"column":7},"end":{"line":140,"column":1}},"locations":[{"start":{"line":12,"column":7},"end":{"line":140,"column":1}}]},"1":{"type":"branch","line":17,"loc":{"start":{"line":17,"column":2},"end":{"line":21,"column":3}},"locations":[{"start":{"line":17,"column":2},"end":{"line":21,"column":3}}]},"2":{"type":"branch","line":18,"loc":{"start":{"line":18,"column":43},"end":{"line":20,"column":5}},"locations":[{"start":{"line":18,"column":43},"end":{"line":20,"column":5}}]},"3":{"type":"branch","line":23,"loc":{"start":{"line":23,"column":2},"end":{"line":42,"column":3}},"locations":[{"start":{"line":23,"column":2},"end":{"line":42,"column":3}}]},"4":{"type":"branch","line":24,"loc":{"start":{"line":24,"column":34},"end":{"line":32,"column":43}},"locations":[{"start":{"line":24,"column":34},"end":{"line":32,"column":43}}]},"5":{"type":"branch","line":32,"loc":{"start":{"line":32,"column":43},"end":{"line":34,"column":11}},"locations":[{"start":{"line":32,"column":43},"end":{"line":34,"column":11}}]},"6":{"type":"branch","line":34,"loc":{"start":{"line":34,"column":4},"end":{"line":41,"column":6}},"locations":[{"start":{"line":34,"column":4},"end":{"line":41,"column":6}}]},"7":{"type":"branch","line":44,"loc":{"start":{"line":44,"column":2},"end":{"line":58,"column":3}},"locations":[{"start":{"line":44,"column":2},"end":{"line":58,"column":3}}]},"8":{"type":"branch","line":47,"loc":{"start":{"line":47,"column":41},"end":{"line":49,"column":5}},"locations":[{"start":{"line":47,"column":41},"end":{"line":49,"column":5}}]},"9":{"type":"branch","line":51,"loc":{"start":{"line":51,"column":13},"end":{"line":51,"column":77}},"locations":[{"start":{"line":51,"column":13},"end":{"line":51,"column":77}}]},"10":{"type":"branch","line":51,"loc":{"start":{"line":51,"column":77},"end":{"line":53,"column":5}},"locations":[{"start":{"line":51,"column":77},"end":{"line":53,"column":5}}]},"11":{"type":"branch","line":60,"loc":{"start":{"line":60,"column":2},"end":{"line":62,"column":3}},"locations":[{"start":{"line":60,"column":2},"end":{"line":62,"column":3}}]},"12":{"type":"branch","line":64,"loc":{"start":{"line":64,"column":2},"end":{"line":66,"column":3}},"locations":[{"start":{"line":64,"column":2},"end":{"line":66,"column":3}}]},"13":{"type":"branch","line":68,"loc":{"start":{"line":68,"column":10},"end":{"line":91,"column":3}},"locations":[{"start":{"line":68,"column":10},"end":{"line":91,"column":3}}]},"14":{"type":"branch","line":69,"loc":{"start":{"line":69,"column":9},"end":{"line":69,"column":35}},"locations":[{"start":{"line":69,"column":9},"end":{"line":69,"column":35}}]},"15":{"type":"branch","line":71,"loc":{"start":{"line":71,"column":25},"end":{"line":85,"column":5}},"locations":[{"start":{"line":71,"column":25},"end":{"line":85,"column":5}}]},"16":{"type":"branch","line":74,"loc":{"start":{"line":74,"column":24},"end":{"line":76,"column":7}},"locations":[{"start":{"line":74,"column":24},"end":{"line":76,"column":7}}]},"17":{"type":"branch","line":93,"loc":{"start":{"line":93,"column":2},"end":{"line":108,"column":3}},"locations":[{"start":{"line":93,"column":2},"end":{"line":108,"column":3}}]},"18":{"type":"branch","line":95,"loc":{"start":{"line":95,"column":38},"end":{"line":97,"column":5}},"locations":[{"start":{"line":95,"column":38},"end":{"line":97,"column":5}}]},"19":{"type":"branch","line":101,"loc":{"start":{"line":101,"column":33},"end":{"line":103,"column":5}},"locations":[{"start":{"line":101,"column":33},"end":{"line":103,"column":5}}]},"20":{"type":"branch","line":110,"loc":{"start":{"line":110,"column":2},"end":{"line":139,"column":3}},"locations":[{"start":{"line":110,"column":2},"end":{"line":139,"column":3}}]},"21":{"type":"branch","line":117,"loc":{"start":{"line":117,"column":26},"end":{"line":119,"column":9}},"locations":[{"start":{"line":117,"column":26},"end":{"line":119,"column":9}}]},"22":{"type":"branch","line":126,"loc":{"start":{"line":126,"column":6},"end":{"line":138,"column":5}},"locations":[{"start":{"line":126,"column":6},"end":{"line":138,"column":5}}]},"23":{"type":"branch","line":142,"loc":{"start":{"line":142,"column":0},"end":{"line":164,"column":1}},"locations":[{"start":{"line":142,"column":0},"end":{"line":164,"column":1}}]},"24":{"type":"branch","line":145,"loc":{"start":{"line":145,"column":32},"end":{"line":147,"column":3}},"locations":[{"start":{"line":145,"column":32},"end":{"line":147,"column":3}}]},"25":{"type":"branch","line":154,"loc":{"start":{"line":154,"column":35},"end":{"line":156,"column":11}},"locations":[{"start":{"line":154,"column":35},"end":{"line":156,"column":11}}]},"26":{"type":"branch","line":166,"loc":{"start":{"line":166,"column":0},"end":{"line":176,"column":1}},"locations":[{"start":{"line":166,"column":0},"end":{"line":176,"column":1}}]},"27":{"type":"branch","line":167,"loc":{"start":{"line":167,"column":40},"end":{"line":169,"column":3}},"locations":[{"start":{"line":167,"column":40},"end":{"line":169,"column":3}}]},"28":{"type":"branch","line":173,"loc":{"start":{"line":173,"column":2},"end":{"line":176,"column":1}},"locations":[{"start":{"line":173,"column":2},"end":{"line":176,"column":1}}]}},"b":{"0":[6],"1":[6],"2":[1],"3":[2],"4":[1],"5":[0],"6":[1],"7":[2],"8":[0],"9":[0],"10":[0],"11":[2],"12":[1],"13":[2],"14":[0],"15":[2],"16":[0],"17":[3],"18":[0],"19":[0],"20":[4],"21":[0],"22":[0],"23":[6],"24":[0],"25":[0],"26":[1],"27":[0],"28":[0]},"fnMap":{"0":{"name":"","decl":{"start":{"line":12,"column":7},"end":{"line":140,"column":1}},"loc":{"start":{"line":12,"column":7},"end":{"line":140,"column":1}},"line":12},"1":{"name":"LessonFilesFetcher","decl":{"start":{"line":17,"column":2},"end":{"line":21,"column":3}},"loc":{"start":{"line":17,"column":2},"end":{"line":21,"column":3}},"line":17},"2":{"name":"invalidate","decl":{"start":{"line":23,"column":2},"end":{"line":42,"column":3}},"loc":{"start":{"line":23,"column":2},"end":{"line":42,"column":3}},"line":23},"3":{"name":"getLessonTemplate","decl":{"start":{"line":44,"column":2},"end":{"line":58,"column":3}},"loc":{"start":{"line":44,"column":2},"end":{"line":58,"column":3}},"line":44},"4":{"name":"getLessonFiles","decl":{"start":{"line":60,"column":2},"end":{"line":62,"column":3}},"loc":{"start":{"line":60,"column":2},"end":{"line":62,"column":3}},"line":60},"5":{"name":"getLessonSolution","decl":{"start":{"line":64,"column":2},"end":{"line":66,"column":3}},"loc":{"start":{"line":64,"column":2},"end":{"line":66,"column":3}},"line":64},"6":{"name":"_fetchTemplate","decl":{"start":{"line":68,"column":10},"end":{"line":91,"column":3}},"loc":{"start":{"line":68,"column":10},"end":{"line":91,"column":3}},"line":68},"7":{"name":"_getFilesFromFilesRefList","decl":{"start":{"line":93,"column":2},"end":{"line":108,"column":3}},"loc":{"start":{"line":93,"column":2},"end":{"line":108,"column":3}},"line":93},"8":{"name":"_fetchFiles","decl":{"start":{"line":110,"column":2},"end":{"line":139,"column":3}},"loc":{"start":{"line":110,"column":2},"end":{"line":139,"column":3}},"line":110},"9":{"name":"convertToFiles","decl":{"start":{"line":142,"column":0},"end":{"line":164,"column":1}},"loc":{"start":{"line":142,"column":0},"end":{"line":164,"column":1}},"line":142},"10":{"name":"getTypeFromFilesRef","decl":{"start":{"line":166,"column":0},"end":{"line":176,"column":1}},"loc":{"start":{"line":166,"column":0},"end":{"line":176,"column":1}},"line":166}},"f":{"0":6,"1":6,"2":2,"3":2,"4":2,"5":1,"6":2,"7":3,"8":4,"9":6,"10":1}} +,"/Users/ari/Git/tutorialkit/packages/runtime/src/tasks.ts": {"path":"/Users/ari/Git/tutorialkit/packages/runtime/src/tasks.ts","all":false,"statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":55}},"9":{"start":{"line":10,"column":0},"end":{"line":10,"column":40}},"31":{"start":{"line":32,"column":0},"end":{"line":32,"column":118}},"32":{"start":{"line":33,"column":0},"end":{"line":33,"column":48}},"34":{"start":{"line":35,"column":0},"end":{"line":35,"column":70}},"35":{"start":{"line":36,"column":0},"end":{"line":36,"column":29}},"37":{"start":{"line":38,"column":0},"end":{"line":38,"column":49}},"39":{"start":{"line":40,"column":0},"end":{"line":40,"column":15}},"40":{"start":{"line":41,"column":0},"end":{"line":41,"column":96}},"41":{"start":{"line":42,"column":0},"end":{"line":42,"column":68}},"42":{"start":{"line":43,"column":0},"end":{"line":43,"column":3}},"44":{"start":{"line":45,"column":0},"end":{"line":45,"column":10}},"45":{"start":{"line":46,"column":0},"end":{"line":46,"column":31}},"46":{"start":{"line":47,"column":0},"end":{"line":47,"column":19}},"47":{"start":{"line":48,"column":0},"end":{"line":48,"column":39}},"48":{"start":{"line":49,"column":0},"end":{"line":49,"column":48}},"49":{"start":{"line":50,"column":0},"end":{"line":50,"column":25}},"50":{"start":{"line":51,"column":0},"end":{"line":51,"column":11}},"52":{"start":{"line":53,"column":0},"end":{"line":53,"column":32}},"53":{"start":{"line":54,"column":0},"end":{"line":54,"column":11}},"54":{"start":{"line":55,"column":0},"end":{"line":55,"column":14}},"55":{"start":{"line":56,"column":0},"end":{"line":56,"column":46}},"56":{"start":{"line":57,"column":0},"end":{"line":57,"column":6}},"57":{"start":{"line":58,"column":0},"end":{"line":58,"column":4}},"58":{"start":{"line":59,"column":0},"end":{"line":59,"column":1}}},"s":{"0":1,"9":1,"31":1,"32":5,"34":5,"35":5,"37":5,"39":5,"40":0,"41":0,"42":0,"44":5,"45":5,"46":2,"47":3,"48":0,"49":0,"50":0,"52":0,"53":3,"54":5,"55":0,"56":0,"57":5,"58":5},"branchMap":{"0":{"type":"branch","line":32,"loc":{"start":{"line":32,"column":7},"end":{"line":59,"column":1}},"locations":[{"start":{"line":32,"column":7},"end":{"line":59,"column":1}}]},"1":{"type":"branch","line":40,"loc":{"start":{"line":40,"column":14},"end":{"line":43,"column":3}},"locations":[{"start":{"line":40,"column":14},"end":{"line":43,"column":3}}]},"2":{"type":"branch","line":46,"loc":{"start":{"line":46,"column":19},"end":{"line":47,"column":19}},"locations":[{"start":{"line":46,"column":19},"end":{"line":47,"column":19}}]},"3":{"type":"branch","line":47,"loc":{"start":{"line":47,"column":8},"end":{"line":54,"column":11}},"locations":[{"start":{"line":47,"column":8},"end":{"line":54,"column":11}}]}},"b":{"0":[5],"1":[0],"2":[2],"3":[3]},"fnMap":{"0":{"name":"newTask","decl":{"start":{"line":32,"column":7},"end":{"line":59,"column":1}},"loc":{"start":{"line":32,"column":7},"end":{"line":59,"column":1}},"line":32},"1":{"name":"abortListener","decl":{"start":{"line":35,"column":24},"end":{"line":35,"column":70}},"loc":{"start":{"line":35,"column":24},"end":{"line":35,"column":70}},"line":35},"2":{"name":"cancel","decl":{"start":{"line":55,"column":4},"end":{"line":57,"column":6}},"loc":{"start":{"line":55,"column":4},"end":{"line":57,"column":6}},"line":55}},"f":{"0":5,"1":0,"2":0}} +,"/Users/ari/Git/tutorialkit/packages/runtime/src/tutorial-runner.ts": {"path":"/Users/ari/Git/tutorialkit/packages/runtime/src/tutorial-runner.ts","all":false,"statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":64}},"3":{"start":{"line":4,"column":0},"end":{"line":4,"column":68}},"4":{"start":{"line":5,"column":0},"end":{"line":5,"column":81}},"5":{"start":{"line":6,"column":0},"end":{"line":6,"column":62}},"6":{"start":{"line":7,"column":0},"end":{"line":7,"column":58}},"7":{"start":{"line":8,"column":0},"end":{"line":8,"column":70}},"55":{"start":{"line":56,"column":0},"end":{"line":56,"column":29}},"56":{"start":{"line":57,"column":0},"end":{"line":57,"column":79}},"57":{"start":{"line":58,"column":0},"end":{"line":58,"column":82}},"58":{"start":{"line":59,"column":0},"end":{"line":59,"column":78}},"59":{"start":{"line":60,"column":0},"end":{"line":60,"column":58}},"60":{"start":{"line":61,"column":0},"end":{"line":61,"column":55}},"61":{"start":{"line":62,"column":0},"end":{"line":62,"column":64}},"62":{"start":{"line":63,"column":0},"end":{"line":63,"column":36}},"63":{"start":{"line":64,"column":0},"end":{"line":64,"column":35}},"66":{"start":{"line":67,"column":0},"end":{"line":67,"column":35}},"67":{"start":{"line":68,"column":0},"end":{"line":68,"column":32}},"69":{"start":{"line":70,"column":0},"end":{"line":70,"column":14}},"70":{"start":{"line":71,"column":0},"end":{"line":71,"column":49}},"71":{"start":{"line":72,"column":0},"end":{"line":72,"column":42}},"72":{"start":{"line":73,"column":0},"end":{"line":73,"column":45}},"73":{"start":{"line":74,"column":0},"end":{"line":74,"column":6}},"84":{"start":{"line":85,"column":0},"end":{"line":85,"column":41}},"85":{"start":{"line":86,"column":0},"end":{"line":86,"column":47}},"86":{"start":{"line":87,"column":0},"end":{"line":87,"column":54}},"89":{"start":{"line":90,"column":0},"end":{"line":90,"column":20}},"90":{"start":{"line":91,"column":0},"end":{"line":91,"column":61}},"91":{"start":{"line":92,"column":0},"end":{"line":92,"column":45}},"92":{"start":{"line":93,"column":0},"end":{"line":93,"column":35}},"93":{"start":{"line":94,"column":0},"end":{"line":94,"column":5}},"94":{"start":{"line":95,"column":0},"end":{"line":95,"column":3}},"96":{"start":{"line":97,"column":0},"end":{"line":97,"column":48}},"97":{"start":{"line":98,"column":0},"end":{"line":98,"column":56}},"98":{"start":{"line":99,"column":0},"end":{"line":99,"column":3}},"106":{"start":{"line":107,"column":0},"end":{"line":107,"column":55}},"107":{"start":{"line":108,"column":0},"end":{"line":108,"column":63}},"109":{"start":{"line":110,"column":0},"end":{"line":110,"column":36}},"110":{"start":{"line":111,"column":0},"end":{"line":111,"column":25}},"111":{"start":{"line":112,"column":0},"end":{"line":112,"column":34}},"113":{"start":{"line":114,"column":0},"end":{"line":114,"column":54}},"115":{"start":{"line":116,"column":0},"end":{"line":116,"column":32}},"117":{"start":{"line":118,"column":0},"end":{"line":118,"column":59}},"119":{"start":{"line":120,"column":0},"end":{"line":120,"column":58}},"120":{"start":{"line":121,"column":0},"end":{"line":121,"column":8}},"121":{"start":{"line":122,"column":0},"end":{"line":122,"column":29}},"122":{"start":{"line":123,"column":0},"end":{"line":123,"column":6}},"123":{"start":{"line":124,"column":0},"end":{"line":124,"column":3}},"130":{"start":{"line":131,"column":0},"end":{"line":131,"column":35}},"131":{"start":{"line":132,"column":0},"end":{"line":132,"column":63}},"133":{"start":{"line":134,"column":0},"end":{"line":134,"column":36}},"134":{"start":{"line":135,"column":0},"end":{"line":135,"column":25}},"135":{"start":{"line":136,"column":0},"end":{"line":136,"column":34}},"137":{"start":{"line":138,"column":0},"end":{"line":138,"column":54}},"139":{"start":{"line":140,"column":0},"end":{"line":140,"column":32}},"141":{"start":{"line":142,"column":0},"end":{"line":142,"column":52}},"143":{"start":{"line":144,"column":0},"end":{"line":144,"column":40}},"144":{"start":{"line":145,"column":0},"end":{"line":145,"column":8}},"145":{"start":{"line":146,"column":0},"end":{"line":146,"column":29}},"146":{"start":{"line":147,"column":0},"end":{"line":147,"column":6}},"147":{"start":{"line":148,"column":0},"end":{"line":148,"column":3}},"159":{"start":{"line":160,"column":0},"end":{"line":160,"column":120}},"160":{"start":{"line":161,"column":0},"end":{"line":161,"column":63}},"162":{"start":{"line":163,"column":0},"end":{"line":163,"column":28}},"163":{"start":{"line":164,"column":0},"end":{"line":164,"column":38}},"164":{"start":{"line":165,"column":0},"end":{"line":165,"column":5}},"166":{"start":{"line":167,"column":0},"end":{"line":167,"column":36}},"167":{"start":{"line":168,"column":0},"end":{"line":168,"column":25}},"168":{"start":{"line":169,"column":0},"end":{"line":169,"column":34}},"170":{"start":{"line":171,"column":0},"end":{"line":171,"column":54}},"172":{"start":{"line":173,"column":0},"end":{"line":173,"column":32}},"174":{"start":{"line":175,"column":0},"end":{"line":175,"column":65}},"176":{"start":{"line":177,"column":0},"end":{"line":177,"column":32}},"178":{"start":{"line":179,"column":0},"end":{"line":179,"column":58}},"179":{"start":{"line":180,"column":0},"end":{"line":180,"column":28}},"180":{"start":{"line":181,"column":0},"end":{"line":181,"column":25}},"181":{"start":{"line":182,"column":0},"end":{"line":182,"column":64}},"182":{"start":{"line":183,"column":0},"end":{"line":183,"column":38}},"183":{"start":{"line":184,"column":0},"end":{"line":184,"column":12}},"184":{"start":{"line":185,"column":0},"end":{"line":185,"column":16}},"185":{"start":{"line":186,"column":0},"end":{"line":186,"column":74}},"186":{"start":{"line":187,"column":0},"end":{"line":187,"column":9}},"188":{"start":{"line":189,"column":0},"end":{"line":189,"column":48}},"189":{"start":{"line":190,"column":0},"end":{"line":190,"column":42}},"191":{"start":{"line":192,"column":0},"end":{"line":192,"column":58}},"192":{"start":{"line":193,"column":0},"end":{"line":193,"column":8}},"193":{"start":{"line":194,"column":0},"end":{"line":194,"column":37}},"194":{"start":{"line":195,"column":0},"end":{"line":195,"column":6}},"196":{"start":{"line":197,"column":0},"end":{"line":197,"column":41}},"197":{"start":{"line":198,"column":0},"end":{"line":198,"column":3}},"212":{"start":{"line":213,"column":0},"end":{"line":213,"column":75}},"213":{"start":{"line":214,"column":0},"end":{"line":214,"column":50}},"214":{"start":{"line":215,"column":0},"end":{"line":215,"column":55}},"215":{"start":{"line":216,"column":0},"end":{"line":216,"column":49}},"216":{"start":{"line":217,"column":0},"end":{"line":217,"column":50}},"218":{"start":{"line":219,"column":0},"end":{"line":219,"column":23}},"219":{"start":{"line":220,"column":0},"end":{"line":220,"column":73}},"220":{"start":{"line":221,"column":0},"end":{"line":221,"column":5}},"222":{"start":{"line":223,"column":0},"end":{"line":223,"column":39}},"223":{"start":{"line":224,"column":0},"end":{"line":224,"column":25}},"229":{"start":{"line":230,"column":0},"end":{"line":230,"column":26}},"231":{"start":{"line":232,"column":0},"end":{"line":232,"column":49}},"232":{"start":{"line":233,"column":0},"end":{"line":233,"column":33}},"233":{"start":{"line":234,"column":0},"end":{"line":234,"column":9}},"235":{"start":{"line":236,"column":0},"end":{"line":236,"column":32}},"237":{"start":{"line":238,"column":0},"end":{"line":238,"column":68}},"239":{"start":{"line":240,"column":0},"end":{"line":240,"column":25}},"248":{"start":{"line":249,"column":0},"end":{"line":249,"column":29}},"249":{"start":{"line":250,"column":0},"end":{"line":250,"column":62}},"250":{"start":{"line":251,"column":0},"end":{"line":251,"column":76}},"252":{"start":{"line":253,"column":0},"end":{"line":253,"column":40}},"253":{"start":{"line":254,"column":0},"end":{"line":254,"column":11}},"255":{"start":{"line":256,"column":0},"end":{"line":256,"column":27}},"256":{"start":{"line":257,"column":0},"end":{"line":257,"column":9}},"259":{"start":{"line":260,"column":0},"end":{"line":260,"column":38}},"261":{"start":{"line":262,"column":0},"end":{"line":262,"column":31}},"262":{"start":{"line":263,"column":0},"end":{"line":263,"column":33}},"263":{"start":{"line":264,"column":0},"end":{"line":264,"column":9}},"265":{"start":{"line":266,"column":0},"end":{"line":266,"column":36}},"267":{"start":{"line":268,"column":0},"end":{"line":268,"column":54}},"269":{"start":{"line":270,"column":0},"end":{"line":270,"column":32}},"271":{"start":{"line":272,"column":0},"end":{"line":272,"column":68}},"272":{"start":{"line":273,"column":0},"end":{"line":273,"column":8}},"273":{"start":{"line":274,"column":0},"end":{"line":274,"column":29}},"274":{"start":{"line":275,"column":0},"end":{"line":275,"column":6}},"275":{"start":{"line":276,"column":0},"end":{"line":276,"column":3}},"280":{"start":{"line":281,"column":0},"end":{"line":281,"column":28}},"281":{"start":{"line":282,"column":0},"end":{"line":282,"column":65}},"282":{"start":{"line":283,"column":0},"end":{"line":283,"column":13}},"283":{"start":{"line":284,"column":0},"end":{"line":284,"column":5}},"285":{"start":{"line":286,"column":0},"end":{"line":286,"column":57}},"286":{"start":{"line":287,"column":0},"end":{"line":287,"column":68}},"287":{"start":{"line":288,"column":0},"end":{"line":288,"column":55}},"289":{"start":{"line":290,"column":0},"end":{"line":290,"column":38}},"291":{"start":{"line":292,"column":0},"end":{"line":292,"column":39}},"292":{"start":{"line":293,"column":0},"end":{"line":293,"column":25}},"293":{"start":{"line":294,"column":0},"end":{"line":294,"column":65}},"295":{"start":{"line":296,"column":0},"end":{"line":296,"column":54}},"297":{"start":{"line":298,"column":0},"end":{"line":298,"column":32}},"299":{"start":{"line":300,"column":0},"end":{"line":300,"column":76}},"300":{"start":{"line":301,"column":0},"end":{"line":301,"column":8}},"301":{"start":{"line":302,"column":0},"end":{"line":302,"column":29}},"302":{"start":{"line":303,"column":0},"end":{"line":303,"column":6}},"303":{"start":{"line":304,"column":0},"end":{"line":304,"column":3}},"311":{"start":{"line":312,"column":0},"end":{"line":312,"column":18}},"312":{"start":{"line":313,"column":0},"end":{"line":313,"column":45}},"315":{"start":{"line":316,"column":0},"end":{"line":316,"column":82}},"316":{"start":{"line":317,"column":0},"end":{"line":317,"column":38}},"317":{"start":{"line":318,"column":0},"end":{"line":318,"column":41}},"318":{"start":{"line":319,"column":0},"end":{"line":319,"column":7}},"319":{"start":{"line":320,"column":0},"end":{"line":320,"column":5}},"322":{"start":{"line":323,"column":0},"end":{"line":323,"column":79}},"323":{"start":{"line":324,"column":0},"end":{"line":324,"column":38}},"324":{"start":{"line":325,"column":0},"end":{"line":325,"column":41}},"325":{"start":{"line":326,"column":0},"end":{"line":326,"column":7}},"326":{"start":{"line":327,"column":0},"end":{"line":327,"column":5}},"328":{"start":{"line":329,"column":0},"end":{"line":329,"column":35}},"329":{"start":{"line":330,"column":0},"end":{"line":330,"column":22}},"331":{"start":{"line":332,"column":0},"end":{"line":332,"column":11}},"332":{"start":{"line":333,"column":0},"end":{"line":333,"column":59}},"333":{"start":{"line":334,"column":0},"end":{"line":334,"column":16}},"336":{"start":{"line":337,"column":0},"end":{"line":337,"column":65}},"337":{"start":{"line":338,"column":0},"end":{"line":338,"column":80}},"338":{"start":{"line":339,"column":0},"end":{"line":339,"column":109}},"339":{"start":{"line":340,"column":0},"end":{"line":340,"column":92}},"341":{"start":{"line":342,"column":0},"end":{"line":342,"column":63}},"342":{"start":{"line":343,"column":0},"end":{"line":343,"column":59}},"343":{"start":{"line":344,"column":0},"end":{"line":344,"column":15}},"344":{"start":{"line":345,"column":0},"end":{"line":345,"column":12}},"345":{"start":{"line":346,"column":0},"end":{"line":346,"column":10}},"346":{"start":{"line":347,"column":0},"end":{"line":347,"column":7}},"347":{"start":{"line":348,"column":0},"end":{"line":348,"column":5}},"349":{"start":{"line":350,"column":0},"end":{"line":350,"column":21}},"350":{"start":{"line":351,"column":0},"end":{"line":351,"column":3}},"352":{"start":{"line":353,"column":0},"end":{"line":353,"column":99}},"353":{"start":{"line":354,"column":0},"end":{"line":354,"column":56}},"355":{"start":{"line":356,"column":0},"end":{"line":356,"column":26}},"357":{"start":{"line":358,"column":0},"end":{"line":358,"column":68}},"358":{"start":{"line":359,"column":0},"end":{"line":359,"column":68}},"360":{"start":{"line":361,"column":0},"end":{"line":361,"column":50}},"362":{"start":{"line":363,"column":0},"end":{"line":363,"column":9}},"363":{"start":{"line":364,"column":0},"end":{"line":364,"column":40}},"365":{"start":{"line":366,"column":0},"end":{"line":366,"column":56}},"368":{"start":{"line":369,"column":0},"end":{"line":369,"column":31}},"370":{"start":{"line":371,"column":0},"end":{"line":371,"column":61}},"371":{"start":{"line":372,"column":0},"end":{"line":372,"column":89}},"373":{"start":{"line":374,"column":0},"end":{"line":374,"column":36}},"374":{"start":{"line":375,"column":0},"end":{"line":375,"column":50}},"375":{"start":{"line":376,"column":0},"end":{"line":376,"column":33}},"376":{"start":{"line":377,"column":0},"end":{"line":377,"column":30}},"377":{"start":{"line":378,"column":0},"end":{"line":378,"column":13}},"379":{"start":{"line":380,"column":0},"end":{"line":380,"column":19}},"380":{"start":{"line":381,"column":0},"end":{"line":381,"column":9}},"382":{"start":{"line":383,"column":0},"end":{"line":383,"column":48}},"383":{"start":{"line":384,"column":0},"end":{"line":384,"column":31}},"384":{"start":{"line":385,"column":0},"end":{"line":385,"column":28}},"385":{"start":{"line":386,"column":0},"end":{"line":386,"column":11}},"388":{"start":{"line":389,"column":0},"end":{"line":389,"column":35}},"389":{"start":{"line":390,"column":0},"end":{"line":390,"column":30}},"390":{"start":{"line":391,"column":0},"end":{"line":391,"column":9}},"392":{"start":{"line":393,"column":0},"end":{"line":393,"column":27}},"394":{"start":{"line":395,"column":0},"end":{"line":395,"column":105}},"396":{"start":{"line":397,"column":0},"end":{"line":397,"column":13}},"397":{"start":{"line":398,"column":0},"end":{"line":398,"column":34}},"398":{"start":{"line":399,"column":0},"end":{"line":399,"column":25}},"399":{"start":{"line":400,"column":0},"end":{"line":400,"column":52}},"400":{"start":{"line":401,"column":0},"end":{"line":401,"column":22}},"401":{"start":{"line":402,"column":0},"end":{"line":402,"column":9}},"403":{"start":{"line":404,"column":0},"end":{"line":404,"column":28}},"404":{"start":{"line":405,"column":0},"end":{"line":405,"column":34}},"405":{"start":{"line":406,"column":0},"end":{"line":406,"column":9}},"407":{"start":{"line":408,"column":0},"end":{"line":408,"column":64}},"409":{"start":{"line":410,"column":0},"end":{"line":410,"column":29}},"410":{"start":{"line":411,"column":0},"end":{"line":411,"column":50}},"411":{"start":{"line":412,"column":0},"end":{"line":412,"column":33}},"412":{"start":{"line":413,"column":0},"end":{"line":413,"column":29}},"413":{"start":{"line":414,"column":0},"end":{"line":414,"column":13}},"415":{"start":{"line":416,"column":0},"end":{"line":416,"column":56}},"416":{"start":{"line":417,"column":0},"end":{"line":417,"column":16}},"417":{"start":{"line":418,"column":0},"end":{"line":418,"column":16}},"418":{"start":{"line":419,"column":0},"end":{"line":419,"column":50}},"419":{"start":{"line":420,"column":0},"end":{"line":420,"column":33}},"420":{"start":{"line":421,"column":0},"end":{"line":421,"column":32}},"421":{"start":{"line":422,"column":0},"end":{"line":422,"column":13}},"422":{"start":{"line":423,"column":0},"end":{"line":423,"column":9}},"424":{"start":{"line":425,"column":0},"end":{"line":425,"column":13}},"425":{"start":{"line":426,"column":0},"end":{"line":426,"column":34}},"426":{"start":{"line":427,"column":0},"end":{"line":427,"column":25}},"427":{"start":{"line":428,"column":0},"end":{"line":428,"column":56}},"428":{"start":{"line":429,"column":0},"end":{"line":429,"column":22}},"429":{"start":{"line":430,"column":0},"end":{"line":430,"column":9}},"430":{"start":{"line":431,"column":0},"end":{"line":431,"column":7}},"432":{"start":{"line":433,"column":0},"end":{"line":433,"column":28}},"433":{"start":{"line":434,"column":0},"end":{"line":434,"column":32}},"434":{"start":{"line":435,"column":0},"end":{"line":435,"column":7}},"435":{"start":{"line":436,"column":0},"end":{"line":436,"column":15}},"436":{"start":{"line":437,"column":0},"end":{"line":437,"column":57}},"437":{"start":{"line":438,"column":0},"end":{"line":438,"column":5}},"438":{"start":{"line":439,"column":0},"end":{"line":439,"column":3}},"440":{"start":{"line":441,"column":0},"end":{"line":441,"column":110}},"441":{"start":{"line":442,"column":0},"end":{"line":442,"column":55}},"443":{"start":{"line":444,"column":0},"end":{"line":444,"column":99}},"449":{"start":{"line":450,"column":0},"end":{"line":450,"column":61}},"450":{"start":{"line":451,"column":0},"end":{"line":451,"column":22}},"451":{"start":{"line":452,"column":0},"end":{"line":452,"column":11}},"452":{"start":{"line":453,"column":0},"end":{"line":453,"column":36}},"453":{"start":{"line":454,"column":0},"end":{"line":454,"column":36}},"454":{"start":{"line":455,"column":0},"end":{"line":455,"column":11}},"455":{"start":{"line":456,"column":0},"end":{"line":456,"column":20}},"456":{"start":{"line":457,"column":0},"end":{"line":457,"column":7}},"458":{"start":{"line":459,"column":0},"end":{"line":459,"column":88}},"460":{"start":{"line":461,"column":0},"end":{"line":461,"column":19}},"461":{"start":{"line":462,"column":0},"end":{"line":462,"column":3}},"463":{"start":{"line":464,"column":0},"end":{"line":464,"column":43}},"464":{"start":{"line":465,"column":0},"end":{"line":465,"column":35}},"465":{"start":{"line":466,"column":0},"end":{"line":466,"column":94}},"466":{"start":{"line":467,"column":0},"end":{"line":467,"column":61}},"467":{"start":{"line":468,"column":0},"end":{"line":468,"column":41}},"468":{"start":{"line":469,"column":0},"end":{"line":469,"column":38}},"470":{"start":{"line":471,"column":0},"end":{"line":471,"column":15}},"471":{"start":{"line":472,"column":0},"end":{"line":472,"column":7}},"472":{"start":{"line":473,"column":0},"end":{"line":473,"column":5}},"473":{"start":{"line":474,"column":0},"end":{"line":474,"column":3}},"475":{"start":{"line":476,"column":0},"end":{"line":476,"column":45}},"477":{"start":{"line":478,"column":0},"end":{"line":478,"column":29}},"478":{"start":{"line":479,"column":0},"end":{"line":479,"column":37}},"479":{"start":{"line":480,"column":0},"end":{"line":480,"column":55}},"480":{"start":{"line":481,"column":0},"end":{"line":481,"column":7}},"481":{"start":{"line":482,"column":0},"end":{"line":482,"column":12}},"482":{"start":{"line":483,"column":0},"end":{"line":483,"column":40}},"483":{"start":{"line":484,"column":0},"end":{"line":484,"column":5}},"485":{"start":{"line":486,"column":0},"end":{"line":486,"column":34}},"486":{"start":{"line":487,"column":0},"end":{"line":487,"column":3}},"488":{"start":{"line":489,"column":0},"end":{"line":489,"column":30}},"489":{"start":{"line":490,"column":0},"end":{"line":490,"column":35}},"490":{"start":{"line":491,"column":0},"end":{"line":491,"column":3}},"492":{"start":{"line":493,"column":0},"end":{"line":493,"column":57}},"493":{"start":{"line":494,"column":0},"end":{"line":494,"column":33}},"494":{"start":{"line":495,"column":0},"end":{"line":495,"column":18}},"495":{"start":{"line":496,"column":0},"end":{"line":496,"column":5}},"497":{"start":{"line":498,"column":0},"end":{"line":498,"column":36}},"498":{"start":{"line":499,"column":0},"end":{"line":499,"column":18}},"499":{"start":{"line":500,"column":0},"end":{"line":500,"column":5}},"501":{"start":{"line":502,"column":0},"end":{"line":502,"column":69}},"502":{"start":{"line":503,"column":0},"end":{"line":503,"column":55}},"504":{"start":{"line":505,"column":0},"end":{"line":505,"column":59}},"505":{"start":{"line":506,"column":0},"end":{"line":506,"column":18}},"506":{"start":{"line":507,"column":0},"end":{"line":507,"column":5}},"508":{"start":{"line":509,"column":0},"end":{"line":509,"column":54}},"509":{"start":{"line":510,"column":0},"end":{"line":510,"column":67}},"510":{"start":{"line":511,"column":0},"end":{"line":511,"column":20}},"511":{"start":{"line":512,"column":0},"end":{"line":512,"column":7}},"512":{"start":{"line":513,"column":0},"end":{"line":513,"column":5}},"514":{"start":{"line":515,"column":0},"end":{"line":515,"column":17}},"515":{"start":{"line":516,"column":0},"end":{"line":516,"column":3}},"516":{"start":{"line":517,"column":0},"end":{"line":517,"column":1}},"518":{"start":{"line":519,"column":0},"end":{"line":519,"column":62}},"519":{"start":{"line":520,"column":0},"end":{"line":520,"column":37}},"520":{"start":{"line":521,"column":0},"end":{"line":521,"column":67}},"521":{"start":{"line":522,"column":0},"end":{"line":522,"column":3}},"523":{"start":{"line":524,"column":0},"end":{"line":524,"column":48}},"524":{"start":{"line":525,"column":0},"end":{"line":525,"column":1}},"526":{"start":{"line":527,"column":0},"end":{"line":527,"column":95}},"527":{"start":{"line":528,"column":0},"end":{"line":528,"column":74}},"529":{"start":{"line":530,"column":0},"end":{"line":530,"column":35}},"530":{"start":{"line":531,"column":0},"end":{"line":531,"column":56}},"531":{"start":{"line":532,"column":0},"end":{"line":532,"column":3}},"533":{"start":{"line":534,"column":0},"end":{"line":534,"column":56}},"534":{"start":{"line":535,"column":0},"end":{"line":535,"column":1}}},"s":{"0":1,"3":1,"4":1,"5":1,"6":1,"7":1,"55":1,"56":2,"57":2,"58":2,"59":2,"60":2,"61":2,"62":2,"63":2,"66":2,"67":2,"69":2,"70":2,"71":2,"72":2,"73":2,"84":2,"85":1,"86":1,"89":1,"90":1,"91":1,"92":1,"93":1,"94":1,"96":2,"97":0,"98":0,"106":2,"107":0,"109":0,"110":0,"111":0,"113":0,"115":0,"117":0,"119":0,"120":0,"121":0,"122":0,"123":0,"130":2,"131":0,"133":0,"134":0,"135":0,"137":0,"139":0,"141":0,"143":0,"144":0,"145":0,"146":0,"147":0,"159":2,"160":2,"162":2,"163":2,"164":2,"166":2,"167":2,"168":2,"170":2,"172":2,"174":2,"176":2,"178":2,"179":0,"180":0,"181":0,"182":0,"183":0,"184":2,"185":2,"186":2,"188":2,"189":2,"191":2,"192":2,"193":2,"194":2,"196":2,"197":2,"212":2,"213":1,"214":1,"215":1,"216":1,"218":1,"219":0,"220":0,"222":1,"223":1,"229":1,"231":1,"232":0,"233":0,"235":1,"237":1,"239":1,"248":0,"249":0,"250":0,"252":0,"253":0,"255":0,"256":0,"259":1,"261":1,"262":1,"263":1,"265":1,"267":1,"269":1,"271":1,"272":1,"273":1,"274":1,"275":1,"280":2,"281":0,"282":0,"283":0,"285":0,"286":0,"287":0,"289":0,"291":0,"292":0,"293":0,"295":0,"297":0,"299":0,"300":0,"301":0,"302":0,"303":0,"311":2,"312":0,"315":0,"316":0,"317":0,"318":0,"319":0,"322":0,"323":0,"324":0,"325":0,"326":0,"328":0,"329":0,"331":0,"332":0,"333":0,"336":0,"337":0,"338":0,"339":0,"341":0,"342":0,"343":0,"344":0,"345":0,"346":0,"347":0,"349":0,"350":0,"352":2,"353":1,"355":1,"357":1,"358":1,"360":1,"362":1,"363":1,"365":1,"368":1,"370":1,"371":1,"373":1,"374":0,"375":0,"376":0,"377":0,"379":0,"380":0,"382":1,"383":1,"384":1,"385":1,"388":1,"389":0,"390":0,"392":1,"394":1,"396":1,"397":1,"398":1,"399":0,"400":0,"401":0,"403":1,"404":1,"405":1,"407":1,"409":0,"410":0,"411":0,"412":0,"413":0,"415":0,"416":0,"417":0,"418":0,"419":0,"420":0,"421":0,"422":0,"424":0,"425":0,"426":0,"427":0,"428":0,"429":0,"430":1,"432":0,"433":0,"434":0,"435":1,"436":0,"437":0,"438":1,"440":2,"441":1,"443":1,"449":1,"450":1,"451":0,"452":0,"453":0,"454":0,"455":1,"456":1,"458":1,"460":1,"461":1,"463":2,"464":2,"465":2,"466":2,"467":2,"468":2,"470":2,"471":2,"472":2,"473":2,"475":2,"477":0,"478":0,"479":0,"480":0,"481":0,"482":0,"483":0,"485":0,"486":0,"488":2,"489":1,"490":1,"492":2,"493":1,"494":0,"495":0,"497":1,"498":1,"499":1,"501":0,"502":0,"504":0,"505":0,"506":0,"508":0,"509":0,"510":0,"511":0,"512":0,"514":0,"515":1,"516":2,"518":0,"519":0,"520":0,"521":0,"523":0,"524":0,"526":0,"527":0,"529":0,"530":0,"531":0,"533":0,"534":0},"branchMap":{"0":{"type":"branch","line":56,"loc":{"start":{"line":56,"column":7},"end":{"line":517,"column":1}},"locations":[{"start":{"line":56,"column":7},"end":{"line":517,"column":1}}]},"1":{"type":"branch","line":70,"loc":{"start":{"line":70,"column":2},"end":{"line":74,"column":6}},"locations":[{"start":{"line":70,"column":2},"end":{"line":74,"column":6}}]},"2":{"type":"branch","line":85,"loc":{"start":{"line":85,"column":2},"end":{"line":95,"column":3}},"locations":[{"start":{"line":85,"column":2},"end":{"line":95,"column":3}}]},"3":{"type":"branch","line":160,"loc":{"start":{"line":160,"column":2},"end":{"line":198,"column":3}},"locations":[{"start":{"line":160,"column":2},"end":{"line":198,"column":3}}]},"4":{"type":"branch","line":161,"loc":{"start":{"line":161,"column":37},"end":{"line":161,"column":63}},"locations":[{"start":{"line":161,"column":37},"end":{"line":161,"column":63}}]},"5":{"type":"branch","line":164,"loc":{"start":{"line":164,"column":11},"end":{"line":164,"column":36}},"locations":[{"start":{"line":164,"column":11},"end":{"line":164,"column":36}}]},"6":{"type":"branch","line":168,"loc":{"start":{"line":168,"column":6},"end":{"line":193,"column":8}},"locations":[{"start":{"line":168,"column":6},"end":{"line":193,"column":8}}]},"7":{"type":"branch","line":179,"loc":{"start":{"line":179,"column":57},"end":{"line":185,"column":15}},"locations":[{"start":{"line":179,"column":57},"end":{"line":185,"column":15}}]},"8":{"type":"branch","line":213,"loc":{"start":{"line":213,"column":2},"end":{"line":276,"column":3}},"locations":[{"start":{"line":213,"column":2},"end":{"line":276,"column":3}}]},"9":{"type":"branch","line":219,"loc":{"start":{"line":219,"column":22},"end":{"line":221,"column":5}},"locations":[{"start":{"line":219,"column":22},"end":{"line":221,"column":5}}]},"10":{"type":"branch","line":224,"loc":{"start":{"line":224,"column":6},"end":{"line":273,"column":8}},"locations":[{"start":{"line":224,"column":6},"end":{"line":273,"column":8}}]},"11":{"type":"branch","line":232,"loc":{"start":{"line":232,"column":19},"end":{"line":232,"column":48}},"locations":[{"start":{"line":232,"column":19},"end":{"line":232,"column":48}}]},"12":{"type":"branch","line":232,"loc":{"start":{"line":232,"column":48},"end":{"line":234,"column":9}},"locations":[{"start":{"line":232,"column":48},"end":{"line":234,"column":9}}]},"13":{"type":"branch","line":238,"loc":{"start":{"line":238,"column":31},"end":{"line":238,"column":68}},"locations":[{"start":{"line":238,"column":31},"end":{"line":238,"column":68}}]},"14":{"type":"branch","line":240,"loc":{"start":{"line":240,"column":24},"end":{"line":257,"column":9}},"locations":[{"start":{"line":240,"column":24},"end":{"line":257,"column":9}}]},"15":{"type":"branch","line":263,"loc":{"start":{"line":263,"column":10},"end":{"line":263,"column":31}},"locations":[{"start":{"line":263,"column":10},"end":{"line":263,"column":31}}]},"16":{"type":"branch","line":266,"loc":{"start":{"line":266,"column":14},"end":{"line":266,"column":36}},"locations":[{"start":{"line":266,"column":14},"end":{"line":266,"column":36}}]},"17":{"type":"branch","line":353,"loc":{"start":{"line":353,"column":2},"end":{"line":439,"column":3}},"locations":[{"start":{"line":353,"column":2},"end":{"line":439,"column":3}}]},"18":{"type":"branch","line":374,"loc":{"start":{"line":374,"column":35},"end":{"line":381,"column":9}},"locations":[{"start":{"line":374,"column":35},"end":{"line":381,"column":9}}]},"19":{"type":"branch","line":389,"loc":{"start":{"line":389,"column":34},"end":{"line":391,"column":9}},"locations":[{"start":{"line":389,"column":34},"end":{"line":391,"column":9}}]},"20":{"type":"branch","line":399,"loc":{"start":{"line":399,"column":8},"end":{"line":402,"column":9}},"locations":[{"start":{"line":399,"column":8},"end":{"line":402,"column":9}}]},"21":{"type":"branch","line":408,"loc":{"start":{"line":408,"column":59},"end":{"line":430,"column":9}},"locations":[{"start":{"line":408,"column":59},"end":{"line":430,"column":9}}]},"22":{"type":"branch","line":431,"loc":{"start":{"line":431,"column":6},"end":{"line":435,"column":7}},"locations":[{"start":{"line":431,"column":6},"end":{"line":435,"column":7}}]},"23":{"type":"branch","line":436,"loc":{"start":{"line":436,"column":4},"end":{"line":438,"column":5}},"locations":[{"start":{"line":436,"column":4},"end":{"line":438,"column":5}}]},"24":{"type":"branch","line":441,"loc":{"start":{"line":441,"column":2},"end":{"line":462,"column":3}},"locations":[{"start":{"line":441,"column":2},"end":{"line":462,"column":3}}]},"25":{"type":"branch","line":444,"loc":{"start":{"line":444,"column":4},"end":{"line":444,"column":18}},"locations":[{"start":{"line":444,"column":4},"end":{"line":444,"column":18}}]},"26":{"type":"branch","line":451,"loc":{"start":{"line":451,"column":16},"end":{"line":455,"column":11}},"locations":[{"start":{"line":451,"column":16},"end":{"line":455,"column":11}}]},"27":{"type":"branch","line":464,"loc":{"start":{"line":464,"column":10},"end":{"line":474,"column":3}},"locations":[{"start":{"line":464,"column":10},"end":{"line":474,"column":3}}]},"28":{"type":"branch","line":473,"loc":{"start":{"line":473,"column":4},"end":{"line":473,"column":5}},"locations":[{"start":{"line":473,"column":4},"end":{"line":473,"column":5}}]},"29":{"type":"branch","line":489,"loc":{"start":{"line":489,"column":10},"end":{"line":491,"column":3}},"locations":[{"start":{"line":489,"column":10},"end":{"line":491,"column":3}}]},"30":{"type":"branch","line":493,"loc":{"start":{"line":493,"column":10},"end":{"line":516,"column":3}},"locations":[{"start":{"line":493,"column":10},"end":{"line":516,"column":3}}]},"31":{"type":"branch","line":494,"loc":{"start":{"line":494,"column":32},"end":{"line":496,"column":5}},"locations":[{"start":{"line":494,"column":32},"end":{"line":496,"column":5}}]},"32":{"type":"branch","line":500,"loc":{"start":{"line":500,"column":4},"end":{"line":515,"column":17}},"locations":[{"start":{"line":500,"column":4},"end":{"line":515,"column":17}}]}},"b":{"0":[2],"1":[2],"2":[1],"3":[2],"4":[0],"5":[0],"6":[2],"7":[0],"8":[1],"9":[0],"10":[1],"11":[0],"12":[0],"13":[0],"14":[0],"15":[0],"16":[0],"17":[1],"18":[0],"19":[0],"20":[0],"21":[0],"22":[0],"23":[0],"24":[1],"25":[0],"26":[0],"27":[2],"28":[0],"29":[1],"30":[1],"31":[0],"32":[0]},"fnMap":{"0":{"name":"","decl":{"start":{"line":56,"column":7},"end":{"line":517,"column":1}},"loc":{"start":{"line":56,"column":7},"end":{"line":517,"column":1}},"line":56},"1":{"name":"TutorialRunner","decl":{"start":{"line":70,"column":2},"end":{"line":74,"column":6}},"loc":{"start":{"line":70,"column":2},"end":{"line":74,"column":6}},"line":70},"2":{"name":"setCommands","decl":{"start":{"line":85,"column":2},"end":{"line":95,"column":3}},"loc":{"start":{"line":85,"column":2},"end":{"line":95,"column":3}},"line":85},"3":{"name":"onTerminalResize","decl":{"start":{"line":97,"column":2},"end":{"line":99,"column":3}},"loc":{"start":{"line":97,"column":2},"end":{"line":99,"column":3}},"line":97},"4":{"name":"updateFile","decl":{"start":{"line":107,"column":2},"end":{"line":124,"column":3}},"loc":{"start":{"line":107,"column":2},"end":{"line":124,"column":3}},"line":107},"5":{"name":"updateFiles","decl":{"start":{"line":131,"column":2},"end":{"line":148,"column":3}},"loc":{"start":{"line":131,"column":2},"end":{"line":148,"column":3}},"line":131},"6":{"name":"prepareFiles","decl":{"start":{"line":160,"column":2},"end":{"line":198,"column":3}},"loc":{"start":{"line":160,"column":2},"end":{"line":198,"column":3}},"line":160},"7":{"name":"_currentLoadTask.__vite_ssr_import_0__.newTask.ignoreCancel","decl":{"start":{"line":168,"column":6},"end":{"line":193,"column":8}},"loc":{"start":{"line":168,"column":6},"end":{"line":193,"column":8}},"line":168},"8":{"name":"runCommands","decl":{"start":{"line":213,"column":2},"end":{"line":276,"column":3}},"loc":{"start":{"line":213,"column":2},"end":{"line":276,"column":3}},"line":213},"9":{"name":"_currentProcessTask.__vite_ssr_import_0__.newTask.ignoreCancel","decl":{"start":{"line":224,"column":6},"end":{"line":273,"column":8}},"loc":{"start":{"line":224,"column":6},"end":{"line":273,"column":8}},"line":224},"10":{"name":"abortListener","decl":{"start":{"line":250,"column":34},"end":{"line":250,"column":62}},"loc":{"start":{"line":250,"column":34},"end":{"line":250,"column":62}},"line":250},"11":{"name":"restartLastRunCommands","decl":{"start":{"line":281,"column":2},"end":{"line":304,"column":3}},"loc":{"start":{"line":281,"column":2},"end":{"line":304,"column":3}},"line":281},"12":{"name":"takeSnapshot","decl":{"start":{"line":312,"column":2},"end":{"line":351,"column":3}},"loc":{"start":{"line":312,"column":2},"end":{"line":351,"column":3}},"line":312},"13":{"name":"_runCommands","decl":{"start":{"line":353,"column":2},"end":{"line":439,"column":3}},"loc":{"start":{"line":353,"column":2},"end":{"line":439,"column":3}},"line":353},"14":{"name":"abortListener","decl":{"start":{"line":358,"column":26},"end":{"line":358,"column":68}},"loc":{"start":{"line":358,"column":26},"end":{"line":358,"column":68}},"line":358},"15":{"name":"_newProcess","decl":{"start":{"line":441,"column":2},"end":{"line":462,"column":3}},"loc":{"start":{"line":441,"column":2},"end":{"line":462,"column":3}},"line":441},"16":{"name":"write","decl":{"start":{"line":459,"column":54},"end":{"line":459,"column":84}},"loc":{"start":{"line":459,"column":54},"end":{"line":459,"column":84}},"line":459},"17":{"name":"_updateDirtyState","decl":{"start":{"line":464,"column":10},"end":{"line":474,"column":3}},"loc":{"start":{"line":464,"column":10},"end":{"line":474,"column":3}},"line":464},"18":{"name":"_updateCurrentFiles","decl":{"start":{"line":476,"column":10},"end":{"line":487,"column":3}},"loc":{"start":{"line":476,"column":10},"end":{"line":487,"column":3}},"line":476},"19":{"name":"_clearDirtyState","decl":{"start":{"line":489,"column":10},"end":{"line":491,"column":3}},"loc":{"start":{"line":489,"column":10},"end":{"line":491,"column":3}},"line":489},"20":{"name":"_changeDetection","decl":{"start":{"line":493,"column":10},"end":{"line":516,"column":3}},"loc":{"start":{"line":493,"column":10},"end":{"line":516,"column":3}},"line":493},"21":{"name":"commandsToList","decl":{"start":{"line":519,"column":0},"end":{"line":525,"column":1}},"loc":{"start":{"line":519,"column":0},"end":{"line":525,"column":1}},"line":519},"22":{"name":"updateFiles","decl":{"start":{"line":527,"column":0},"end":{"line":535,"column":1}},"loc":{"start":{"line":527,"column":0},"end":{"line":535,"column":1}},"line":527}},"f":{"0":2,"1":2,"2":1,"3":0,"4":0,"5":0,"6":2,"7":2,"8":1,"9":1,"10":0,"11":0,"12":0,"13":1,"14":0,"15":1,"16":0,"17":2,"18":0,"19":1,"20":1,"21":0,"22":0}} +,"/Users/ari/Git/tutorialkit/packages/runtime/src/store/editor.ts": {"path":"/Users/ari/Git/tutorialkit/packages/runtime/src/store/editor.ts","all":true,"statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":62}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":49}},"17":{"start":{"line":18,"column":0},"end":{"line":18,"column":26}},"18":{"start":{"line":19,"column":0},"end":{"line":19,"column":44}},"19":{"start":{"line":20,"column":0},"end":{"line":20,"column":39}},"21":{"start":{"line":22,"column":0},"end":{"line":22,"column":96}},"22":{"start":{"line":23,"column":0},"end":{"line":23,"column":24}},"23":{"start":{"line":24,"column":0},"end":{"line":24,"column":23}},"24":{"start":{"line":25,"column":0},"end":{"line":25,"column":5}},"26":{"start":{"line":27,"column":0},"end":{"line":27,"column":35}},"27":{"start":{"line":28,"column":0},"end":{"line":28,"column":5}},"29":{"start":{"line":30,"column":0},"end":{"line":30,"column":49}},"30":{"start":{"line":31,"column":0},"end":{"line":31,"column":36}},"31":{"start":{"line":32,"column":0},"end":{"line":32,"column":3}},"33":{"start":{"line":34,"column":0},"end":{"line":34,"column":45}},"35":{"start":{"line":36,"column":0},"end":{"line":36,"column":31}},"36":{"start":{"line":37,"column":0},"end":{"line":37,"column":25}},"37":{"start":{"line":38,"column":0},"end":{"line":38,"column":27}},"38":{"start":{"line":39,"column":0},"end":{"line":39,"column":38}},"39":{"start":{"line":40,"column":0},"end":{"line":40,"column":20}},"40":{"start":{"line":41,"column":0},"end":{"line":41,"column":23}},"41":{"start":{"line":42,"column":0},"end":{"line":42,"column":15}},"42":{"start":{"line":43,"column":0},"end":{"line":43,"column":26}},"43":{"start":{"line":44,"column":0},"end":{"line":44,"column":30}},"44":{"start":{"line":45,"column":0},"end":{"line":45,"column":25}},"45":{"start":{"line":46,"column":0},"end":{"line":46,"column":16}},"46":{"start":{"line":47,"column":0},"end":{"line":47,"column":14}},"47":{"start":{"line":48,"column":0},"end":{"line":48,"column":13}},"48":{"start":{"line":49,"column":0},"end":{"line":49,"column":10}},"49":{"start":{"line":50,"column":0},"end":{"line":50,"column":8}},"50":{"start":{"line":51,"column":0},"end":{"line":51,"column":12}},"51":{"start":{"line":52,"column":0},"end":{"line":52,"column":53}},"53":{"start":{"line":54,"column":0},"end":{"line":54,"column":25}},"54":{"start":{"line":55,"column":0},"end":{"line":55,"column":27}},"55":{"start":{"line":56,"column":0},"end":{"line":56,"column":60}},"56":{"start":{"line":57,"column":0},"end":{"line":57,"column":20}},"57":{"start":{"line":58,"column":0},"end":{"line":58,"column":23}},"58":{"start":{"line":59,"column":0},"end":{"line":59,"column":15}},"59":{"start":{"line":60,"column":0},"end":{"line":60,"column":22}},"60":{"start":{"line":61,"column":0},"end":{"line":61,"column":31}},"61":{"start":{"line":62,"column":0},"end":{"line":62,"column":25}},"62":{"start":{"line":63,"column":0},"end":{"line":63,"column":62}},"63":{"start":{"line":64,"column":0},"end":{"line":64,"column":16}},"64":{"start":{"line":65,"column":0},"end":{"line":65,"column":14}},"65":{"start":{"line":66,"column":0},"end":{"line":66,"column":13}},"66":{"start":{"line":67,"column":0},"end":{"line":67,"column":36}},"67":{"start":{"line":68,"column":0},"end":{"line":68,"column":8}},"68":{"start":{"line":69,"column":0},"end":{"line":69,"column":5}},"69":{"start":{"line":70,"column":0},"end":{"line":70,"column":3}},"71":{"start":{"line":72,"column":0},"end":{"line":72,"column":68}},"72":{"start":{"line":73,"column":0},"end":{"line":73,"column":57}},"74":{"start":{"line":75,"column":0},"end":{"line":75,"column":25}},"75":{"start":{"line":76,"column":0},"end":{"line":76,"column":13}},"76":{"start":{"line":77,"column":0},"end":{"line":77,"column":5}},"78":{"start":{"line":79,"column":0},"end":{"line":79,"column":37}},"79":{"start":{"line":80,"column":0},"end":{"line":80,"column":23}},"80":{"start":{"line":81,"column":0},"end":{"line":81,"column":23}},"81":{"start":{"line":82,"column":0},"end":{"line":82,"column":7}},"82":{"start":{"line":83,"column":0},"end":{"line":83,"column":3}},"84":{"start":{"line":85,"column":0},"end":{"line":85,"column":58}},"85":{"start":{"line":86,"column":0},"end":{"line":86,"column":57}},"87":{"start":{"line":88,"column":0},"end":{"line":88,"column":25}},"88":{"start":{"line":89,"column":0},"end":{"line":89,"column":19}},"89":{"start":{"line":90,"column":0},"end":{"line":90,"column":5}},"91":{"start":{"line":92,"column":0},"end":{"line":92,"column":47}},"92":{"start":{"line":93,"column":0},"end":{"line":93,"column":54}},"94":{"start":{"line":95,"column":0},"end":{"line":95,"column":25}},"95":{"start":{"line":96,"column":0},"end":{"line":96,"column":39}},"96":{"start":{"line":97,"column":0},"end":{"line":97,"column":25}},"97":{"start":{"line":98,"column":0},"end":{"line":98,"column":23}},"98":{"start":{"line":99,"column":0},"end":{"line":99,"column":9}},"99":{"start":{"line":100,"column":0},"end":{"line":100,"column":5}},"101":{"start":{"line":102,"column":0},"end":{"line":102,"column":26}},"102":{"start":{"line":103,"column":0},"end":{"line":103,"column":3}},"104":{"start":{"line":105,"column":0},"end":{"line":105,"column":95}},"105":{"start":{"line":106,"column":0},"end":{"line":106,"column":89}},"106":{"start":{"line":107,"column":0},"end":{"line":107,"column":44}},"107":{"start":{"line":108,"column":0},"end":{"line":108,"column":27}},"108":{"start":{"line":109,"column":0},"end":{"line":109,"column":7}},"109":{"start":{"line":110,"column":0},"end":{"line":110,"column":7}},"111":{"start":{"line":112,"column":0},"end":{"line":112,"column":78}},"112":{"start":{"line":113,"column":0},"end":{"line":113,"column":43}},"118":{"start":{"line":119,"column":0},"end":{"line":119,"column":42}},"123":{"start":{"line":124,"column":0},"end":{"line":124,"column":30}},"124":{"start":{"line":125,"column":0},"end":{"line":125,"column":29}},"126":{"start":{"line":127,"column":0},"end":{"line":127,"column":37}},"127":{"start":{"line":128,"column":0},"end":{"line":128,"column":11}},"128":{"start":{"line":129,"column":0},"end":{"line":129,"column":7}},"129":{"start":{"line":130,"column":0},"end":{"line":130,"column":7}},"131":{"start":{"line":132,"column":0},"end":{"line":132,"column":18}},"132":{"start":{"line":133,"column":0},"end":{"line":133,"column":33}},"134":{"start":{"line":135,"column":0},"end":{"line":135,"column":39}},"135":{"start":{"line":136,"column":0},"end":{"line":136,"column":6}},"136":{"start":{"line":137,"column":0},"end":{"line":137,"column":3}},"137":{"start":{"line":138,"column":0},"end":{"line":138,"column":1}}},"s":{"0":0,"1":0,"17":0,"18":0,"19":0,"21":0,"22":0,"23":0,"24":0,"26":0,"27":0,"29":0,"30":0,"31":0,"33":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"71":0,"72":0,"74":0,"75":0,"76":0,"78":0,"79":0,"80":0,"81":0,"82":0,"84":0,"85":0,"87":0,"88":0,"89":0,"91":0,"92":0,"94":0,"95":0,"96":0,"97":0,"98":0,"99":0,"101":0,"102":0,"104":0,"105":0,"106":0,"107":0,"108":0,"109":0,"111":0,"112":0,"118":0,"123":0,"124":0,"126":0,"127":0,"128":0,"129":0,"131":0,"132":0,"134":0,"135":0,"136":0,"137":0},"branchMap":{"0":{"type":"branch","line":1,"loc":{"start":{"line":1,"column":3440},"end":{"line":138,"column":1}},"locations":[{"start":{"line":1,"column":3440},"end":{"line":138,"column":1}}]}},"b":{"0":[0]},"fnMap":{"0":{"name":"(empty-report)","decl":{"start":{"line":1,"column":3440},"end":{"line":138,"column":1}},"loc":{"start":{"line":1,"column":3440},"end":{"line":138,"column":1}},"line":1}},"f":{"0":0}} +,"/Users/ari/Git/tutorialkit/packages/runtime/src/store/index.ts": {"path":"/Users/ari/Git/tutorialkit/packages/runtime/src/store/index.ts","all":true,"statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":56}},"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":53}},"3":{"start":{"line":4,"column":0},"end":{"line":4,"column":56}},"4":{"start":{"line":5,"column":0},"end":{"line":5,"column":49}},"5":{"start":{"line":6,"column":0},"end":{"line":6,"column":55}},"7":{"start":{"line":8,"column":0},"end":{"line":8,"column":93}},"9":{"start":{"line":10,"column":0},"end":{"line":10,"column":59}},"11":{"start":{"line":12,"column":0},"end":{"line":12,"column":106}},"12":{"start":{"line":13,"column":0},"end":{"line":13,"column":46}},"13":{"start":{"line":14,"column":0},"end":{"line":14,"column":46}},"29":{"start":{"line":30,"column":0},"end":{"line":30,"column":28}},"30":{"start":{"line":31,"column":0},"end":{"line":31,"column":47}},"32":{"start":{"line":33,"column":0},"end":{"line":33,"column":34}},"33":{"start":{"line":34,"column":0},"end":{"line":34,"column":40}},"34":{"start":{"line":35,"column":0},"end":{"line":35,"column":36}},"35":{"start":{"line":36,"column":0},"end":{"line":36,"column":40}},"37":{"start":{"line":38,"column":0},"end":{"line":38,"column":50}},"38":{"start":{"line":39,"column":0},"end":{"line":39,"column":50}},"39":{"start":{"line":40,"column":0},"end":{"line":40,"column":49}},"40":{"start":{"line":41,"column":0},"end":{"line":41,"column":38}},"41":{"start":{"line":42,"column":0},"end":{"line":42,"column":27}},"42":{"start":{"line":43,"column":0},"end":{"line":43,"column":30}},"44":{"start":{"line":45,"column":0},"end":{"line":45,"column":42}},"45":{"start":{"line":46,"column":0},"end":{"line":46,"column":45}},"46":{"start":{"line":47,"column":0},"end":{"line":47,"column":45}},"52":{"start":{"line":53,"column":0},"end":{"line":53,"column":52}},"54":{"start":{"line":55,"column":0},"end":{"line":55,"column":70}},"55":{"start":{"line":56,"column":0},"end":{"line":56,"column":38}},"56":{"start":{"line":57,"column":0},"end":{"line":57,"column":42}},"57":{"start":{"line":58,"column":0},"end":{"line":58,"column":68}},"58":{"start":{"line":59,"column":0},"end":{"line":59,"column":64}},"59":{"start":{"line":60,"column":0},"end":{"line":60,"column":73}},"60":{"start":{"line":61,"column":0},"end":{"line":61,"column":101}},"67":{"start":{"line":68,"column":0},"end":{"line":68,"column":26}},"68":{"start":{"line":69,"column":0},"end":{"line":69,"column":83}},"69":{"start":{"line":70,"column":0},"end":{"line":70,"column":33}},"71":{"start":{"line":72,"column":0},"end":{"line":72,"column":46}},"72":{"start":{"line":73,"column":0},"end":{"line":73,"column":77}},"74":{"start":{"line":75,"column":0},"end":{"line":75,"column":32}},"75":{"start":{"line":76,"column":0},"end":{"line":76,"column":26}},"76":{"start":{"line":77,"column":0},"end":{"line":77,"column":20}},"77":{"start":{"line":78,"column":0},"end":{"line":78,"column":13}},"78":{"start":{"line":79,"column":0},"end":{"line":79,"column":27}},"79":{"start":{"line":80,"column":0},"end":{"line":80,"column":56}},"80":{"start":{"line":81,"column":0},"end":{"line":81,"column":36}},"82":{"start":{"line":83,"column":0},"end":{"line":83,"column":73}},"83":{"start":{"line":84,"column":0},"end":{"line":84,"column":49}},"84":{"start":{"line":85,"column":0},"end":{"line":85,"column":15}},"86":{"start":{"line":87,"column":0},"end":{"line":87,"column":20}},"87":{"start":{"line":88,"column":0},"end":{"line":88,"column":13}},"88":{"start":{"line":89,"column":0},"end":{"line":89,"column":30}},"89":{"start":{"line":90,"column":0},"end":{"line":90,"column":59}},"90":{"start":{"line":91,"column":0},"end":{"line":91,"column":36}},"92":{"start":{"line":93,"column":0},"end":{"line":93,"column":76}},"93":{"start":{"line":94,"column":0},"end":{"line":94,"column":52}},"94":{"start":{"line":95,"column":0},"end":{"line":95,"column":15}},"96":{"start":{"line":97,"column":0},"end":{"line":97,"column":20}},"97":{"start":{"line":98,"column":0},"end":{"line":98,"column":13}},"98":{"start":{"line":99,"column":0},"end":{"line":99,"column":30}},"99":{"start":{"line":100,"column":0},"end":{"line":100,"column":34}},"101":{"start":{"line":102,"column":0},"end":{"line":102,"column":50}},"103":{"start":{"line":104,"column":0},"end":{"line":104,"column":20}},"104":{"start":{"line":105,"column":0},"end":{"line":105,"column":13}},"105":{"start":{"line":106,"column":0},"end":{"line":106,"column":11}},"106":{"start":{"line":107,"column":0},"end":{"line":107,"column":9}},"108":{"start":{"line":109,"column":0},"end":{"line":109,"column":43}},"109":{"start":{"line":110,"column":0},"end":{"line":110,"column":37}},"111":{"start":{"line":112,"column":0},"end":{"line":112,"column":48}},"112":{"start":{"line":113,"column":0},"end":{"line":113,"column":48}},"114":{"start":{"line":115,"column":0},"end":{"line":115,"column":37}},"115":{"start":{"line":116,"column":0},"end":{"line":116,"column":31}},"116":{"start":{"line":117,"column":0},"end":{"line":117,"column":92}},"118":{"start":{"line":119,"column":0},"end":{"line":119,"column":41}},"119":{"start":{"line":120,"column":0},"end":{"line":120,"column":52}},"121":{"start":{"line":122,"column":0},"end":{"line":122,"column":35}},"122":{"start":{"line":123,"column":0},"end":{"line":123,"column":14}},"123":{"start":{"line":124,"column":0},"end":{"line":124,"column":35}},"124":{"start":{"line":125,"column":0},"end":{"line":125,"column":12}},"125":{"start":{"line":126,"column":0},"end":{"line":126,"column":9}},"126":{"start":{"line":127,"column":0},"end":{"line":127,"column":9}},"127":{"start":{"line":128,"column":0},"end":{"line":128,"column":5}},"128":{"start":{"line":129,"column":0},"end":{"line":129,"column":3}},"130":{"start":{"line":131,"column":0},"end":{"line":131,"column":62}},"131":{"start":{"line":132,"column":0},"end":{"line":132,"column":34}},"132":{"start":{"line":133,"column":0},"end":{"line":133,"column":13}},"133":{"start":{"line":134,"column":0},"end":{"line":134,"column":5}},"135":{"start":{"line":136,"column":0},"end":{"line":136,"column":31}},"137":{"start":{"line":138,"column":0},"end":{"line":138,"column":19}},"138":{"start":{"line":139,"column":0},"end":{"line":139,"column":26}},"139":{"start":{"line":140,"column":0},"end":{"line":140,"column":38}},"141":{"start":{"line":142,"column":0},"end":{"line":142,"column":66}},"142":{"start":{"line":143,"column":0},"end":{"line":143,"column":71}},"143":{"start":{"line":144,"column":0},"end":{"line":144,"column":42}},"144":{"start":{"line":145,"column":0},"end":{"line":145,"column":49}},"146":{"start":{"line":147,"column":0},"end":{"line":147,"column":22}},"147":{"start":{"line":148,"column":0},"end":{"line":148,"column":13}},"148":{"start":{"line":149,"column":0},"end":{"line":149,"column":5}},"150":{"start":{"line":151,"column":0},"end":{"line":151,"column":31}},"151":{"start":{"line":152,"column":0},"end":{"line":152,"column":25}},"152":{"start":{"line":153,"column":0},"end":{"line":153,"column":83}},"153":{"start":{"line":154,"column":0},"end":{"line":154,"column":77}},"155":{"start":{"line":156,"column":0},"end":{"line":156,"column":117}},"157":{"start":{"line":158,"column":0},"end":{"line":158,"column":35}},"159":{"start":{"line":160,"column":0},"end":{"line":160,"column":63}},"160":{"start":{"line":161,"column":0},"end":{"line":161,"column":26}},"161":{"start":{"line":162,"column":0},"end":{"line":162,"column":61}},"162":{"start":{"line":163,"column":0},"end":{"line":163,"column":23}},"163":{"start":{"line":164,"column":0},"end":{"line":164,"column":11}},"165":{"start":{"line":166,"column":0},"end":{"line":166,"column":32}},"167":{"start":{"line":168,"column":0},"end":{"line":168,"column":40}},"168":{"start":{"line":169,"column":0},"end":{"line":169,"column":34}},"169":{"start":{"line":170,"column":0},"end":{"line":170,"column":40}},"171":{"start":{"line":172,"column":0},"end":{"line":172,"column":46}},"173":{"start":{"line":174,"column":0},"end":{"line":174,"column":46}},"174":{"start":{"line":175,"column":0},"end":{"line":175,"column":55}},"175":{"start":{"line":176,"column":0},"end":{"line":176,"column":60}},"176":{"start":{"line":177,"column":0},"end":{"line":177,"column":63}},"177":{"start":{"line":178,"column":0},"end":{"line":178,"column":9}},"179":{"start":{"line":180,"column":0},"end":{"line":180,"column":29}},"181":{"start":{"line":182,"column":0},"end":{"line":182,"column":32}},"183":{"start":{"line":184,"column":0},"end":{"line":184,"column":41}},"184":{"start":{"line":185,"column":0},"end":{"line":185,"column":8}},"185":{"start":{"line":186,"column":0},"end":{"line":186,"column":29}},"186":{"start":{"line":187,"column":0},"end":{"line":187,"column":6}},"187":{"start":{"line":188,"column":0},"end":{"line":188,"column":3}},"189":{"start":{"line":190,"column":0},"end":{"line":190,"column":47}},"190":{"start":{"line":191,"column":0},"end":{"line":191,"column":40}},"191":{"start":{"line":192,"column":0},"end":{"line":192,"column":3}},"193":{"start":{"line":194,"column":0},"end":{"line":194,"column":54}},"194":{"start":{"line":195,"column":0},"end":{"line":195,"column":46}},"195":{"start":{"line":196,"column":0},"end":{"line":196,"column":3}},"197":{"start":{"line":198,"column":0},"end":{"line":198,"column":67}},"198":{"start":{"line":199,"column":0},"end":{"line":199,"column":45}},"199":{"start":{"line":200,"column":0},"end":{"line":200,"column":3}},"201":{"start":{"line":202,"column":0},"end":{"line":202,"column":46}},"202":{"start":{"line":203,"column":0},"end":{"line":203,"column":22}},"203":{"start":{"line":204,"column":0},"end":{"line":204,"column":3}},"205":{"start":{"line":206,"column":0},"end":{"line":206,"column":50}},"206":{"start":{"line":207,"column":0},"end":{"line":207,"column":39}},"207":{"start":{"line":208,"column":0},"end":{"line":208,"column":3}},"209":{"start":{"line":210,"column":0},"end":{"line":210,"column":37}},"210":{"start":{"line":211,"column":0},"end":{"line":211,"column":32}},"211":{"start":{"line":212,"column":0},"end":{"line":212,"column":3}},"213":{"start":{"line":214,"column":0},"end":{"line":214,"column":56}},"214":{"start":{"line":215,"column":0},"end":{"line":215,"column":42}},"215":{"start":{"line":216,"column":0},"end":{"line":216,"column":3}},"217":{"start":{"line":218,"column":0},"end":{"line":218,"column":46}},"218":{"start":{"line":219,"column":0},"end":{"line":219,"column":24}},"219":{"start":{"line":220,"column":0},"end":{"line":220,"column":3}},"221":{"start":{"line":222,"column":0},"end":{"line":222,"column":22}},"222":{"start":{"line":223,"column":0},"end":{"line":223,"column":21}},"223":{"start":{"line":224,"column":0},"end":{"line":224,"column":3}},"225":{"start":{"line":226,"column":0},"end":{"line":226,"column":41}},"226":{"start":{"line":227,"column":0},"end":{"line":227,"column":26}},"227":{"start":{"line":228,"column":0},"end":{"line":228,"column":3}},"232":{"start":{"line":233,"column":0},"end":{"line":233,"column":15}},"233":{"start":{"line":234,"column":0},"end":{"line":234,"column":38}},"234":{"start":{"line":235,"column":0},"end":{"line":235,"column":3}},"236":{"start":{"line":237,"column":0},"end":{"line":237,"column":26}},"237":{"start":{"line":238,"column":0},"end":{"line":238,"column":24}},"238":{"start":{"line":239,"column":0},"end":{"line":239,"column":19}},"239":{"start":{"line":240,"column":0},"end":{"line":240,"column":5}},"241":{"start":{"line":242,"column":0},"end":{"line":242,"column":41}},"243":{"start":{"line":244,"column":0},"end":{"line":244,"column":103}},"244":{"start":{"line":245,"column":0},"end":{"line":245,"column":3}},"246":{"start":{"line":247,"column":0},"end":{"line":247,"column":24}},"247":{"start":{"line":248,"column":0},"end":{"line":248,"column":24}},"248":{"start":{"line":249,"column":0},"end":{"line":249,"column":19}},"249":{"start":{"line":250,"column":0},"end":{"line":250,"column":5}},"251":{"start":{"line":252,"column":0},"end":{"line":252,"column":41}},"253":{"start":{"line":254,"column":0},"end":{"line":254,"column":28}},"254":{"start":{"line":255,"column":0},"end":{"line":255,"column":3}},"256":{"start":{"line":257,"column":0},"end":{"line":257,"column":26}},"257":{"start":{"line":258,"column":0},"end":{"line":258,"column":24}},"258":{"start":{"line":259,"column":0},"end":{"line":259,"column":19}},"259":{"start":{"line":260,"column":0},"end":{"line":260,"column":5}},"261":{"start":{"line":262,"column":0},"end":{"line":262,"column":43}},"263":{"start":{"line":264,"column":0},"end":{"line":264,"column":30}},"264":{"start":{"line":265,"column":0},"end":{"line":265,"column":3}},"266":{"start":{"line":267,"column":0},"end":{"line":267,"column":31}},"267":{"start":{"line":268,"column":0},"end":{"line":268,"column":50}},"268":{"start":{"line":269,"column":0},"end":{"line":269,"column":3}},"270":{"start":{"line":271,"column":0},"end":{"line":271,"column":26}},"271":{"start":{"line":272,"column":0},"end":{"line":272,"column":79}},"272":{"start":{"line":273,"column":0},"end":{"line":273,"column":3}},"274":{"start":{"line":275,"column":0},"end":{"line":275,"column":17}},"275":{"start":{"line":276,"column":0},"end":{"line":276,"column":18}},"276":{"start":{"line":277,"column":0},"end":{"line":277,"column":3}},"278":{"start":{"line":279,"column":0},"end":{"line":279,"column":11}},"279":{"start":{"line":280,"column":0},"end":{"line":280,"column":49}},"281":{"start":{"line":282,"column":0},"end":{"line":282,"column":41}},"282":{"start":{"line":283,"column":0},"end":{"line":283,"column":13}},"283":{"start":{"line":284,"column":0},"end":{"line":284,"column":5}},"285":{"start":{"line":286,"column":0},"end":{"line":286,"column":54}},"286":{"start":{"line":287,"column":0},"end":{"line":287,"column":48}},"287":{"start":{"line":288,"column":0},"end":{"line":288,"column":3}},"289":{"start":{"line":290,"column":0},"end":{"line":290,"column":11}},"290":{"start":{"line":291,"column":0},"end":{"line":291,"column":49}},"292":{"start":{"line":293,"column":0},"end":{"line":293,"column":44}},"293":{"start":{"line":294,"column":0},"end":{"line":294,"column":13}},"294":{"start":{"line":295,"column":0},"end":{"line":295,"column":5}},"296":{"start":{"line":297,"column":0},"end":{"line":297,"column":68}},"298":{"start":{"line":299,"column":0},"end":{"line":299,"column":42}},"299":{"start":{"line":300,"column":0},"end":{"line":300,"column":36}},"300":{"start":{"line":301,"column":0},"end":{"line":301,"column":3}},"302":{"start":{"line":303,"column":0},"end":{"line":303,"column":49}},"303":{"start":{"line":304,"column":0},"end":{"line":304,"column":48}},"304":{"start":{"line":305,"column":0},"end":{"line":305,"column":3}},"306":{"start":{"line":307,"column":0},"end":{"line":307,"column":49}},"307":{"start":{"line":308,"column":0},"end":{"line":308,"column":71}},"309":{"start":{"line":310,"column":0},"end":{"line":310,"column":21}},"310":{"start":{"line":311,"column":0},"end":{"line":311,"column":49}},"311":{"start":{"line":312,"column":0},"end":{"line":312,"column":5}},"312":{"start":{"line":313,"column":0},"end":{"line":313,"column":3}},"314":{"start":{"line":315,"column":0},"end":{"line":315,"column":29}},"315":{"start":{"line":316,"column":0},"end":{"line":316,"column":36}},"316":{"start":{"line":317,"column":0},"end":{"line":317,"column":3}},"318":{"start":{"line":319,"column":0},"end":{"line":319,"column":49}},"319":{"start":{"line":320,"column":0},"end":{"line":320,"column":58}},"321":{"start":{"line":322,"column":0},"end":{"line":322,"column":20}},"322":{"start":{"line":323,"column":0},"end":{"line":323,"column":13}},"323":{"start":{"line":324,"column":0},"end":{"line":324,"column":5}},"325":{"start":{"line":326,"column":0},"end":{"line":326,"column":42}},"326":{"start":{"line":327,"column":0},"end":{"line":327,"column":3}},"328":{"start":{"line":329,"column":0},"end":{"line":329,"column":62}},"329":{"start":{"line":330,"column":0},"end":{"line":330,"column":54}},"331":{"start":{"line":332,"column":0},"end":{"line":332,"column":26}},"332":{"start":{"line":333,"column":0},"end":{"line":333,"column":13}},"333":{"start":{"line":334,"column":0},"end":{"line":334,"column":5}},"335":{"start":{"line":336,"column":0},"end":{"line":336,"column":40}},"337":{"start":{"line":338,"column":0},"end":{"line":338,"column":63}},"338":{"start":{"line":339,"column":0},"end":{"line":339,"column":3}},"340":{"start":{"line":341,"column":0},"end":{"line":341,"column":51}},"341":{"start":{"line":342,"column":0},"end":{"line":342,"column":53}},"342":{"start":{"line":343,"column":0},"end":{"line":343,"column":3}},"344":{"start":{"line":345,"column":0},"end":{"line":345,"column":48}},"345":{"start":{"line":346,"column":0},"end":{"line":346,"column":23}},"346":{"start":{"line":347,"column":0},"end":{"line":347,"column":55}},"347":{"start":{"line":348,"column":0},"end":{"line":348,"column":48}},"348":{"start":{"line":349,"column":0},"end":{"line":349,"column":5}},"349":{"start":{"line":350,"column":0},"end":{"line":350,"column":3}},"351":{"start":{"line":352,"column":0},"end":{"line":352,"column":95}},"352":{"start":{"line":353,"column":0},"end":{"line":353,"column":67}},"353":{"start":{"line":354,"column":0},"end":{"line":354,"column":3}},"355":{"start":{"line":356,"column":0},"end":{"line":356,"column":19}},"356":{"start":{"line":357,"column":0},"end":{"line":357,"column":49}},"357":{"start":{"line":358,"column":0},"end":{"line":358,"column":3}},"359":{"start":{"line":360,"column":0},"end":{"line":360,"column":18}},"360":{"start":{"line":361,"column":0},"end":{"line":361,"column":39}},"361":{"start":{"line":362,"column":0},"end":{"line":362,"column":3}},"362":{"start":{"line":363,"column":0},"end":{"line":363,"column":1}}},"s":{"0":0,"2":0,"3":0,"4":0,"5":0,"7":0,"9":0,"11":0,"12":0,"13":0,"29":0,"30":0,"32":0,"33":0,"34":0,"35":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"44":0,"45":0,"46":0,"52":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"67":0,"68":0,"69":0,"71":0,"72":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"82":0,"83":0,"84":0,"86":0,"87":0,"88":0,"89":0,"90":0,"92":0,"93":0,"94":0,"96":0,"97":0,"98":0,"99":0,"101":0,"103":0,"104":0,"105":0,"106":0,"108":0,"109":0,"111":0,"112":0,"114":0,"115":0,"116":0,"118":0,"119":0,"121":0,"122":0,"123":0,"124":0,"125":0,"126":0,"127":0,"128":0,"130":0,"131":0,"132":0,"133":0,"135":0,"137":0,"138":0,"139":0,"141":0,"142":0,"143":0,"144":0,"146":0,"147":0,"148":0,"150":0,"151":0,"152":0,"153":0,"155":0,"157":0,"159":0,"160":0,"161":0,"162":0,"163":0,"165":0,"167":0,"168":0,"169":0,"171":0,"173":0,"174":0,"175":0,"176":0,"177":0,"179":0,"181":0,"183":0,"184":0,"185":0,"186":0,"187":0,"189":0,"190":0,"191":0,"193":0,"194":0,"195":0,"197":0,"198":0,"199":0,"201":0,"202":0,"203":0,"205":0,"206":0,"207":0,"209":0,"210":0,"211":0,"213":0,"214":0,"215":0,"217":0,"218":0,"219":0,"221":0,"222":0,"223":0,"225":0,"226":0,"227":0,"232":0,"233":0,"234":0,"236":0,"237":0,"238":0,"239":0,"241":0,"243":0,"244":0,"246":0,"247":0,"248":0,"249":0,"251":0,"253":0,"254":0,"256":0,"257":0,"258":0,"259":0,"261":0,"263":0,"264":0,"266":0,"267":0,"268":0,"270":0,"271":0,"272":0,"274":0,"275":0,"276":0,"278":0,"279":0,"281":0,"282":0,"283":0,"285":0,"286":0,"287":0,"289":0,"290":0,"292":0,"293":0,"294":0,"296":0,"298":0,"299":0,"300":0,"302":0,"303":0,"304":0,"306":0,"307":0,"309":0,"310":0,"311":0,"312":0,"314":0,"315":0,"316":0,"318":0,"319":0,"321":0,"322":0,"323":0,"325":0,"326":0,"328":0,"329":0,"331":0,"332":0,"333":0,"335":0,"337":0,"338":0,"340":0,"341":0,"342":0,"344":0,"345":0,"346":0,"347":0,"348":0,"349":0,"351":0,"352":0,"353":0,"355":0,"356":0,"357":0,"359":0,"360":0,"361":0,"362":0},"branchMap":{"0":{"type":"branch","line":1,"loc":{"start":{"line":1,"column":9744},"end":{"line":363,"column":1}},"locations":[{"start":{"line":1,"column":9744},"end":{"line":363,"column":1}}]}},"b":{"0":[0]},"fnMap":{"0":{"name":"(empty-report)","decl":{"start":{"line":1,"column":9744},"end":{"line":363,"column":1}},"loc":{"start":{"line":1,"column":9744},"end":{"line":363,"column":1}},"line":1}},"f":{"0":0}} +,"/Users/ari/Git/tutorialkit/packages/runtime/src/store/previews.ts": {"path":"/Users/ari/Git/tutorialkit/packages/runtime/src/store/previews.ts","all":true,"statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":56}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":34}},"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":62}},"5":{"start":{"line":6,"column":0},"end":{"line":6,"column":28}},"6":{"start":{"line":7,"column":0},"end":{"line":7,"column":49}},"7":{"start":{"line":8,"column":0},"end":{"line":8,"column":46}},"13":{"start":{"line":14,"column":0},"end":{"line":14,"column":37}},"15":{"start":{"line":16,"column":0},"end":{"line":16,"column":59}},"16":{"start":{"line":17,"column":0},"end":{"line":17,"column":36}},"17":{"start":{"line":18,"column":0},"end":{"line":18,"column":3}},"19":{"start":{"line":20,"column":0},"end":{"line":20,"column":67}},"20":{"start":{"line":21,"column":0},"end":{"line":21,"column":51}},"22":{"start":{"line":23,"column":0},"end":{"line":23,"column":50}},"23":{"start":{"line":24,"column":0},"end":{"line":24,"column":94}},"25":{"start":{"line":26,"column":0},"end":{"line":26,"column":38}},"26":{"start":{"line":27,"column":0},"end":{"line":27,"column":60}},"27":{"start":{"line":28,"column":0},"end":{"line":28,"column":32}},"28":{"start":{"line":29,"column":0},"end":{"line":29,"column":43}},"29":{"start":{"line":30,"column":0},"end":{"line":30,"column":7}},"31":{"start":{"line":32,"column":0},"end":{"line":32,"column":38}},"32":{"start":{"line":33,"column":0},"end":{"line":33,"column":37}},"33":{"start":{"line":34,"column":0},"end":{"line":34,"column":27}},"34":{"start":{"line":35,"column":0},"end":{"line":35,"column":9}},"36":{"start":{"line":37,"column":0},"end":{"line":37,"column":46}},"37":{"start":{"line":38,"column":0},"end":{"line":38,"column":40}},"38":{"start":{"line":39,"column":0},"end":{"line":39,"column":14}},"39":{"start":{"line":40,"column":0},"end":{"line":40,"column":57}},"40":{"start":{"line":41,"column":0},"end":{"line":41,"column":48}},"41":{"start":{"line":42,"column":0},"end":{"line":42,"column":7}},"42":{"start":{"line":43,"column":0},"end":{"line":43,"column":7}},"43":{"start":{"line":44,"column":0},"end":{"line":44,"column":3}},"49":{"start":{"line":50,"column":0},"end":{"line":50,"column":38}},"50":{"start":{"line":51,"column":0},"end":{"line":51,"column":27}},"52":{"start":{"line":53,"column":0},"end":{"line":53,"column":28}},"54":{"start":{"line":55,"column":0},"end":{"line":55,"column":13}},"55":{"start":{"line":56,"column":0},"end":{"line":56,"column":5}},"58":{"start":{"line":59,"column":0},"end":{"line":59,"column":57}},"60":{"start":{"line":61,"column":0},"end":{"line":61,"column":52}},"61":{"start":{"line":62,"column":0},"end":{"line":62,"column":44}},"63":{"start":{"line":64,"column":0},"end":{"line":64,"column":119}},"65":{"start":{"line":66,"column":0},"end":{"line":66,"column":25}},"66":{"start":{"line":67,"column":0},"end":{"line":67,"column":27}},"68":{"start":{"line":69,"column":0},"end":{"line":69,"column":50}},"69":{"start":{"line":70,"column":0},"end":{"line":70,"column":7}},"71":{"start":{"line":72,"column":0},"end":{"line":72,"column":25}},"72":{"start":{"line":73,"column":0},"end":{"line":73,"column":7}},"74":{"start":{"line":75,"column":0},"end":{"line":75,"column":74}},"76":{"start":{"line":77,"column":0},"end":{"line":77,"column":24}},"77":{"start":{"line":78,"column":0},"end":{"line":78,"column":53}},"78":{"start":{"line":79,"column":0},"end":{"line":79,"column":85}},"80":{"start":{"line":81,"column":0},"end":{"line":81,"column":27}},"81":{"start":{"line":82,"column":0},"end":{"line":82,"column":16}},"82":{"start":{"line":83,"column":0},"end":{"line":83,"column":9}},"83":{"start":{"line":84,"column":0},"end":{"line":84,"column":7}},"84":{"start":{"line":85,"column":0},"end":{"line":85,"column":5}},"86":{"start":{"line":87,"column":0},"end":{"line":87,"column":24}},"87":{"start":{"line":88,"column":0},"end":{"line":88,"column":13}},"88":{"start":{"line":89,"column":0},"end":{"line":89,"column":5}},"90":{"start":{"line":91,"column":0},"end":{"line":91,"column":40}},"96":{"start":{"line":97,"column":0},"end":{"line":97,"column":32}},"97":{"start":{"line":98,"column":0},"end":{"line":98,"column":100}},"99":{"start":{"line":100,"column":0},"end":{"line":100,"column":60}},"100":{"start":{"line":101,"column":0},"end":{"line":101,"column":12}},"101":{"start":{"line":102,"column":0},"end":{"line":102,"column":46}},"102":{"start":{"line":103,"column":0},"end":{"line":103,"column":5}},"103":{"start":{"line":104,"column":0},"end":{"line":104,"column":3}},"104":{"start":{"line":105,"column":0},"end":{"line":105,"column":1}}},"s":{"0":0,"1":0,"2":0,"5":0,"6":0,"7":0,"13":0,"15":0,"16":0,"17":0,"19":0,"20":0,"22":0,"23":0,"25":0,"26":0,"27":0,"28":0,"29":0,"31":0,"32":0,"33":0,"34":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"49":0,"50":0,"52":0,"54":0,"55":0,"58":0,"60":0,"61":0,"63":0,"65":0,"66":0,"68":0,"69":0,"71":0,"72":0,"74":0,"76":0,"77":0,"78":0,"80":0,"81":0,"82":0,"83":0,"84":0,"86":0,"87":0,"88":0,"90":0,"96":0,"97":0,"99":0,"100":0,"101":0,"102":0,"103":0,"104":0},"branchMap":{"0":{"type":"branch","line":1,"loc":{"start":{"line":1,"column":3107},"end":{"line":105,"column":1}},"locations":[{"start":{"line":1,"column":3107},"end":{"line":105,"column":1}}]}},"b":{"0":[0]},"fnMap":{"0":{"name":"(empty-report)","decl":{"start":{"line":1,"column":3107},"end":{"line":105,"column":1}},"loc":{"start":{"line":1,"column":3107},"end":{"line":105,"column":1}},"line":1}},"f":{"0":0}} +,"/Users/ari/Git/tutorialkit/packages/runtime/src/store/terminal.ts": {"path":"/Users/ari/Git/tutorialkit/packages/runtime/src/store/terminal.ts","all":false,"statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":57}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":55}},"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":34}},"3":{"start":{"line":4,"column":0},"end":{"line":4,"column":44}},"4":{"start":{"line":5,"column":0},"end":{"line":5,"column":62}},"5":{"start":{"line":6,"column":0},"end":{"line":6,"column":82}},"6":{"start":{"line":7,"column":0},"end":{"line":7,"column":57}},"7":{"start":{"line":8,"column":0},"end":{"line":8,"column":83}},"9":{"start":{"line":10,"column":0},"end":{"line":10,"column":28}},"10":{"start":{"line":11,"column":0},"end":{"line":11,"column":62}},"12":{"start":{"line":13,"column":0},"end":{"line":13,"column":53}},"13":{"start":{"line":14,"column":0},"end":{"line":14,"column":38}},"15":{"start":{"line":16,"column":0},"end":{"line":16,"column":14}},"16":{"start":{"line":17,"column":0},"end":{"line":17,"column":49}},"17":{"start":{"line":18,"column":0},"end":{"line":18,"column":30}},"18":{"start":{"line":19,"column":0},"end":{"line":19,"column":5}},"19":{"start":{"line":20,"column":0},"end":{"line":20,"column":35}},"20":{"start":{"line":21,"column":0},"end":{"line":21,"column":38}},"21":{"start":{"line":22,"column":0},"end":{"line":22,"column":7}},"22":{"start":{"line":23,"column":0},"end":{"line":23,"column":3}},"24":{"start":{"line":25,"column":0},"end":{"line":25,"column":43}},"25":{"start":{"line":26,"column":0},"end":{"line":26,"column":24}},"26":{"start":{"line":27,"column":0},"end":{"line":27,"column":3}},"28":{"start":{"line":29,"column":0},"end":{"line":29,"column":22}},"29":{"start":{"line":30,"column":0},"end":{"line":30,"column":55}},"30":{"start":{"line":31,"column":0},"end":{"line":31,"column":3}},"32":{"start":{"line":33,"column":0},"end":{"line":33,"column":53}},"33":{"start":{"line":34,"column":0},"end":{"line":34,"column":56}},"34":{"start":{"line":35,"column":0},"end":{"line":35,"column":57}},"37":{"start":{"line":38,"column":0},"end":{"line":38,"column":112}},"40":{"start":{"line":41,"column":0},"end":{"line":41,"column":51}},"41":{"start":{"line":42,"column":0},"end":{"line":42,"column":46}},"43":{"start":{"line":44,"column":0},"end":{"line":44,"column":32}},"45":{"start":{"line":46,"column":0},"end":{"line":46,"column":31}},"47":{"start":{"line":48,"column":0},"end":{"line":48,"column":48}},"48":{"start":{"line":49,"column":0},"end":{"line":49,"column":7}},"50":{"start":{"line":51,"column":0},"end":{"line":51,"column":36}},"51":{"start":{"line":52,"column":0},"end":{"line":52,"column":29}},"52":{"start":{"line":53,"column":0},"end":{"line":53,"column":7}},"54":{"start":{"line":55,"column":0},"end":{"line":55,"column":51}},"56":{"start":{"line":57,"column":0},"end":{"line":57,"column":37}},"57":{"start":{"line":58,"column":0},"end":{"line":58,"column":49}},"58":{"start":{"line":59,"column":0},"end":{"line":59,"column":104}},"59":{"start":{"line":60,"column":0},"end":{"line":60,"column":12}},"60":{"start":{"line":61,"column":0},"end":{"line":61,"column":24}},"62":{"start":{"line":63,"column":0},"end":{"line":63,"column":13}},"63":{"start":{"line":64,"column":0},"end":{"line":64,"column":7}},"64":{"start":{"line":65,"column":0},"end":{"line":65,"column":5}},"67":{"start":{"line":68,"column":0},"end":{"line":68,"column":44}},"68":{"start":{"line":69,"column":0},"end":{"line":69,"column":28}},"69":{"start":{"line":70,"column":0},"end":{"line":70,"column":5}},"71":{"start":{"line":72,"column":0},"end":{"line":72,"column":47}},"72":{"start":{"line":73,"column":0},"end":{"line":73,"column":3}},"80":{"start":{"line":81,"column":0},"end":{"line":81,"column":57}},"81":{"start":{"line":82,"column":0},"end":{"line":82,"column":84}},"83":{"start":{"line":84,"column":0},"end":{"line":84,"column":17}},"85":{"start":{"line":86,"column":0},"end":{"line":86,"column":13}},"86":{"start":{"line":87,"column":0},"end":{"line":87,"column":5}},"88":{"start":{"line":89,"column":0},"end":{"line":89,"column":35}},"89":{"start":{"line":90,"column":0},"end":{"line":90,"column":3}},"91":{"start":{"line":92,"column":0},"end":{"line":92,"column":48}},"93":{"start":{"line":94,"column":0},"end":{"line":94,"column":59}},"94":{"start":{"line":95,"column":0},"end":{"line":95,"column":44}},"95":{"start":{"line":96,"column":0},"end":{"line":96,"column":5}},"96":{"start":{"line":97,"column":0},"end":{"line":97,"column":3}},"98":{"start":{"line":99,"column":0},"end":{"line":99,"column":56}},"99":{"start":{"line":100,"column":0},"end":{"line":100,"column":44}},"101":{"start":{"line":102,"column":0},"end":{"line":102,"column":46}},"103":{"start":{"line":104,"column":0},"end":{"line":104,"column":37}},"104":{"start":{"line":105,"column":0},"end":{"line":105,"column":66}},"106":{"start":{"line":107,"column":0},"end":{"line":107,"column":28}},"108":{"start":{"line":109,"column":0},"end":{"line":109,"column":30}},"109":{"start":{"line":110,"column":0},"end":{"line":110,"column":5}},"111":{"start":{"line":112,"column":0},"end":{"line":112,"column":20}},"112":{"start":{"line":113,"column":0},"end":{"line":113,"column":48}},"113":{"start":{"line":114,"column":0},"end":{"line":114,"column":5}},"115":{"start":{"line":116,"column":0},"end":{"line":116,"column":9}},"116":{"start":{"line":117,"column":0},"end":{"line":117,"column":60}},"118":{"start":{"line":119,"column":0},"end":{"line":119,"column":22}},"119":{"start":{"line":120,"column":0},"end":{"line":120,"column":32}},"120":{"start":{"line":121,"column":0},"end":{"line":121,"column":7}},"122":{"start":{"line":123,"column":0},"end":{"line":123,"column":34}},"123":{"start":{"line":124,"column":0},"end":{"line":124,"column":21}},"124":{"start":{"line":125,"column":0},"end":{"line":125,"column":30}},"126":{"start":{"line":127,"column":0},"end":{"line":127,"column":19}},"128":{"start":{"line":129,"column":0},"end":{"line":129,"column":21}},"129":{"start":{"line":130,"column":0},"end":{"line":130,"column":9}},"130":{"start":{"line":131,"column":0},"end":{"line":131,"column":96}},"131":{"start":{"line":132,"column":0},"end":{"line":132,"column":13}},"132":{"start":{"line":133,"column":0},"end":{"line":133,"column":37}},"133":{"start":{"line":134,"column":0},"end":{"line":134,"column":13}},"134":{"start":{"line":135,"column":0},"end":{"line":135,"column":26}},"135":{"start":{"line":136,"column":0},"end":{"line":136,"column":59}},"136":{"start":{"line":137,"column":0},"end":{"line":137,"column":13}},"137":{"start":{"line":138,"column":0},"end":{"line":138,"column":21}},"138":{"start":{"line":139,"column":0},"end":{"line":139,"column":8}},"140":{"start":{"line":141,"column":0},"end":{"line":141,"column":18}},"141":{"start":{"line":142,"column":0},"end":{"line":142,"column":5}},"142":{"start":{"line":143,"column":0},"end":{"line":143,"column":3}},"143":{"start":{"line":144,"column":0},"end":{"line":144,"column":1}},"145":{"start":{"line":146,"column":0},"end":{"line":146,"column":61}},"146":{"start":{"line":147,"column":0},"end":{"line":147,"column":35}},"147":{"start":{"line":148,"column":0},"end":{"line":148,"column":19}},"148":{"start":{"line":149,"column":0},"end":{"line":149,"column":7}},"149":{"start":{"line":150,"column":0},"end":{"line":150,"column":52}},"150":{"start":{"line":151,"column":0},"end":{"line":151,"column":11}},"151":{"start":{"line":152,"column":0},"end":{"line":152,"column":194}},"152":{"start":{"line":153,"column":0},"end":{"line":153,"column":11}},"153":{"start":{"line":154,"column":0},"end":{"line":154,"column":43}},"154":{"start":{"line":155,"column":0},"end":{"line":155,"column":58}},"155":{"start":{"line":156,"column":0},"end":{"line":156,"column":11}},"156":{"start":{"line":157,"column":0},"end":{"line":157,"column":19}},"157":{"start":{"line":158,"column":0},"end":{"line":158,"column":6}},"159":{"start":{"line":160,"column":0},"end":{"line":160,"column":48}},"160":{"start":{"line":161,"column":0},"end":{"line":161,"column":3}},"161":{"start":{"line":162,"column":0},"end":{"line":162,"column":1}}},"s":{"0":1,"1":1,"2":1,"3":1,"4":1,"5":1,"6":1,"7":1,"9":1,"10":2,"12":2,"13":2,"15":2,"16":2,"17":2,"18":2,"19":2,"20":2,"21":2,"22":2,"24":2,"25":1,"26":1,"28":2,"29":0,"30":0,"32":2,"33":0,"34":0,"37":0,"40":0,"41":0,"43":0,"45":0,"47":0,"48":0,"50":0,"51":0,"52":0,"54":0,"56":0,"57":0,"58":0,"59":0,"60":0,"62":0,"63":0,"64":0,"67":0,"68":0,"69":0,"71":0,"72":0,"80":2,"81":0,"83":0,"85":0,"86":0,"88":0,"89":0,"91":2,"93":0,"94":0,"95":0,"96":0,"98":2,"99":0,"101":0,"103":0,"104":0,"106":0,"108":0,"109":0,"111":0,"112":0,"113":0,"115":0,"116":0,"118":0,"119":0,"120":0,"122":0,"123":0,"124":0,"126":0,"128":0,"129":0,"130":0,"131":0,"132":0,"133":0,"134":0,"135":0,"136":0,"137":0,"138":0,"140":0,"141":0,"142":0,"143":2,"145":0,"146":0,"147":0,"148":0,"149":0,"150":0,"151":0,"152":0,"153":0,"154":0,"155":0,"156":0,"157":0,"159":0,"160":0,"161":0},"branchMap":{"0":{"type":"branch","line":10,"loc":{"start":{"line":10,"column":7},"end":{"line":144,"column":1}},"locations":[{"start":{"line":10,"column":7},"end":{"line":144,"column":1}}]},"1":{"type":"branch","line":16,"loc":{"start":{"line":16,"column":2},"end":{"line":23,"column":3}},"locations":[{"start":{"line":16,"column":2},"end":{"line":23,"column":3}}]},"2":{"type":"branch","line":20,"loc":{"start":{"line":20,"column":28},"end":{"line":22,"column":5}},"locations":[{"start":{"line":20,"column":28},"end":{"line":22,"column":5}}]},"3":{"type":"branch","line":25,"loc":{"start":{"line":25,"column":2},"end":{"line":27,"column":3}},"locations":[{"start":{"line":25,"column":2},"end":{"line":27,"column":3}}]}},"b":{"0":[2],"1":[2],"2":[2],"3":[1]},"fnMap":{"0":{"name":"","decl":{"start":{"line":10,"column":7},"end":{"line":144,"column":1}},"loc":{"start":{"line":10,"column":7},"end":{"line":144,"column":1}},"line":10},"1":{"name":"TerminalStore","decl":{"start":{"line":16,"column":2},"end":{"line":23,"column":3}},"loc":{"start":{"line":16,"column":2},"end":{"line":23,"column":3}},"line":16},"2":{"name":"getOutputPanel","decl":{"start":{"line":25,"column":2},"end":{"line":27,"column":3}},"loc":{"start":{"line":25,"column":2},"end":{"line":27,"column":3}},"line":25},"3":{"name":"hasTerminalPanel","decl":{"start":{"line":29,"column":2},"end":{"line":31,"column":3}},"loc":{"start":{"line":29,"column":2},"end":{"line":31,"column":3}},"line":29},"4":{"name":"setTerminalConfiguration","decl":{"start":{"line":33,"column":2},"end":{"line":73,"column":3}},"loc":{"start":{"line":33,"column":2},"end":{"line":73,"column":3}},"line":33},"5":{"name":"attachTerminal","decl":{"start":{"line":81,"column":2},"end":{"line":90,"column":3}},"loc":{"start":{"line":81,"column":2},"end":{"line":90,"column":3}},"line":81},"6":{"name":"onTerminalResize","decl":{"start":{"line":92,"column":2},"end":{"line":97,"column":3}},"loc":{"start":{"line":92,"column":2},"end":{"line":97,"column":3}},"line":92},"7":{"name":"_bootWebContainer","decl":{"start":{"line":99,"column":2},"end":{"line":143,"column":3}},"loc":{"start":{"line":99,"column":2},"end":{"line":143,"column":3}},"line":99},"8":{"name":"validateWebContainerSupported","decl":{"start":{"line":146,"column":0},"end":{"line":162,"column":1}},"loc":{"start":{"line":146,"column":0},"end":{"line":162,"column":1}},"line":146}},"f":{"0":2,"1":2,"2":1,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0}} +,"/Users/ari/Git/tutorialkit/packages/runtime/src/utils/promises.ts": {"path":"/Users/ari/Git/tutorialkit/packages/runtime/src/utils/promises.ts","all":false,"statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":61}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":52}},"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":35}},"3":{"start":{"line":4,"column":0},"end":{"line":4,"column":3}},"5":{"start":{"line":6,"column":0},"end":{"line":6,"column":52}},"6":{"start":{"line":7,"column":0},"end":{"line":7,"column":38}},"8":{"start":{"line":9,"column":0},"end":{"line":9,"column":57}},"9":{"start":{"line":10,"column":0},"end":{"line":10,"column":23}},"10":{"start":{"line":11,"column":0},"end":{"line":11,"column":21}},"11":{"start":{"line":12,"column":0},"end":{"line":12,"column":5}},"13":{"start":{"line":14,"column":0},"end":{"line":14,"column":10}},"14":{"start":{"line":15,"column":0},"end":{"line":15,"column":12}},"15":{"start":{"line":16,"column":0},"end":{"line":16,"column":11}},"16":{"start":{"line":17,"column":0},"end":{"line":17,"column":12}},"17":{"start":{"line":18,"column":0},"end":{"line":18,"column":4}},"18":{"start":{"line":19,"column":0},"end":{"line":19,"column":1}},"20":{"start":{"line":21,"column":0},"end":{"line":21,"column":49}},"21":{"start":{"line":22,"column":0},"end":{"line":22,"column":59}},"22":{"start":{"line":23,"column":0},"end":{"line":23,"column":1}},"29":{"start":{"line":30,"column":0},"end":{"line":30,"column":24}},"30":{"start":{"line":31,"column":0},"end":{"line":31,"column":35}},"31":{"start":{"line":32,"column":0},"end":{"line":32,"column":24}},"32":{"start":{"line":33,"column":0},"end":{"line":33,"column":5}},"33":{"start":{"line":34,"column":0},"end":{"line":34,"column":1}}},"s":{"0":1,"1":1,"2":0,"3":0,"5":1,"6":1,"8":1,"9":1,"10":1,"11":1,"13":1,"14":1,"15":1,"16":1,"17":1,"18":1,"20":1,"21":0,"22":0,"29":1,"30":0,"31":0,"32":0,"33":0},"branchMap":{"0":{"type":"branch","line":1,"loc":{"start":{"line":1,"column":7},"end":{"line":19,"column":1}},"locations":[{"start":{"line":1,"column":7},"end":{"line":19,"column":1}}]},"1":{"type":"branch","line":2,"loc":{"start":{"line":2,"column":51},"end":{"line":4,"column":3}},"locations":[{"start":{"line":2,"column":51},"end":{"line":4,"column":3}}]},"2":{"type":"branch","line":9,"loc":{"start":{"line":9,"column":33},"end":{"line":12,"column":3}},"locations":[{"start":{"line":9,"column":33},"end":{"line":12,"column":3}}]}},"b":{"0":[1],"1":[0],"2":[1]},"fnMap":{"0":{"name":"withResolvers","decl":{"start":{"line":1,"column":7},"end":{"line":19,"column":1}},"loc":{"start":{"line":1,"column":7},"end":{"line":19,"column":1}},"line":1},"1":{"name":"wait","decl":{"start":{"line":21,"column":7},"end":{"line":23,"column":1}},"loc":{"start":{"line":21,"column":7},"end":{"line":23,"column":1}},"line":21},"2":{"name":"tick","decl":{"start":{"line":30,"column":7},"end":{"line":34,"column":1}},"loc":{"start":{"line":30,"column":7},"end":{"line":34,"column":1}},"line":30}},"f":{"0":1,"1":0,"2":0}} +,"/Users/ari/Git/tutorialkit/packages/runtime/src/utils/support.ts": {"path":"/Users/ari/Git/tutorialkit/packages/runtime/src/utils/support.ts","all":false,"statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":43}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":7}},"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":67}},"3":{"start":{"line":4,"column":0},"end":{"line":4,"column":67}},"4":{"start":{"line":5,"column":0},"end":{"line":5,"column":69}},"5":{"start":{"line":6,"column":0},"end":{"line":6,"column":67}},"7":{"start":{"line":8,"column":0},"end":{"line":8,"column":72}},"8":{"start":{"line":9,"column":0},"end":{"line":9,"column":18}},"9":{"start":{"line":10,"column":0},"end":{"line":10,"column":5}},"11":{"start":{"line":12,"column":0},"end":{"line":12,"column":50}},"13":{"start":{"line":14,"column":0},"end":{"line":14,"column":94}},"14":{"start":{"line":15,"column":0},"end":{"line":15,"column":58}},"15":{"start":{"line":16,"column":0},"end":{"line":16,"column":58}},"17":{"start":{"line":18,"column":0},"end":{"line":18,"column":77}},"18":{"start":{"line":19,"column":0},"end":{"line":19,"column":5}},"21":{"start":{"line":22,"column":0},"end":{"line":22,"column":64}},"22":{"start":{"line":23,"column":0},"end":{"line":23,"column":11}},"23":{"start":{"line":24,"column":0},"end":{"line":24,"column":17}},"24":{"start":{"line":25,"column":0},"end":{"line":25,"column":3}},"25":{"start":{"line":26,"column":0},"end":{"line":26,"column":1}}},"s":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":0,"7":0,"8":0,"9":0,"11":0,"13":0,"14":0,"15":0,"17":0,"18":0,"21":0,"22":0,"23":0,"24":0,"25":0},"branchMap":{},"b":{},"fnMap":{"0":{"name":"isWebContainerSupported","decl":{"start":{"line":1,"column":7},"end":{"line":26,"column":1}},"loc":{"start":{"line":1,"column":7},"end":{"line":26,"column":1}},"line":1}},"f":{"0":0}} +,"/Users/ari/Git/tutorialkit/packages/runtime/src/utils/terminal.ts": {"path":"/Users/ari/Git/tutorialkit/packages/runtime/src/utils/terminal.ts","all":false,"statementMap":{"9":{"start":{"line":10,"column":0},"end":{"line":10,"column":24}},"11":{"start":{"line":12,"column":0},"end":{"line":12,"column":28}},"12":{"start":{"line":13,"column":0},"end":{"line":13,"column":8}},"13":{"start":{"line":14,"column":0},"end":{"line":14,"column":18}},"14":{"start":{"line":15,"column":0},"end":{"line":15,"column":53}},"15":{"start":{"line":16,"column":0},"end":{"line":16,"column":52}},"16":{"start":{"line":17,"column":0},"end":{"line":17,"column":55}},"17":{"start":{"line":18,"column":0},"end":{"line":18,"column":55}},"18":{"start":{"line":19,"column":0},"end":{"line":19,"column":2}},"20":{"start":{"line":21,"column":0},"end":{"line":21,"column":53}},"21":{"start":{"line":22,"column":0},"end":{"line":22,"column":20}},"22":{"start":{"line":23,"column":0},"end":{"line":23,"column":37}},"23":{"start":{"line":24,"column":0},"end":{"line":24,"column":1}}},"s":{"9":1,"11":1,"12":1,"13":1,"14":1,"15":1,"16":1,"17":1,"18":1,"20":1,"21":1,"22":1,"23":1},"branchMap":{"0":{"type":"branch","line":21,"loc":{"start":{"line":21,"column":7},"end":{"line":24,"column":1}},"locations":[{"start":{"line":21,"column":7},"end":{"line":24,"column":1}}]},"1":{"type":"branch","line":22,"loc":{"start":{"line":22,"column":2},"end":{"line":22,"column":18}},"locations":[{"start":{"line":22,"column":2},"end":{"line":22,"column":18}}]},"2":{"type":"branch","line":23,"loc":{"start":{"line":23,"column":2},"end":{"line":23,"column":18}},"locations":[{"start":{"line":23,"column":2},"end":{"line":23,"column":18}}]}},"b":{"0":[1],"1":[0],"2":[0]},"fnMap":{"0":{"name":"red","decl":{"start":{"line":15,"column":7},"end":{"line":15,"column":53}},"loc":{"start":{"line":15,"column":7},"end":{"line":15,"column":53}},"line":15},"1":{"name":"gray","decl":{"start":{"line":16,"column":8},"end":{"line":16,"column":52}},"loc":{"start":{"line":16,"column":8},"end":{"line":16,"column":52}},"line":16},"2":{"name":"green","decl":{"start":{"line":17,"column":9},"end":{"line":17,"column":55}},"loc":{"start":{"line":17,"column":9},"end":{"line":17,"column":55}},"line":17},"3":{"name":"magenta","decl":{"start":{"line":18,"column":11},"end":{"line":18,"column":55}},"loc":{"start":{"line":18,"column":11},"end":{"line":18,"column":55}},"line":18},"4":{"name":"clearTerminal","decl":{"start":{"line":21,"column":7},"end":{"line":24,"column":1}},"loc":{"start":{"line":21,"column":7},"end":{"line":24,"column":1}},"line":21}},"f":{"0":0,"1":0,"2":0,"3":0,"4":1}} +,"/Users/ari/Git/tutorialkit/packages/runtime/src/webcontainer/command.ts": {"path":"/Users/ari/Git/tutorialkit/packages/runtime/src/webcontainer/command.ts","all":false,"statementMap":{"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":52}},"7":{"start":{"line":8,"column":0},"end":{"line":8,"column":39}},"12":{"start":{"line":13,"column":0},"end":{"line":13,"column":33}},"14":{"start":{"line":15,"column":0},"end":{"line":15,"column":65}},"15":{"start":{"line":16,"column":0},"end":{"line":16,"column":83}},"16":{"start":{"line":17,"column":0},"end":{"line":17,"column":74}},"17":{"start":{"line":18,"column":0},"end":{"line":18,"column":3}},"19":{"start":{"line":20,"column":0},"end":{"line":20,"column":23}},"20":{"start":{"line":21,"column":0},"end":{"line":21,"column":23}},"22":{"start":{"line":23,"column":0},"end":{"line":23,"column":26}},"23":{"start":{"line":24,"column":0},"end":{"line":24,"column":58}},"24":{"start":{"line":25,"column":0},"end":{"line":25,"column":22}},"25":{"start":{"line":26,"column":0},"end":{"line":26,"column":7}},"27":{"start":{"line":28,"column":0},"end":{"line":28,"column":30}},"28":{"start":{"line":29,"column":0},"end":{"line":29,"column":32}},"29":{"start":{"line":30,"column":0},"end":{"line":30,"column":7}},"30":{"start":{"line":31,"column":0},"end":{"line":31,"column":9}},"31":{"start":{"line":32,"column":0},"end":{"line":32,"column":3}},"32":{"start":{"line":33,"column":0},"end":{"line":33,"column":1}},"34":{"start":{"line":35,"column":0},"end":{"line":35,"column":22}},"38":{"start":{"line":39,"column":0},"end":{"line":39,"column":32}},"43":{"start":{"line":44,"column":0},"end":{"line":44,"column":25}},"45":{"start":{"line":46,"column":0},"end":{"line":46,"column":39}},"46":{"start":{"line":47,"column":0},"end":{"line":47,"column":56}},"47":{"start":{"line":48,"column":0},"end":{"line":48,"column":42}},"48":{"start":{"line":49,"column":0},"end":{"line":49,"column":3}},"50":{"start":{"line":51,"column":0},"end":{"line":51,"column":16}},"51":{"start":{"line":52,"column":0},"end":{"line":52,"column":36}},"52":{"start":{"line":53,"column":0},"end":{"line":53,"column":3}},"54":{"start":{"line":55,"column":0},"end":{"line":55,"column":41}},"55":{"start":{"line":56,"column":0},"end":{"line":56,"column":45}},"56":{"start":{"line":57,"column":0},"end":{"line":57,"column":3}},"58":{"start":{"line":59,"column":0},"end":{"line":59,"column":42}},"59":{"start":{"line":60,"column":0},"end":{"line":60,"column":19}},"61":{"start":{"line":62,"column":0},"end":{"line":62,"column":38}},"62":{"start":{"line":63,"column":0},"end":{"line":63,"column":22}},"63":{"start":{"line":64,"column":0},"end":{"line":64,"column":40}},"64":{"start":{"line":65,"column":0},"end":{"line":65,"column":25}},"65":{"start":{"line":66,"column":0},"end":{"line":66,"column":12}},"66":{"start":{"line":67,"column":0},"end":{"line":67,"column":28}},"67":{"start":{"line":68,"column":0},"end":{"line":68,"column":5}},"69":{"start":{"line":70,"column":0},"end":{"line":70,"column":17}},"70":{"start":{"line":71,"column":0},"end":{"line":71,"column":3}},"72":{"start":{"line":73,"column":0},"end":{"line":73,"column":49}},"73":{"start":{"line":74,"column":0},"end":{"line":74,"column":38}},"74":{"start":{"line":75,"column":0},"end":{"line":75,"column":21}},"75":{"start":{"line":76,"column":0},"end":{"line":76,"column":5}},"77":{"start":{"line":78,"column":0},"end":{"line":78,"column":33}},"78":{"start":{"line":79,"column":0},"end":{"line":79,"column":24}},"79":{"start":{"line":80,"column":0},"end":{"line":80,"column":5}},"81":{"start":{"line":82,"column":0},"end":{"line":82,"column":27}},"82":{"start":{"line":83,"column":0},"end":{"line":83,"column":3}},"83":{"start":{"line":84,"column":0},"end":{"line":84,"column":1}}},"s":{"2":1,"7":5,"12":5,"14":5,"15":5,"16":5,"17":5,"19":5,"20":3,"22":3,"23":3,"24":2,"25":2,"27":3,"28":3,"29":3,"30":3,"31":3,"32":5,"34":1,"38":23,"43":23,"45":23,"46":23,"47":23,"48":23,"50":23,"51":3,"52":3,"54":23,"55":2,"56":2,"58":23,"59":23,"61":23,"62":17,"63":23,"64":2,"65":6,"66":4,"67":4,"69":23,"70":23,"72":23,"73":23,"74":17,"75":17,"77":16,"78":2,"79":2,"81":4,"82":23,"83":23},"branchMap":{"0":{"type":"branch","line":3,"loc":{"start":{"line":3,"column":7},"end":{"line":33,"column":1}},"locations":[{"start":{"line":3,"column":7},"end":{"line":33,"column":1}}]},"1":{"type":"branch","line":15,"loc":{"start":{"line":15,"column":2},"end":{"line":18,"column":3}},"locations":[{"start":{"line":15,"column":2},"end":{"line":18,"column":3}}]},"2":{"type":"branch","line":16,"loc":{"start":{"line":16,"column":27},"end":{"line":16,"column":48}},"locations":[{"start":{"line":16,"column":27},"end":{"line":16,"column":48}}]},"3":{"type":"branch","line":17,"loc":{"start":{"line":17,"column":60},"end":{"line":17,"column":74}},"locations":[{"start":{"line":17,"column":60},"end":{"line":17,"column":74}}]},"4":{"type":"branch","line":16,"loc":{"start":{"line":16,"column":48},"end":{"line":16,"column":81}},"locations":[{"start":{"line":16,"column":48},"end":{"line":16,"column":81}}]},"5":{"type":"branch","line":20,"loc":{"start":{"line":20,"column":2},"end":{"line":32,"column":3}},"locations":[{"start":{"line":20,"column":2},"end":{"line":32,"column":3}}]},"6":{"type":"branch","line":23,"loc":{"start":{"line":23,"column":12},"end":{"line":31,"column":7}},"locations":[{"start":{"line":23,"column":12},"end":{"line":31,"column":7}}]},"7":{"type":"branch","line":24,"loc":{"start":{"line":24,"column":34},"end":{"line":24,"column":57}},"locations":[{"start":{"line":24,"column":34},"end":{"line":24,"column":57}}]},"8":{"type":"branch","line":24,"loc":{"start":{"line":24,"column":57},"end":{"line":26,"column":7}},"locations":[{"start":{"line":24,"column":57},"end":{"line":26,"column":7}}]},"9":{"type":"branch","line":35,"loc":{"start":{"line":35,"column":7},"end":{"line":84,"column":1}},"locations":[{"start":{"line":35,"column":7},"end":{"line":84,"column":1}}]},"10":{"type":"branch","line":46,"loc":{"start":{"line":46,"column":2},"end":{"line":49,"column":3}},"locations":[{"start":{"line":46,"column":2},"end":{"line":49,"column":3}}]},"11":{"type":"branch","line":51,"loc":{"start":{"line":51,"column":2},"end":{"line":53,"column":3}},"locations":[{"start":{"line":51,"column":2},"end":{"line":53,"column":3}}]},"12":{"type":"branch","line":55,"loc":{"start":{"line":55,"column":9},"end":{"line":57,"column":3}},"locations":[{"start":{"line":55,"column":9},"end":{"line":57,"column":3}}]},"13":{"type":"branch","line":59,"loc":{"start":{"line":59,"column":9},"end":{"line":71,"column":3}},"locations":[{"start":{"line":59,"column":9},"end":{"line":71,"column":3}}]},"14":{"type":"branch","line":62,"loc":{"start":{"line":62,"column":37},"end":{"line":64,"column":15}},"locations":[{"start":{"line":62,"column":37},"end":{"line":64,"column":15}}]},"15":{"type":"branch","line":64,"loc":{"start":{"line":64,"column":4},"end":{"line":68,"column":5}},"locations":[{"start":{"line":64,"column":4},"end":{"line":68,"column":5}}]},"16":{"type":"branch","line":64,"loc":{"start":{"line":64,"column":39},"end":{"line":66,"column":11}},"locations":[{"start":{"line":64,"column":39},"end":{"line":66,"column":11}}]},"17":{"type":"branch","line":66,"loc":{"start":{"line":66,"column":4},"end":{"line":68,"column":5}},"locations":[{"start":{"line":66,"column":4},"end":{"line":68,"column":5}}]},"18":{"type":"branch","line":73,"loc":{"start":{"line":73,"column":9},"end":{"line":83,"column":3}},"locations":[{"start":{"line":73,"column":9},"end":{"line":83,"column":3}}]},"19":{"type":"branch","line":74,"loc":{"start":{"line":74,"column":37},"end":{"line":76,"column":5}},"locations":[{"start":{"line":74,"column":37},"end":{"line":76,"column":5}}]},"20":{"type":"branch","line":76,"loc":{"start":{"line":76,"column":4},"end":{"line":82,"column":27}},"locations":[{"start":{"line":76,"column":4},"end":{"line":82,"column":27}}]},"21":{"type":"branch","line":76,"loc":{"start":{"line":76,"column":4},"end":{"line":78,"column":32}},"locations":[{"start":{"line":76,"column":4},"end":{"line":78,"column":32}}]},"22":{"type":"branch","line":78,"loc":{"start":{"line":78,"column":32},"end":{"line":80,"column":5}},"locations":[{"start":{"line":78,"column":32},"end":{"line":80,"column":5}}]},"23":{"type":"branch","line":80,"loc":{"start":{"line":80,"column":4},"end":{"line":82,"column":27}},"locations":[{"start":{"line":80,"column":4},"end":{"line":82,"column":27}}]}},"b":{"0":[5],"1":[5],"2":[4],"3":[0],"4":[5],"5":[3],"6":[3],"7":[2],"8":[2],"9":[23],"10":[23],"11":[3],"12":[2],"13":[23],"14":[17],"15":[6],"16":[2],"17":[4],"18":[23],"19":[17],"20":[16],"21":[6],"22":[2],"23":[4]},"fnMap":{"0":{"name":"","decl":{"start":{"line":3,"column":7},"end":{"line":33,"column":1}},"loc":{"start":{"line":3,"column":7},"end":{"line":33,"column":1}},"line":3},"1":{"name":"Commands","decl":{"start":{"line":15,"column":2},"end":{"line":18,"column":3}},"loc":{"start":{"line":15,"column":2},"end":{"line":18,"column":3}},"line":15},"2":{"name":"","decl":{"start":{"line":35,"column":7},"end":{"line":84,"column":1}},"loc":{"start":{"line":35,"column":7},"end":{"line":84,"column":1}},"line":35},"3":{"name":"Command","decl":{"start":{"line":46,"column":2},"end":{"line":49,"column":3}},"loc":{"start":{"line":46,"column":2},"end":{"line":49,"column":3}},"line":46},"4":{"name":"isRunnable","decl":{"start":{"line":51,"column":2},"end":{"line":53,"column":3}},"loc":{"start":{"line":51,"column":2},"end":{"line":53,"column":3}},"line":51},"5":{"name":"equals","decl":{"start":{"line":55,"column":9},"end":{"line":57,"column":3}},"loc":{"start":{"line":55,"column":9},"end":{"line":57,"column":3}},"line":55},"6":{"name":"toTitle","decl":{"start":{"line":59,"column":9},"end":{"line":71,"column":3}},"loc":{"start":{"line":59,"column":9},"end":{"line":71,"column":3}},"line":59},"7":{"name":"toShellCommand","decl":{"start":{"line":73,"column":9},"end":{"line":83,"column":3}},"loc":{"start":{"line":73,"column":9},"end":{"line":83,"column":3}},"line":73}},"f":{"0":5,"1":5,"2":23,"3":23,"4":3,"5":2,"6":23,"7":23}} +,"/Users/ari/Git/tutorialkit/packages/runtime/src/webcontainer/index.ts": {"path":"/Users/ari/Git/tutorialkit/packages/runtime/src/webcontainer/index.ts","all":true,"statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":49}}},"s":{"0":0},"branchMap":{"0":{"type":"branch","line":1,"loc":{"start":{"line":1,"column":215},"end":{"line":4,"column":68}},"locations":[{"start":{"line":1,"column":215},"end":{"line":4,"column":68}}]}},"b":{"0":[0]},"fnMap":{"0":{"name":"(empty-report)","decl":{"start":{"line":1,"column":215},"end":{"line":4,"column":68}},"loc":{"start":{"line":1,"column":215},"end":{"line":4,"column":68}},"line":1}},"f":{"0":0}} +,"/Users/ari/Git/tutorialkit/packages/runtime/src/webcontainer/on-demand-boot.ts": {"path":"/Users/ari/Git/tutorialkit/packages/runtime/src/webcontainer/on-demand-boot.ts","all":true,"statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":3}},"9":{"start":{"line":10,"column":0},"end":{"line":10,"column":67}},"10":{"start":{"line":11,"column":0},"end":{"line":11,"column":53}},"11":{"start":{"line":12,"column":0},"end":{"line":12,"column":53}},"15":{"start":{"line":16,"column":0},"end":{"line":16,"column":52}},"16":{"start":{"line":17,"column":0},"end":{"line":17,"column":45}},"18":{"start":{"line":19,"column":0},"end":{"line":19,"column":68}},"20":{"start":{"line":21,"column":0},"end":{"line":21,"column":54}},"21":{"start":{"line":22,"column":0},"end":{"line":22,"column":44}},"22":{"start":{"line":23,"column":0},"end":{"line":23,"column":64}},"23":{"start":{"line":24,"column":0},"end":{"line":24,"column":3}},"25":{"start":{"line":26,"column":0},"end":{"line":26,"column":44}},"26":{"start":{"line":27,"column":0},"end":{"line":27,"column":33}},"28":{"start":{"line":29,"column":0},"end":{"line":29,"column":35}},"29":{"start":{"line":30,"column":0},"end":{"line":30,"column":3}},"31":{"start":{"line":32,"column":0},"end":{"line":32,"column":56}},"33":{"start":{"line":34,"column":0},"end":{"line":34,"column":32}},"35":{"start":{"line":36,"column":0},"end":{"line":36,"column":22}},"36":{"start":{"line":37,"column":0},"end":{"line":37,"column":1}},"38":{"start":{"line":39,"column":0},"end":{"line":39,"column":31}},"39":{"start":{"line":40,"column":0},"end":{"line":40,"column":44}},"40":{"start":{"line":41,"column":0},"end":{"line":41,"column":11}},"41":{"start":{"line":42,"column":0},"end":{"line":42,"column":3}},"43":{"start":{"line":44,"column":0},"end":{"line":44,"column":27}},"44":{"start":{"line":45,"column":0},"end":{"line":45,"column":1}},"46":{"start":{"line":47,"column":0},"end":{"line":47,"column":25}},"47":{"start":{"line":48,"column":0},"end":{"line":48,"column":60}},"49":{"start":{"line":50,"column":0},"end":{"line":50,"column":64}},"50":{"start":{"line":51,"column":0},"end":{"line":51,"column":88}},"52":{"start":{"line":53,"column":0},"end":{"line":53,"column":23}},"53":{"start":{"line":54,"column":0},"end":{"line":54,"column":1}}},"s":{"0":0,"9":0,"10":0,"11":0,"15":0,"16":0,"18":0,"20":0,"21":0,"22":0,"23":0,"25":0,"26":0,"28":0,"29":0,"31":0,"33":0,"35":0,"36":0,"38":0,"39":0,"40":0,"41":0,"43":0,"44":0,"46":0,"47":0,"49":0,"50":0,"52":0,"53":0},"branchMap":{"0":{"type":"branch","line":1,"loc":{"start":{"line":1,"column":0},"end":{"line":54,"column":-191}},"locations":[{"start":{"line":1,"column":0},"end":{"line":54,"column":-191}}]}},"b":{"0":[0]},"fnMap":{"0":{"name":"(empty-report)","decl":{"start":{"line":1,"column":0},"end":{"line":54,"column":-191}},"loc":{"start":{"line":1,"column":0},"end":{"line":54,"column":-191}},"line":1}},"f":{"0":0}} +,"/Users/ari/Git/tutorialkit/packages/runtime/src/webcontainer/preview-info.ts": {"path":"/Users/ari/Git/tutorialkit/packages/runtime/src/webcontainer/preview-info.ts","all":false,"statementMap":{"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":26}},"3":{"start":{"line":4,"column":0},"end":{"line":4,"column":15}},"4":{"start":{"line":5,"column":0},"end":{"line":5,"column":17}},"5":{"start":{"line":6,"column":0},"end":{"line":6,"column":17}},"6":{"start":{"line":7,"column":0},"end":{"line":7,"column":19}},"7":{"start":{"line":8,"column":0},"end":{"line":8,"column":20}},"9":{"start":{"line":10,"column":0},"end":{"line":10,"column":33}},"10":{"start":{"line":11,"column":0},"end":{"line":11,"column":23}},"11":{"start":{"line":12,"column":0},"end":{"line":12,"column":68}},"12":{"start":{"line":13,"column":0},"end":{"line":13,"column":5}},"14":{"start":{"line":15,"column":0},"end":{"line":15,"column":21}},"15":{"start":{"line":16,"column":0},"end":{"line":16,"column":3}},"17":{"start":{"line":18,"column":0},"end":{"line":18,"column":77}},"18":{"start":{"line":19,"column":0},"end":{"line":19,"column":38}},"19":{"start":{"line":20,"column":0},"end":{"line":20,"column":26}},"20":{"start":{"line":21,"column":0},"end":{"line":21,"column":45}},"21":{"start":{"line":22,"column":0},"end":{"line":22,"column":49}},"22":{"start":{"line":23,"column":0},"end":{"line":23,"column":33}},"23":{"start":{"line":24,"column":0},"end":{"line":24,"column":37}},"24":{"start":{"line":25,"column":0},"end":{"line":25,"column":40}},"25":{"start":{"line":26,"column":0},"end":{"line":26,"column":29}},"26":{"start":{"line":27,"column":0},"end":{"line":27,"column":30}},"27":{"start":{"line":28,"column":0},"end":{"line":28,"column":33}},"28":{"start":{"line":29,"column":0},"end":{"line":29,"column":12}},"29":{"start":{"line":30,"column":0},"end":{"line":30,"column":31}},"30":{"start":{"line":31,"column":0},"end":{"line":31,"column":33}},"31":{"start":{"line":32,"column":0},"end":{"line":32,"column":39}},"32":{"start":{"line":33,"column":0},"end":{"line":33,"column":5}},"34":{"start":{"line":35,"column":0},"end":{"line":35,"column":25}},"35":{"start":{"line":36,"column":0},"end":{"line":36,"column":3}},"37":{"start":{"line":38,"column":0},"end":{"line":38,"column":49}},"38":{"start":{"line":39,"column":0},"end":{"line":39,"column":81}},"39":{"start":{"line":40,"column":0},"end":{"line":40,"column":3}},"40":{"start":{"line":41,"column":0},"end":{"line":41,"column":1}}},"s":{"2":1,"3":19,"4":19,"5":19,"6":19,"7":19,"9":19,"10":1,"11":1,"12":1,"14":0,"15":1,"17":19,"18":19,"19":9,"20":19,"21":4,"22":4,"23":4,"24":10,"25":4,"26":4,"27":4,"28":6,"29":2,"30":2,"31":2,"32":2,"34":19,"35":19,"37":19,"38":5,"39":5,"40":19},"branchMap":{"0":{"type":"branch","line":3,"loc":{"start":{"line":3,"column":7},"end":{"line":41,"column":1}},"locations":[{"start":{"line":3,"column":7},"end":{"line":41,"column":1}}]},"1":{"type":"branch","line":10,"loc":{"start":{"line":10,"column":2},"end":{"line":16,"column":3}},"locations":[{"start":{"line":10,"column":2},"end":{"line":16,"column":3}}]},"2":{"type":"branch","line":12,"loc":{"start":{"line":12,"column":26},"end":{"line":12,"column":43}},"locations":[{"start":{"line":12,"column":26},"end":{"line":12,"column":43}}]},"3":{"type":"branch","line":13,"loc":{"start":{"line":13,"column":4},"end":{"line":15,"column":21}},"locations":[{"start":{"line":13,"column":4},"end":{"line":15,"column":21}}]},"4":{"type":"branch","line":18,"loc":{"start":{"line":18,"column":2},"end":{"line":36,"column":3}},"locations":[{"start":{"line":18,"column":2},"end":{"line":36,"column":3}}]},"5":{"type":"branch","line":19,"loc":{"start":{"line":19,"column":37},"end":{"line":21,"column":15}},"locations":[{"start":{"line":19,"column":37},"end":{"line":21,"column":15}}]},"6":{"type":"branch","line":21,"loc":{"start":{"line":21,"column":4},"end":{"line":33,"column":5}},"locations":[{"start":{"line":21,"column":4},"end":{"line":33,"column":5}}]},"7":{"type":"branch","line":21,"loc":{"start":{"line":21,"column":44},"end":{"line":25,"column":15}},"locations":[{"start":{"line":21,"column":44},"end":{"line":25,"column":15}}]},"8":{"type":"branch","line":25,"loc":{"start":{"line":25,"column":4},"end":{"line":33,"column":5}},"locations":[{"start":{"line":25,"column":4},"end":{"line":33,"column":5}}]},"9":{"type":"branch","line":25,"loc":{"start":{"line":25,"column":39},"end":{"line":29,"column":11}},"locations":[{"start":{"line":25,"column":39},"end":{"line":29,"column":11}}]},"10":{"type":"branch","line":29,"loc":{"start":{"line":29,"column":4},"end":{"line":33,"column":5}},"locations":[{"start":{"line":29,"column":4},"end":{"line":33,"column":5}}]},"11":{"type":"branch","line":38,"loc":{"start":{"line":38,"column":9},"end":{"line":40,"column":3}},"locations":[{"start":{"line":38,"column":9},"end":{"line":40,"column":3}}]},"12":{"type":"branch","line":39,"loc":{"start":{"line":39,"column":24},"end":{"line":39,"column":61}},"locations":[{"start":{"line":39,"column":24},"end":{"line":39,"column":61}}]},"13":{"type":"branch","line":39,"loc":{"start":{"line":39,"column":49},"end":{"line":39,"column":81}},"locations":[{"start":{"line":39,"column":49},"end":{"line":39,"column":81}}]}},"b":{"0":[19],"1":[1],"2":[0],"3":[0],"4":[19],"5":[9],"6":[10],"7":[4],"8":[6],"9":[4],"10":[2],"11":[5],"12":[4],"13":[2]},"fnMap":{"0":{"name":"","decl":{"start":{"line":3,"column":7},"end":{"line":41,"column":1}},"loc":{"start":{"line":3,"column":7},"end":{"line":41,"column":1}},"line":3},"1":{"name":"get url","decl":{"start":{"line":10,"column":2},"end":{"line":16,"column":3}},"loc":{"start":{"line":10,"column":2},"end":{"line":16,"column":3}},"line":10},"2":{"name":"PreviewInfo","decl":{"start":{"line":18,"column":2},"end":{"line":36,"column":3}},"loc":{"start":{"line":18,"column":2},"end":{"line":36,"column":3}},"line":18},"3":{"name":"equals","decl":{"start":{"line":38,"column":9},"end":{"line":40,"column":3}},"loc":{"start":{"line":38,"column":9},"end":{"line":40,"column":3}},"line":38}},"f":{"0":19,"1":1,"2":19,"3":5}} +,"/Users/ari/Git/tutorialkit/packages/runtime/src/webcontainer/shell.ts": {"path":"/Users/ari/Git/tutorialkit/packages/runtime/src/webcontainer/shell.ts","all":false,"statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":54}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":53}},"16":{"start":{"line":17,"column":0},"end":{"line":17,"column":36}},"17":{"start":{"line":18,"column":0},"end":{"line":18,"column":29}},"18":{"start":{"line":19,"column":0},"end":{"line":19,"column":22}},"19":{"start":{"line":20,"column":0},"end":{"line":20,"column":38}},"20":{"start":{"line":21,"column":0},"end":{"line":21,"column":3}},"21":{"start":{"line":22,"column":0},"end":{"line":22,"column":28}},"23":{"start":{"line":24,"column":0},"end":{"line":24,"column":33}},"25":{"start":{"line":26,"column":0},"end":{"line":26,"column":32}},"26":{"start":{"line":27,"column":0},"end":{"line":27,"column":3}},"28":{"start":{"line":29,"column":0},"end":{"line":29,"column":46}},"30":{"start":{"line":31,"column":0},"end":{"line":31,"column":67}},"31":{"start":{"line":32,"column":0},"end":{"line":32,"column":3}},"34":{"start":{"line":35,"column":0},"end":{"line":35,"column":76}},"35":{"start":{"line":36,"column":0},"end":{"line":36,"column":15}},"36":{"start":{"line":37,"column":0},"end":{"line":37,"column":32}},"37":{"start":{"line":38,"column":0},"end":{"line":38,"column":32}},"38":{"start":{"line":39,"column":0},"end":{"line":39,"column":6}},"39":{"start":{"line":40,"column":0},"end":{"line":40,"column":5}},"41":{"start":{"line":42,"column":0},"end":{"line":42,"column":42}},"42":{"start":{"line":43,"column":0},"end":{"line":43,"column":32}},"44":{"start":{"line":45,"column":0},"end":{"line":45,"column":41}},"45":{"start":{"line":46,"column":0},"end":{"line":46,"column":28}},"47":{"start":{"line":48,"column":0},"end":{"line":48,"column":16}},"48":{"start":{"line":49,"column":0},"end":{"line":49,"column":24}},"49":{"start":{"line":50,"column":0},"end":{"line":50,"column":19}},"50":{"start":{"line":51,"column":0},"end":{"line":51,"column":29}},"51":{"start":{"line":52,"column":0},"end":{"line":52,"column":71}},"53":{"start":{"line":54,"column":0},"end":{"line":54,"column":38}},"55":{"start":{"line":56,"column":0},"end":{"line":56,"column":33}},"57":{"start":{"line":58,"column":0},"end":{"line":58,"column":31}},"58":{"start":{"line":59,"column":0},"end":{"line":59,"column":11}},"59":{"start":{"line":60,"column":0},"end":{"line":60,"column":9}},"61":{"start":{"line":62,"column":0},"end":{"line":62,"column":29}},"62":{"start":{"line":63,"column":0},"end":{"line":63,"column":8}},"63":{"start":{"line":64,"column":0},"end":{"line":64,"column":7}},"64":{"start":{"line":65,"column":0},"end":{"line":65,"column":4}},"66":{"start":{"line":67,"column":0},"end":{"line":67,"column":29}},"67":{"start":{"line":68,"column":0},"end":{"line":68,"column":24}},"68":{"start":{"line":69,"column":0},"end":{"line":69,"column":24}},"69":{"start":{"line":70,"column":0},"end":{"line":70,"column":5}},"70":{"start":{"line":71,"column":0},"end":{"line":71,"column":5}},"72":{"start":{"line":73,"column":0},"end":{"line":73,"column":25}},"74":{"start":{"line":75,"column":0},"end":{"line":75,"column":17}},"75":{"start":{"line":76,"column":0},"end":{"line":76,"column":1}}},"s":{"0":1,"1":1,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"23":0,"25":0,"26":0,"28":0,"30":0,"31":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"41":0,"42":0,"44":0,"45":0,"47":0,"48":0,"49":0,"50":0,"51":0,"53":0,"55":0,"57":0,"58":0,"59":0,"61":0,"62":0,"63":0,"64":0,"66":0,"67":0,"68":0,"69":0,"70":0,"72":0,"74":0,"75":0},"branchMap":{},"b":{},"fnMap":{"0":{"name":"newJSHProcess","decl":{"start":{"line":17,"column":0},"end":{"line":76,"column":1}},"loc":{"start":{"line":17,"column":0},"end":{"line":76,"column":1}},"line":17}},"f":{"0":0}} +,"/Users/ari/Git/tutorialkit/packages/runtime/src/webcontainer/steps.ts": {"path":"/Users/ari/Git/tutorialkit/packages/runtime/src/webcontainer/steps.ts","all":false,"statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":34}},"10":{"start":{"line":11,"column":0},"end":{"line":11,"column":30}},"14":{"start":{"line":15,"column":0},"end":{"line":15,"column":45}},"16":{"start":{"line":17,"column":0},"end":{"line":17,"column":40}},"17":{"start":{"line":18,"column":0},"end":{"line":18,"column":30}},"18":{"start":{"line":19,"column":0},"end":{"line":19,"column":21}},"19":{"start":{"line":20,"column":0},"end":{"line":20,"column":36}},"20":{"start":{"line":21,"column":0},"end":{"line":21,"column":31}},"21":{"start":{"line":22,"column":0},"end":{"line":22,"column":25}},"22":{"start":{"line":23,"column":0},"end":{"line":23,"column":12}},"23":{"start":{"line":24,"column":0},"end":{"line":24,"column":8}},"24":{"start":{"line":25,"column":0},"end":{"line":25,"column":12}},"25":{"start":{"line":26,"column":0},"end":{"line":26,"column":32}},"26":{"start":{"line":27,"column":0},"end":{"line":27,"column":5}},"27":{"start":{"line":28,"column":0},"end":{"line":28,"column":3}},"29":{"start":{"line":30,"column":0},"end":{"line":30,"column":41}},"30":{"start":{"line":31,"column":0},"end":{"line":31,"column":42}},"32":{"start":{"line":33,"column":0},"end":{"line":33,"column":24}},"33":{"start":{"line":34,"column":0},"end":{"line":34,"column":13}},"34":{"start":{"line":35,"column":0},"end":{"line":35,"column":5}},"36":{"start":{"line":37,"column":0},"end":{"line":37,"column":94}},"37":{"start":{"line":38,"column":0},"end":{"line":38,"column":3}},"39":{"start":{"line":40,"column":0},"end":{"line":40,"column":32}},"40":{"start":{"line":41,"column":0},"end":{"line":41,"column":42}},"42":{"start":{"line":43,"column":0},"end":{"line":43,"column":24}},"43":{"start":{"line":44,"column":0},"end":{"line":44,"column":13}},"44":{"start":{"line":45,"column":0},"end":{"line":45,"column":5}},"46":{"start":{"line":47,"column":0},"end":{"line":47,"column":20}},"47":{"start":{"line":48,"column":0},"end":{"line":48,"column":38}},"48":{"start":{"line":49,"column":0},"end":{"line":49,"column":51}},"49":{"start":{"line":50,"column":0},"end":{"line":50,"column":16}},"50":{"start":{"line":51,"column":0},"end":{"line":51,"column":35}},"51":{"start":{"line":52,"column":0},"end":{"line":52,"column":10}},"52":{"start":{"line":53,"column":0},"end":{"line":53,"column":7}},"53":{"start":{"line":54,"column":0},"end":{"line":54,"column":3}},"54":{"start":{"line":55,"column":0},"end":{"line":55,"column":1}}},"s":{"0":1,"10":1,"14":5,"16":5,"17":5,"18":5,"19":5,"20":8,"21":8,"22":5,"23":5,"24":5,"25":0,"26":0,"27":5,"29":5,"30":2,"32":2,"33":0,"34":0,"36":2,"37":2,"39":5,"40":1,"42":1,"43":0,"44":0,"46":1,"47":1,"48":1,"49":2,"50":2,"51":1,"52":1,"53":1,"54":5},"branchMap":{"0":{"type":"branch","line":11,"loc":{"start":{"line":11,"column":7},"end":{"line":55,"column":1}},"locations":[{"start":{"line":11,"column":7},"end":{"line":55,"column":1}}]},"1":{"type":"branch","line":17,"loc":{"start":{"line":17,"column":2},"end":{"line":28,"column":3}},"locations":[{"start":{"line":17,"column":2},"end":{"line":28,"column":3}}]},"2":{"type":"branch","line":25,"loc":{"start":{"line":25,"column":4},"end":{"line":27,"column":5}},"locations":[{"start":{"line":25,"column":4},"end":{"line":27,"column":5}}]},"3":{"type":"branch","line":20,"loc":{"start":{"line":20,"column":21},"end":{"line":23,"column":10}},"locations":[{"start":{"line":20,"column":21},"end":{"line":23,"column":10}}]},"4":{"type":"branch","line":30,"loc":{"start":{"line":30,"column":2},"end":{"line":38,"column":3}},"locations":[{"start":{"line":30,"column":2},"end":{"line":38,"column":3}}]},"5":{"type":"branch","line":33,"loc":{"start":{"line":33,"column":23},"end":{"line":35,"column":5}},"locations":[{"start":{"line":33,"column":23},"end":{"line":35,"column":5}}]},"6":{"type":"branch","line":40,"loc":{"start":{"line":40,"column":2},"end":{"line":54,"column":3}},"locations":[{"start":{"line":40,"column":2},"end":{"line":54,"column":3}}]},"7":{"type":"branch","line":43,"loc":{"start":{"line":43,"column":23},"end":{"line":45,"column":5}},"locations":[{"start":{"line":43,"column":23},"end":{"line":45,"column":5}}]},"8":{"type":"branch","line":49,"loc":{"start":{"line":49,"column":39},"end":{"line":52,"column":8}},"locations":[{"start":{"line":49,"column":39},"end":{"line":52,"column":8}}]}},"b":{"0":[5],"1":[5],"2":[0],"3":[8],"4":[2],"5":[0],"6":[1],"7":[0],"8":[2]},"fnMap":{"0":{"name":"","decl":{"start":{"line":11,"column":7},"end":{"line":55,"column":1}},"loc":{"start":{"line":11,"column":7},"end":{"line":55,"column":1}},"line":11},"1":{"name":"setFromCommands","decl":{"start":{"line":17,"column":2},"end":{"line":28,"column":3}},"loc":{"start":{"line":17,"column":2},"end":{"line":28,"column":3}},"line":17},"2":{"name":"updateStep","decl":{"start":{"line":30,"column":2},"end":{"line":38,"column":3}},"loc":{"start":{"line":30,"column":2},"end":{"line":38,"column":3}},"line":30},"3":{"name":"skipRemaining","decl":{"start":{"line":40,"column":2},"end":{"line":54,"column":3}},"loc":{"start":{"line":40,"column":2},"end":{"line":54,"column":3}},"line":40}},"f":{"0":5,"1":5,"2":2,"3":1}} +,"/Users/ari/Git/tutorialkit/packages/runtime/src/webcontainer/terminal-config.ts": {"path":"/Users/ari/Git/tutorialkit/packages/runtime/src/webcontainer/terminal-config.ts","all":false,"statementMap":{"16":{"start":{"line":17,"column":0},"end":{"line":17,"column":29}},"17":{"start":{"line":18,"column":0},"end":{"line":18,"column":44}},"19":{"start":{"line":20,"column":0},"end":{"line":20,"column":40}},"20":{"start":{"line":21,"column":0},"end":{"line":21,"column":55}},"22":{"start":{"line":23,"column":0},"end":{"line":23,"column":30}},"23":{"start":{"line":24,"column":0},"end":{"line":24,"column":3}},"25":{"start":{"line":26,"column":0},"end":{"line":26,"column":16}},"26":{"start":{"line":27,"column":0},"end":{"line":27,"column":31}},"27":{"start":{"line":28,"column":0},"end":{"line":28,"column":3}},"29":{"start":{"line":30,"column":0},"end":{"line":30,"column":21}},"30":{"start":{"line":31,"column":0},"end":{"line":31,"column":36}},"31":{"start":{"line":32,"column":0},"end":{"line":32,"column":3}},"32":{"start":{"line":33,"column":0},"end":{"line":33,"column":1}},"34":{"start":{"line":35,"column":0},"end":{"line":35,"column":66}},"35":{"start":{"line":36,"column":0},"end":{"line":36,"column":19}},"36":{"start":{"line":37,"column":0},"end":{"line":37,"column":23}},"37":{"start":{"line":38,"column":0},"end":{"line":38,"column":2}},"39":{"start":{"line":40,"column":0},"end":{"line":40,"column":17}},"45":{"start":{"line":46,"column":0},"end":{"line":46,"column":49}},"46":{"start":{"line":47,"column":0},"end":{"line":47,"column":58}},"47":{"start":{"line":48,"column":0},"end":{"line":48,"column":14}},"48":{"start":{"line":49,"column":0},"end":{"line":49,"column":16}},"49":{"start":{"line":50,"column":0},"end":{"line":50,"column":4}},"51":{"start":{"line":52,"column":0},"end":{"line":52,"column":23}},"52":{"start":{"line":53,"column":0},"end":{"line":53,"column":23}},"53":{"start":{"line":54,"column":0},"end":{"line":54,"column":16}},"54":{"start":{"line":55,"column":0},"end":{"line":55,"column":18}},"55":{"start":{"line":56,"column":0},"end":{"line":56,"column":6}},"56":{"start":{"line":57,"column":0},"end":{"line":57,"column":3}},"58":{"start":{"line":59,"column":0},"end":{"line":59,"column":22}},"59":{"start":{"line":60,"column":0},"end":{"line":60,"column":25}},"61":{"start":{"line":62,"column":0},"end":{"line":62,"column":32}},"62":{"start":{"line":63,"column":0},"end":{"line":63,"column":41}},"63":{"start":{"line":64,"column":0},"end":{"line":64,"column":31}},"64":{"start":{"line":65,"column":0},"end":{"line":65,"column":43}},"66":{"start":{"line":67,"column":0},"end":{"line":67,"column":14}},"67":{"start":{"line":68,"column":0},"end":{"line":68,"column":37}},"68":{"start":{"line":69,"column":0},"end":{"line":69,"column":53}},"69":{"start":{"line":70,"column":0},"end":{"line":70,"column":5}},"70":{"start":{"line":71,"column":0},"end":{"line":71,"column":32}},"73":{"start":{"line":74,"column":0},"end":{"line":74,"column":17}},"74":{"start":{"line":75,"column":0},"end":{"line":75,"column":42}},"77":{"start":{"line":78,"column":0},"end":{"line":78,"column":51}},"79":{"start":{"line":80,"column":0},"end":{"line":80,"column":22}},"80":{"start":{"line":81,"column":0},"end":{"line":81,"column":29}},"81":{"start":{"line":82,"column":0},"end":{"line":82,"column":7}},"83":{"start":{"line":84,"column":0},"end":{"line":84,"column":39}},"84":{"start":{"line":85,"column":0},"end":{"line":85,"column":5}},"86":{"start":{"line":87,"column":0},"end":{"line":87,"column":23}},"87":{"start":{"line":88,"column":0},"end":{"line":88,"column":87}},"88":{"start":{"line":89,"column":0},"end":{"line":89,"column":3}},"90":{"start":{"line":91,"column":0},"end":{"line":91,"column":18}},"91":{"start":{"line":92,"column":0},"end":{"line":92,"column":26}},"92":{"start":{"line":93,"column":0},"end":{"line":93,"column":3}},"94":{"start":{"line":95,"column":0},"end":{"line":95,"column":17}},"95":{"start":{"line":96,"column":0},"end":{"line":96,"column":25}},"96":{"start":{"line":97,"column":0},"end":{"line":97,"column":3}},"98":{"start":{"line":99,"column":0},"end":{"line":99,"column":24}},"99":{"start":{"line":100,"column":0},"end":{"line":100,"column":33}},"100":{"start":{"line":101,"column":0},"end":{"line":101,"column":23}},"101":{"start":{"line":102,"column":0},"end":{"line":102,"column":5}},"103":{"start":{"line":104,"column":0},"end":{"line":104,"column":12}},"104":{"start":{"line":105,"column":0},"end":{"line":105,"column":61}},"105":{"start":{"line":106,"column":0},"end":{"line":106,"column":50}},"106":{"start":{"line":107,"column":0},"end":{"line":107,"column":6}},"107":{"start":{"line":108,"column":0},"end":{"line":108,"column":3}},"110":{"start":{"line":111,"column":0},"end":{"line":111,"column":14}},"112":{"start":{"line":113,"column":0},"end":{"line":113,"column":32}},"113":{"start":{"line":114,"column":0},"end":{"line":114,"column":3}},"115":{"start":{"line":116,"column":0},"end":{"line":116,"column":14}},"116":{"start":{"line":117,"column":0},"end":{"line":117,"column":32}},"117":{"start":{"line":118,"column":0},"end":{"line":118,"column":3}},"119":{"start":{"line":120,"column":0},"end":{"line":120,"column":11}},"120":{"start":{"line":121,"column":0},"end":{"line":121,"column":25}},"121":{"start":{"line":122,"column":0},"end":{"line":122,"column":29}},"122":{"start":{"line":123,"column":0},"end":{"line":123,"column":12}},"123":{"start":{"line":124,"column":0},"end":{"line":124,"column":22}},"124":{"start":{"line":125,"column":0},"end":{"line":125,"column":5}},"125":{"start":{"line":126,"column":0},"end":{"line":126,"column":3}},"127":{"start":{"line":128,"column":0},"end":{"line":128,"column":23}},"128":{"start":{"line":129,"column":0},"end":{"line":129,"column":25}},"129":{"start":{"line":130,"column":0},"end":{"line":130,"column":33}},"130":{"start":{"line":131,"column":0},"end":{"line":131,"column":12}},"131":{"start":{"line":132,"column":0},"end":{"line":132,"column":28}},"132":{"start":{"line":133,"column":0},"end":{"line":133,"column":5}},"133":{"start":{"line":134,"column":0},"end":{"line":134,"column":3}},"135":{"start":{"line":136,"column":0},"end":{"line":136,"column":44}},"136":{"start":{"line":137,"column":0},"end":{"line":137,"column":25}},"137":{"start":{"line":138,"column":0},"end":{"line":138,"column":38}},"138":{"start":{"line":139,"column":0},"end":{"line":139,"column":12}},"139":{"start":{"line":140,"column":0},"end":{"line":140,"column":30}},"140":{"start":{"line":141,"column":0},"end":{"line":141,"column":5}},"141":{"start":{"line":142,"column":0},"end":{"line":142,"column":3}},"149":{"start":{"line":150,"column":0},"end":{"line":150,"column":47}},"150":{"start":{"line":151,"column":0},"end":{"line":151,"column":28}},"152":{"start":{"line":153,"column":0},"end":{"line":153,"column":49}},"153":{"start":{"line":154,"column":0},"end":{"line":154,"column":65}},"154":{"start":{"line":155,"column":0},"end":{"line":155,"column":5}},"155":{"start":{"line":156,"column":0},"end":{"line":156,"column":3}},"162":{"start":{"line":163,"column":0},"end":{"line":163,"column":39}},"163":{"start":{"line":164,"column":0},"end":{"line":164,"column":36}},"164":{"start":{"line":165,"column":0},"end":{"line":165,"column":27}},"165":{"start":{"line":166,"column":0},"end":{"line":166,"column":5}},"167":{"start":{"line":168,"column":0},"end":{"line":168,"column":20}},"168":{"start":{"line":169,"column":0},"end":{"line":169,"column":30}},"170":{"start":{"line":171,"column":0},"end":{"line":171,"column":23}},"171":{"start":{"line":172,"column":0},"end":{"line":172,"column":36}},"172":{"start":{"line":173,"column":0},"end":{"line":173,"column":5}},"174":{"start":{"line":175,"column":0},"end":{"line":175,"column":49}},"175":{"start":{"line":176,"column":0},"end":{"line":176,"column":66}},"176":{"start":{"line":177,"column":0},"end":{"line":177,"column":5}},"177":{"start":{"line":178,"column":0},"end":{"line":178,"column":3}},"178":{"start":{"line":179,"column":0},"end":{"line":179,"column":1}},"186":{"start":{"line":187,"column":0},"end":{"line":187,"column":85}},"187":{"start":{"line":188,"column":0},"end":{"line":188,"column":22}},"189":{"start":{"line":190,"column":0},"end":{"line":190,"column":25}},"191":{"start":{"line":192,"column":0},"end":{"line":192,"column":12}},"192":{"start":{"line":193,"column":0},"end":{"line":193,"column":17}},"193":{"start":{"line":194,"column":0},"end":{"line":194,"column":18}},"194":{"start":{"line":195,"column":0},"end":{"line":195,"column":6}},"195":{"start":{"line":196,"column":0},"end":{"line":196,"column":3}},"198":{"start":{"line":199,"column":0},"end":{"line":199,"column":29}},"201":{"start":{"line":202,"column":0},"end":{"line":202,"column":48}},"202":{"start":{"line":203,"column":0},"end":{"line":203,"column":12}},"203":{"start":{"line":204,"column":0},"end":{"line":204,"column":44}},"204":{"start":{"line":205,"column":0},"end":{"line":205,"column":18}},"205":{"start":{"line":206,"column":0},"end":{"line":206,"column":6}},"206":{"start":{"line":207,"column":0},"end":{"line":207,"column":3}},"208":{"start":{"line":209,"column":0},"end":{"line":209,"column":37}},"210":{"start":{"line":211,"column":0},"end":{"line":211,"column":19}},"211":{"start":{"line":212,"column":0},"end":{"line":212,"column":42}},"212":{"start":{"line":213,"column":0},"end":{"line":213,"column":40}},"213":{"start":{"line":214,"column":0},"end":{"line":214,"column":4}},"215":{"start":{"line":216,"column":0},"end":{"line":216,"column":22}},"216":{"start":{"line":217,"column":0},"end":{"line":217,"column":37}},"217":{"start":{"line":218,"column":0},"end":{"line":218,"column":47}},"218":{"start":{"line":219,"column":0},"end":{"line":219,"column":46}},"219":{"start":{"line":220,"column":0},"end":{"line":220,"column":58}},"220":{"start":{"line":221,"column":0},"end":{"line":221,"column":46}},"221":{"start":{"line":222,"column":0},"end":{"line":222,"column":42}},"222":{"start":{"line":223,"column":0},"end":{"line":223,"column":41}},"224":{"start":{"line":225,"column":0},"end":{"line":225,"column":40}},"225":{"start":{"line":226,"column":0},"end":{"line":226,"column":60}},"226":{"start":{"line":227,"column":0},"end":{"line":227,"column":42}},"227":{"start":{"line":228,"column":0},"end":{"line":228,"column":55}},"228":{"start":{"line":229,"column":0},"end":{"line":229,"column":28}},"229":{"start":{"line":230,"column":0},"end":{"line":230,"column":23}},"230":{"start":{"line":231,"column":0},"end":{"line":231,"column":13}},"231":{"start":{"line":232,"column":0},"end":{"line":232,"column":16}},"232":{"start":{"line":233,"column":0},"end":{"line":233,"column":57}},"233":{"start":{"line":234,"column":0},"end":{"line":234,"column":25}},"234":{"start":{"line":235,"column":0},"end":{"line":235,"column":31}},"235":{"start":{"line":236,"column":0},"end":{"line":236,"column":74}},"236":{"start":{"line":237,"column":0},"end":{"line":237,"column":71}},"237":{"start":{"line":238,"column":0},"end":{"line":238,"column":13}},"238":{"start":{"line":239,"column":0},"end":{"line":239,"column":9}},"240":{"start":{"line":241,"column":0},"end":{"line":241,"column":35}},"241":{"start":{"line":242,"column":0},"end":{"line":242,"column":7}},"242":{"start":{"line":243,"column":0},"end":{"line":243,"column":5}},"243":{"start":{"line":244,"column":0},"end":{"line":244,"column":3}},"245":{"start":{"line":246,"column":0},"end":{"line":246,"column":47}},"246":{"start":{"line":247,"column":0},"end":{"line":247,"column":37}},"248":{"start":{"line":249,"column":0},"end":{"line":249,"column":39}},"249":{"start":{"line":250,"column":0},"end":{"line":250,"column":22}},"250":{"start":{"line":251,"column":0},"end":{"line":251,"column":5}},"251":{"start":{"line":252,"column":0},"end":{"line":252,"column":3}},"253":{"start":{"line":254,"column":0},"end":{"line":254,"column":10}},"254":{"start":{"line":255,"column":0},"end":{"line":255,"column":16}},"255":{"start":{"line":256,"column":0},"end":{"line":256,"column":11}},"256":{"start":{"line":257,"column":0},"end":{"line":257,"column":4}},"257":{"start":{"line":258,"column":0},"end":{"line":258,"column":1}}},"s":{"16":1,"17":14,"19":14,"20":14,"22":14,"23":14,"25":14,"26":43,"27":43,"29":14,"30":1,"31":1,"32":14,"34":1,"35":1,"36":1,"37":1,"39":1,"45":1,"46":26,"47":26,"48":26,"49":26,"51":26,"52":13,"53":13,"54":13,"55":13,"56":13,"58":26,"59":26,"61":26,"62":26,"63":26,"64":26,"66":26,"67":26,"68":26,"69":26,"70":26,"73":26,"74":13,"77":13,"79":13,"80":2,"81":2,"83":13,"84":13,"86":26,"87":26,"88":26,"90":26,"91":0,"92":0,"94":26,"95":0,"96":0,"98":26,"99":15,"100":4,"101":4,"103":11,"104":15,"105":15,"106":15,"107":15,"110":26,"112":0,"113":0,"115":26,"116":0,"117":0,"119":26,"120":0,"121":0,"122":0,"123":0,"124":0,"125":0,"127":26,"128":0,"129":0,"130":0,"131":0,"132":0,"133":0,"135":26,"136":0,"137":0,"138":0,"139":0,"140":0,"141":0,"149":26,"150":0,"152":0,"153":0,"154":0,"155":0,"162":26,"163":0,"164":0,"165":0,"167":0,"168":0,"170":0,"171":0,"172":0,"174":0,"175":0,"176":0,"177":0,"178":26,"186":14,"187":14,"189":14,"191":1,"192":1,"193":1,"194":1,"195":1,"198":13,"201":14,"202":4,"203":4,"204":4,"205":4,"206":4,"208":9,"210":9,"211":9,"212":9,"213":9,"215":9,"216":9,"217":0,"218":9,"219":1,"220":9,"221":8,"222":21,"224":21,"225":8,"226":21,"227":5,"228":5,"229":5,"230":5,"231":13,"232":8,"233":8,"234":8,"235":8,"236":8,"237":8,"238":8,"240":21,"241":21,"242":8,"243":9,"245":12,"246":1,"248":1,"249":0,"250":0,"251":1,"253":9,"254":9,"255":9,"256":9,"257":9},"branchMap":{"0":{"type":"branch","line":17,"loc":{"start":{"line":17,"column":7},"end":{"line":33,"column":1}},"locations":[{"start":{"line":17,"column":7},"end":{"line":33,"column":1}}]},"1":{"type":"branch","line":20,"loc":{"start":{"line":20,"column":2},"end":{"line":24,"column":3}},"locations":[{"start":{"line":20,"column":2},"end":{"line":24,"column":3}}]},"2":{"type":"branch","line":26,"loc":{"start":{"line":26,"column":2},"end":{"line":28,"column":3}},"locations":[{"start":{"line":26,"column":2},"end":{"line":28,"column":3}}]},"3":{"type":"branch","line":30,"loc":{"start":{"line":30,"column":2},"end":{"line":32,"column":3}},"locations":[{"start":{"line":30,"column":2},"end":{"line":32,"column":3}}]},"4":{"type":"branch","line":46,"loc":{"start":{"line":46,"column":7},"end":{"line":179,"column":1}},"locations":[{"start":{"line":46,"column":7},"end":{"line":179,"column":1}}]},"5":{"type":"branch","line":67,"loc":{"start":{"line":67,"column":2},"end":{"line":89,"column":3}},"locations":[{"start":{"line":67,"column":2},"end":{"line":89,"column":3}}]},"6":{"type":"branch","line":71,"loc":{"start":{"line":71,"column":16},"end":{"line":71,"column":32}},"locations":[{"start":{"line":71,"column":16},"end":{"line":71,"column":32}}]},"7":{"type":"branch","line":74,"loc":{"start":{"line":74,"column":16},"end":{"line":85,"column":5}},"locations":[{"start":{"line":74,"column":16},"end":{"line":85,"column":5}}]},"8":{"type":"branch","line":80,"loc":{"start":{"line":80,"column":21},"end":{"line":82,"column":7}},"locations":[{"start":{"line":80,"column":21},"end":{"line":82,"column":7}}]},"9":{"type":"branch","line":88,"loc":{"start":{"line":88,"column":14},"end":{"line":88,"column":31}},"locations":[{"start":{"line":88,"column":14},"end":{"line":88,"column":31}}]},"10":{"type":"branch","line":88,"loc":{"start":{"line":88,"column":24},"end":{"line":88,"column":87}},"locations":[{"start":{"line":88,"column":24},"end":{"line":88,"column":87}}]},"11":{"type":"branch","line":88,"loc":{"start":{"line":88,"column":40},"end":{"line":88,"column":62}},"locations":[{"start":{"line":88,"column":40},"end":{"line":88,"column":62}}]},"12":{"type":"branch","line":88,"loc":{"start":{"line":88,"column":51},"end":{"line":88,"column":87}},"locations":[{"start":{"line":88,"column":51},"end":{"line":88,"column":87}}]},"13":{"type":"branch","line":52,"loc":{"start":{"line":52,"column":9},"end":{"line":57,"column":3}},"locations":[{"start":{"line":52,"column":9},"end":{"line":57,"column":3}}]},"14":{"type":"branch","line":99,"loc":{"start":{"line":99,"column":2},"end":{"line":108,"column":3}},"locations":[{"start":{"line":99,"column":2},"end":{"line":108,"column":3}}]},"15":{"type":"branch","line":100,"loc":{"start":{"line":100,"column":32},"end":{"line":102,"column":5}},"locations":[{"start":{"line":100,"column":32},"end":{"line":102,"column":5}}]},"16":{"type":"branch","line":102,"loc":{"start":{"line":102,"column":4},"end":{"line":105,"column":55}},"locations":[{"start":{"line":102,"column":4},"end":{"line":105,"column":55}}]},"17":{"type":"branch","line":105,"loc":{"start":{"line":105,"column":37},"end":{"line":105,"column":61}},"locations":[{"start":{"line":105,"column":37},"end":{"line":105,"column":61}}]},"18":{"type":"branch","line":106,"loc":{"start":{"line":106,"column":26},"end":{"line":106,"column":50}},"locations":[{"start":{"line":106,"column":26},"end":{"line":106,"column":50}}]},"19":{"type":"branch","line":187,"loc":{"start":{"line":187,"column":0},"end":{"line":258,"column":1}},"locations":[{"start":{"line":187,"column":0},"end":{"line":258,"column":1}}]},"20":{"type":"branch","line":190,"loc":{"start":{"line":190,"column":24},"end":{"line":196,"column":3}},"locations":[{"start":{"line":190,"column":24},"end":{"line":196,"column":3}}]},"21":{"type":"branch","line":196,"loc":{"start":{"line":196,"column":2},"end":{"line":202,"column":30}},"locations":[{"start":{"line":196,"column":2},"end":{"line":202,"column":30}}]},"22":{"type":"branch","line":202,"loc":{"start":{"line":202,"column":17},"end":{"line":202,"column":47}},"locations":[{"start":{"line":202,"column":17},"end":{"line":202,"column":47}}]},"23":{"type":"branch","line":202,"loc":{"start":{"line":202,"column":47},"end":{"line":207,"column":3}},"locations":[{"start":{"line":202,"column":47},"end":{"line":207,"column":3}}]},"24":{"type":"branch","line":207,"loc":{"start":{"line":207,"column":2},"end":{"line":258,"column":1}},"locations":[{"start":{"line":207,"column":2},"end":{"line":258,"column":1}}]},"25":{"type":"branch","line":207,"loc":{"start":{"line":207,"column":2},"end":{"line":246,"column":46}},"locations":[{"start":{"line":207,"column":2},"end":{"line":246,"column":46}}]},"26":{"type":"branch","line":217,"loc":{"start":{"line":217,"column":36},"end":{"line":219,"column":15}},"locations":[{"start":{"line":217,"column":36},"end":{"line":219,"column":15}}]},"27":{"type":"branch","line":219,"loc":{"start":{"line":219,"column":45},"end":{"line":221,"column":15}},"locations":[{"start":{"line":219,"column":45},"end":{"line":221,"column":15}}]},"28":{"type":"branch","line":221,"loc":{"start":{"line":221,"column":4},"end":{"line":243,"column":5}},"locations":[{"start":{"line":221,"column":4},"end":{"line":243,"column":5}}]},"29":{"type":"branch","line":222,"loc":{"start":{"line":222,"column":41},"end":{"line":242,"column":7}},"locations":[{"start":{"line":222,"column":41},"end":{"line":242,"column":7}}]},"30":{"type":"branch","line":225,"loc":{"start":{"line":225,"column":39},"end":{"line":227,"column":19}},"locations":[{"start":{"line":225,"column":39},"end":{"line":227,"column":19}}]},"31":{"type":"branch","line":227,"loc":{"start":{"line":227,"column":8},"end":{"line":239,"column":9}},"locations":[{"start":{"line":227,"column":8},"end":{"line":239,"column":9}}]},"32":{"type":"branch","line":227,"loc":{"start":{"line":227,"column":41},"end":{"line":232,"column":15}},"locations":[{"start":{"line":227,"column":41},"end":{"line":232,"column":15}}]},"33":{"type":"branch","line":232,"loc":{"start":{"line":232,"column":8},"end":{"line":239,"column":9}},"locations":[{"start":{"line":232,"column":8},"end":{"line":239,"column":9}}]},"34":{"type":"branch","line":236,"loc":{"start":{"line":236,"column":34},"end":{"line":236,"column":74}},"locations":[{"start":{"line":236,"column":34},"end":{"line":236,"column":74}}]},"35":{"type":"branch","line":237,"loc":{"start":{"line":237,"column":33},"end":{"line":237,"column":71}},"locations":[{"start":{"line":237,"column":33},"end":{"line":237,"column":71}}]},"36":{"type":"branch","line":246,"loc":{"start":{"line":246,"column":46},"end":{"line":252,"column":3}},"locations":[{"start":{"line":246,"column":46},"end":{"line":252,"column":3}}]},"37":{"type":"branch","line":249,"loc":{"start":{"line":249,"column":38},"end":{"line":251,"column":5}},"locations":[{"start":{"line":249,"column":38},"end":{"line":251,"column":5}}]},"38":{"type":"branch","line":252,"loc":{"start":{"line":252,"column":2},"end":{"line":258,"column":1}},"locations":[{"start":{"line":252,"column":2},"end":{"line":258,"column":1}}]}},"b":{"0":[14],"1":[14],"2":[43],"3":[1],"4":[26],"5":[26],"6":[22],"7":[13],"8":[2],"9":[22],"10":[24],"11":[11],"12":[13],"13":[13],"14":[15],"15":[4],"16":[11],"17":[2],"18":[11],"19":[14],"20":[1],"21":[13],"22":[10],"23":[4],"24":[12],"25":[9],"26":[0],"27":[1],"28":[8],"29":[21],"30":[8],"31":[13],"32":[5],"33":[8],"34":[6],"35":[7],"36":[1],"37":[0],"38":[9]},"fnMap":{"0":{"name":"","decl":{"start":{"line":17,"column":7},"end":{"line":33,"column":1}},"loc":{"start":{"line":17,"column":7},"end":{"line":33,"column":1}},"line":17},"1":{"name":"TerminalConfig","decl":{"start":{"line":20,"column":2},"end":{"line":24,"column":3}},"loc":{"start":{"line":20,"column":2},"end":{"line":24,"column":3}},"line":20},"2":{"name":"get panels","decl":{"start":{"line":26,"column":2},"end":{"line":28,"column":3}},"loc":{"start":{"line":26,"column":2},"end":{"line":28,"column":3}},"line":26},"3":{"name":"get activePanel","decl":{"start":{"line":30,"column":2},"end":{"line":32,"column":3}},"loc":{"start":{"line":30,"column":2},"end":{"line":32,"column":3}},"line":30},"4":{"name":"","decl":{"start":{"line":46,"column":7},"end":{"line":179,"column":1}},"loc":{"start":{"line":46,"column":7},"end":{"line":179,"column":1}},"line":46},"5":{"name":"TerminalPanel","decl":{"start":{"line":67,"column":2},"end":{"line":89,"column":3}},"loc":{"start":{"line":67,"column":2},"end":{"line":89,"column":3}},"line":67},"6":{"name":"resetCount","decl":{"start":{"line":52,"column":9},"end":{"line":57,"column":3}},"loc":{"start":{"line":52,"column":9},"end":{"line":57,"column":3}},"line":52},"7":{"name":"get terminal","decl":{"start":{"line":91,"column":2},"end":{"line":93,"column":3}},"loc":{"start":{"line":91,"column":2},"end":{"line":93,"column":3}},"line":91},"8":{"name":"get process","decl":{"start":{"line":95,"column":2},"end":{"line":97,"column":3}},"loc":{"start":{"line":95,"column":2},"end":{"line":97,"column":3}},"line":95},"9":{"name":"get processOptions","decl":{"start":{"line":99,"column":2},"end":{"line":108,"column":3}},"loc":{"start":{"line":99,"column":2},"end":{"line":108,"column":3}},"line":99},"10":{"name":"get cols","decl":{"start":{"line":111,"column":2},"end":{"line":114,"column":3}},"loc":{"start":{"line":111,"column":2},"end":{"line":114,"column":3}},"line":111},"11":{"name":"get rows","decl":{"start":{"line":116,"column":2},"end":{"line":118,"column":3}},"loc":{"start":{"line":116,"column":2},"end":{"line":118,"column":3}},"line":116},"12":{"name":"reset","decl":{"start":{"line":120,"column":2},"end":{"line":126,"column":3}},"loc":{"start":{"line":120,"column":2},"end":{"line":126,"column":3}},"line":120},"13":{"name":"write","decl":{"start":{"line":128,"column":2},"end":{"line":134,"column":3}},"loc":{"start":{"line":128,"column":2},"end":{"line":134,"column":3}},"line":128},"14":{"name":"onData","decl":{"start":{"line":136,"column":2},"end":{"line":142,"column":3}},"loc":{"start":{"line":136,"column":2},"end":{"line":142,"column":3}},"line":136},"15":{"name":"attachProcess","decl":{"start":{"line":150,"column":2},"end":{"line":156,"column":3}},"loc":{"start":{"line":150,"column":2},"end":{"line":156,"column":3}},"line":150},"16":{"name":"attachTerminal","decl":{"start":{"line":163,"column":2},"end":{"line":178,"column":3}},"loc":{"start":{"line":163,"column":2},"end":{"line":178,"column":3}},"line":163},"17":{"name":"normalizeTerminalConfig","decl":{"start":{"line":187,"column":0},"end":{"line":258,"column":1}},"loc":{"start":{"line":187,"column":0},"end":{"line":258,"column":1}},"line":187}},"f":{"0":14,"1":14,"2":43,"3":1,"4":26,"5":26,"6":13,"7":0,"8":0,"9":15,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":14}} +,"/Users/ari/Git/tutorialkit/packages/runtime/src/webcontainer/utils/files.ts": {"path":"/Users/ari/Git/tutorialkit/packages/runtime/src/webcontainer/utils/files.ts","all":false,"statementMap":{"5":{"start":{"line":6,"column":0},"end":{"line":6,"column":51}},"6":{"start":{"line":7,"column":0},"end":{"line":7,"column":36}},"7":{"start":{"line":8,"column":0},"end":{"line":8,"column":36}},"9":{"start":{"line":10,"column":0},"end":{"line":10,"column":48}},"10":{"start":{"line":11,"column":0},"end":{"line":11,"column":17}},"11":{"start":{"line":12,"column":0},"end":{"line":12,"column":3}},"13":{"start":{"line":14,"column":0},"end":{"line":14,"column":20}},"14":{"start":{"line":15,"column":0},"end":{"line":15,"column":20}},"16":{"start":{"line":17,"column":0},"end":{"line":17,"column":47}},"17":{"start":{"line":18,"column":0},"end":{"line":18,"column":35}},"19":{"start":{"line":20,"column":0},"end":{"line":20,"column":37}},"20":{"start":{"line":21,"column":0},"end":{"line":21,"column":19}},"21":{"start":{"line":22,"column":0},"end":{"line":22,"column":5}},"23":{"start":{"line":24,"column":0},"end":{"line":24,"column":38}},"24":{"start":{"line":25,"column":0},"end":{"line":25,"column":19}},"25":{"start":{"line":26,"column":0},"end":{"line":26,"column":5}},"26":{"start":{"line":27,"column":0},"end":{"line":27,"column":3}},"28":{"start":{"line":29,"column":0},"end":{"line":29,"column":14}},"29":{"start":{"line":30,"column":0},"end":{"line":30,"column":1}},"36":{"start":{"line":37,"column":0},"end":{"line":37,"column":67}},"37":{"start":{"line":38,"column":0},"end":{"line":38,"column":36}},"38":{"start":{"line":39,"column":0},"end":{"line":39,"column":31}},"40":{"start":{"line":41,"column":0},"end":{"line":41,"column":34}},"41":{"start":{"line":42,"column":0},"end":{"line":42,"column":40}},"42":{"start":{"line":43,"column":0},"end":{"line":43,"column":38}},"44":{"start":{"line":45,"column":0},"end":{"line":45,"column":42}},"45":{"start":{"line":46,"column":0},"end":{"line":46,"column":29}},"46":{"start":{"line":47,"column":0},"end":{"line":47,"column":42}},"47":{"start":{"line":48,"column":0},"end":{"line":48,"column":44}},"48":{"start":{"line":49,"column":0},"end":{"line":49,"column":5}},"49":{"start":{"line":50,"column":0},"end":{"line":50,"column":3}},"51":{"start":{"line":52,"column":0},"end":{"line":52,"column":33}},"52":{"start":{"line":53,"column":0},"end":{"line":53,"column":32}},"53":{"start":{"line":54,"column":0},"end":{"line":54,"column":50}},"54":{"start":{"line":55,"column":0},"end":{"line":55,"column":5}},"55":{"start":{"line":56,"column":0},"end":{"line":56,"column":3}},"57":{"start":{"line":58,"column":0},"end":{"line":58,"column":10}},"58":{"start":{"line":59,"column":0},"end":{"line":59,"column":20}},"59":{"start":{"line":60,"column":0},"end":{"line":60,"column":12}},"60":{"start":{"line":61,"column":0},"end":{"line":61,"column":4}},"61":{"start":{"line":62,"column":0},"end":{"line":62,"column":1}},"63":{"start":{"line":64,"column":0},"end":{"line":64,"column":58}},"64":{"start":{"line":65,"column":0},"end":{"line":65,"column":34}},"66":{"start":{"line":67,"column":0},"end":{"line":67,"column":33}},"67":{"start":{"line":68,"column":0},"end":{"line":68,"column":70}},"69":{"start":{"line":70,"column":0},"end":{"line":70,"column":43}},"71":{"start":{"line":72,"column":0},"end":{"line":72,"column":47}},"72":{"start":{"line":73,"column":0},"end":{"line":73,"column":31}},"74":{"start":{"line":75,"column":0},"end":{"line":75,"column":38}},"75":{"start":{"line":76,"column":0},"end":{"line":76,"column":29}},"76":{"start":{"line":77,"column":0},"end":{"line":77,"column":17}},"77":{"start":{"line":78,"column":0},"end":{"line":78,"column":38}},"78":{"start":{"line":79,"column":0},"end":{"line":79,"column":12}},"79":{"start":{"line":80,"column":0},"end":{"line":80,"column":10}},"80":{"start":{"line":81,"column":0},"end":{"line":81,"column":14}},"81":{"start":{"line":82,"column":0},"end":{"line":82,"column":61}},"83":{"start":{"line":84,"column":0},"end":{"line":84,"column":36}},"85":{"start":{"line":86,"column":0},"end":{"line":86,"column":22}},"86":{"start":{"line":87,"column":0},"end":{"line":87,"column":20}},"87":{"start":{"line":88,"column":0},"end":{"line":88,"column":26}},"88":{"start":{"line":89,"column":0},"end":{"line":89,"column":12}},"90":{"start":{"line":91,"column":0},"end":{"line":91,"column":37}},"91":{"start":{"line":92,"column":0},"end":{"line":92,"column":9}},"93":{"start":{"line":94,"column":0},"end":{"line":94,"column":39}},"94":{"start":{"line":95,"column":0},"end":{"line":95,"column":7}},"95":{"start":{"line":96,"column":0},"end":{"line":96,"column":5}},"96":{"start":{"line":97,"column":0},"end":{"line":97,"column":3}},"98":{"start":{"line":99,"column":0},"end":{"line":99,"column":14}},"99":{"start":{"line":100,"column":0},"end":{"line":100,"column":1}},"101":{"start":{"line":102,"column":0},"end":{"line":102,"column":99}},"102":{"start":{"line":103,"column":0},"end":{"line":103,"column":39}},"103":{"start":{"line":104,"column":0},"end":{"line":104,"column":47}},"104":{"start":{"line":105,"column":0},"end":{"line":105,"column":3}},"105":{"start":{"line":106,"column":0},"end":{"line":106,"column":1}}},"s":{"5":1,"6":4,"7":4,"9":4,"10":1,"11":1,"13":3,"14":3,"16":3,"17":3,"19":3,"20":1,"21":1,"23":3,"24":1,"25":1,"26":3,"28":1,"29":1,"36":1,"37":4,"38":4,"40":4,"41":5,"42":5,"44":5,"45":2,"46":5,"47":2,"48":2,"49":5,"51":4,"52":5,"53":2,"54":2,"55":5,"57":4,"58":4,"59":4,"60":4,"61":4,"63":1,"64":3,"66":3,"67":9,"69":9,"71":9,"72":14,"74":14,"75":9,"76":9,"77":9,"78":9,"79":9,"80":14,"81":5,"83":5,"85":5,"86":3,"87":3,"88":3,"90":3,"91":3,"93":5,"94":5,"95":14,"96":9,"98":3,"99":3,"101":5,"102":5,"103":0,"104":0,"105":5},"branchMap":{"0":{"type":"branch","line":6,"loc":{"start":{"line":6,"column":7},"end":{"line":30,"column":1}},"locations":[{"start":{"line":6,"column":7},"end":{"line":30,"column":1}}]},"1":{"type":"branch","line":10,"loc":{"start":{"line":10,"column":47},"end":{"line":12,"column":3}},"locations":[{"start":{"line":10,"column":47},"end":{"line":12,"column":3}}]},"2":{"type":"branch","line":12,"loc":{"start":{"line":12,"column":2},"end":{"line":27,"column":3}},"locations":[{"start":{"line":12,"column":2},"end":{"line":27,"column":3}}]},"3":{"type":"branch","line":20,"loc":{"start":{"line":20,"column":36},"end":{"line":22,"column":5}},"locations":[{"start":{"line":20,"column":36},"end":{"line":22,"column":5}}]},"4":{"type":"branch","line":22,"loc":{"start":{"line":22,"column":4},"end":{"line":24,"column":37}},"locations":[{"start":{"line":22,"column":4},"end":{"line":24,"column":37}}]},"5":{"type":"branch","line":24,"loc":{"start":{"line":24,"column":37},"end":{"line":26,"column":5}},"locations":[{"start":{"line":24,"column":37},"end":{"line":26,"column":5}}]},"6":{"type":"branch","line":27,"loc":{"start":{"line":27,"column":2},"end":{"line":30,"column":1}},"locations":[{"start":{"line":27,"column":2},"end":{"line":30,"column":1}}]},"7":{"type":"branch","line":37,"loc":{"start":{"line":37,"column":7},"end":{"line":62,"column":1}},"locations":[{"start":{"line":37,"column":7},"end":{"line":62,"column":1}}]},"8":{"type":"branch","line":41,"loc":{"start":{"line":41,"column":33},"end":{"line":50,"column":3}},"locations":[{"start":{"line":41,"column":33},"end":{"line":50,"column":3}}]},"9":{"type":"branch","line":45,"loc":{"start":{"line":45,"column":41},"end":{"line":47,"column":15}},"locations":[{"start":{"line":45,"column":41},"end":{"line":47,"column":15}}]},"10":{"type":"branch","line":47,"loc":{"start":{"line":47,"column":4},"end":{"line":49,"column":5}},"locations":[{"start":{"line":47,"column":4},"end":{"line":49,"column":5}}]},"11":{"type":"branch","line":47,"loc":{"start":{"line":47,"column":41},"end":{"line":49,"column":5}},"locations":[{"start":{"line":47,"column":41},"end":{"line":49,"column":5}}]},"12":{"type":"branch","line":52,"loc":{"start":{"line":52,"column":32},"end":{"line":56,"column":3}},"locations":[{"start":{"line":52,"column":32},"end":{"line":56,"column":3}}]},"13":{"type":"branch","line":53,"loc":{"start":{"line":53,"column":31},"end":{"line":55,"column":5}},"locations":[{"start":{"line":53,"column":31},"end":{"line":55,"column":5}}]},"14":{"type":"branch","line":64,"loc":{"start":{"line":64,"column":7},"end":{"line":100,"column":1}},"locations":[{"start":{"line":64,"column":7},"end":{"line":100,"column":1}}]},"15":{"type":"branch","line":67,"loc":{"start":{"line":67,"column":32},"end":{"line":97,"column":3}},"locations":[{"start":{"line":67,"column":32},"end":{"line":97,"column":3}}]},"16":{"type":"branch","line":72,"loc":{"start":{"line":72,"column":46},"end":{"line":96,"column":5}},"locations":[{"start":{"line":72,"column":46},"end":{"line":96,"column":5}}]},"17":{"type":"branch","line":75,"loc":{"start":{"line":75,"column":37},"end":{"line":81,"column":13}},"locations":[{"start":{"line":75,"column":37},"end":{"line":81,"column":13}}]},"18":{"type":"branch","line":81,"loc":{"start":{"line":81,"column":6},"end":{"line":95,"column":7}},"locations":[{"start":{"line":81,"column":6},"end":{"line":95,"column":7}}]},"19":{"type":"branch","line":86,"loc":{"start":{"line":86,"column":21},"end":{"line":92,"column":9}},"locations":[{"start":{"line":86,"column":21},"end":{"line":92,"column":9}}]},"20":{"type":"branch","line":68,"loc":{"start":{"line":68,"column":48},"end":{"line":68,"column":68}},"locations":[{"start":{"line":68,"column":48},"end":{"line":68,"column":68}}]},"21":{"type":"branch","line":102,"loc":{"start":{"line":102,"column":0},"end":{"line":106,"column":1}},"locations":[{"start":{"line":102,"column":0},"end":{"line":106,"column":1}}]},"22":{"type":"branch","line":103,"loc":{"start":{"line":103,"column":6},"end":{"line":103,"column":38}},"locations":[{"start":{"line":103,"column":6},"end":{"line":103,"column":38}}]},"23":{"type":"branch","line":103,"loc":{"start":{"line":103,"column":38},"end":{"line":105,"column":3}},"locations":[{"start":{"line":103,"column":38},"end":{"line":105,"column":3}}]}},"b":{"0":[4],"1":[1],"2":[3],"3":[1],"4":[2],"5":[1],"6":[1],"7":[4],"8":[5],"9":[2],"10":[3],"11":[2],"12":[5],"13":[2],"14":[3],"15":[9],"16":[14],"17":[9],"18":[5],"19":[3],"20":[23],"21":[5],"22":[2],"23":[0]},"fnMap":{"0":{"name":"areFilesEqual","decl":{"start":{"line":6,"column":7},"end":{"line":30,"column":1}},"loc":{"start":{"line":6,"column":7},"end":{"line":30,"column":1}},"line":6},"1":{"name":"diffFiles","decl":{"start":{"line":37,"column":7},"end":{"line":62,"column":1}},"loc":{"start":{"line":37,"column":7},"end":{"line":62,"column":1}},"line":37},"2":{"name":"toFileTree","decl":{"start":{"line":64,"column":7},"end":{"line":100,"column":1}},"loc":{"start":{"line":64,"column":7},"end":{"line":100,"column":1}},"line":64},"3":{"name":"assertDirectoryNode","decl":{"start":{"line":102,"column":0},"end":{"line":106,"column":1}},"loc":{"start":{"line":102,"column":0},"end":{"line":106,"column":1}},"line":102}},"f":{"0":4,"1":4,"2":3,"3":5}} +} diff --git a/packages/runtime/coverage/favicon.png b/packages/runtime/coverage/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..c1525b811a167671e9de1fa78aab9f5c0b61cef7 GIT binary patch literal 445 zcmV;u0Yd(XP))rP{nL}Ln%S7`m{0DjX9TLF* zFCb$4Oi7vyLOydb!7n&^ItCzb-%BoB`=x@N2jll2Nj`kauio%aw_@fe&*}LqlFT43 z8doAAe))z_%=P%v^@JHp3Hjhj^6*Kr_h|g_Gr?ZAa&y>wxHE99Gk>A)2MplWz2xdG zy8VD2J|Uf#EAw*bo5O*PO_}X2Tob{%bUoO2G~T`@%S6qPyc}VkhV}UifBuRk>%5v( z)x7B{I~z*k<7dv#5tC+m{km(D087J4O%+<<;K|qwefb6@GSX45wCK}Sn*> + + + + Code coverage report for All files + + + + + + + + + +
+
+

All files

+
+ +
+ 42.23% + Statements + 628/1487 +
+ + +
+ 71.87% + Branches + 138/192 +
+ + +
+ 58% + Functions + 58/100 +
+ + +
+ 42.23% + Lines + 628/1487 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
src +
+
55.82%254/45544.77%30/6763.15%24/3855.82%254/455
src/store +
+
5.48%29/52957.14%4/725%3/125.48%29/529
src/utils +
+
52.63%30/5750%3/622.22%2/952.63%30/57
src/webcontainer +
+
65.32%243/37288.63%78/8867.56%25/3765.32%243/372
src/webcontainer/utils +
+
97.29%72/7495.83%23/24100%4/497.29%72/74
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/runtime/coverage/prettify.css b/packages/runtime/coverage/prettify.css new file mode 100644 index 00000000..b317a7cd --- /dev/null +++ b/packages/runtime/coverage/prettify.css @@ -0,0 +1 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/packages/runtime/coverage/prettify.js b/packages/runtime/coverage/prettify.js new file mode 100644 index 00000000..b3225238 --- /dev/null +++ b/packages/runtime/coverage/prettify.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/packages/runtime/coverage/sort-arrow-sprite.png b/packages/runtime/coverage/sort-arrow-sprite.png new file mode 100644 index 0000000000000000000000000000000000000000..6ed68316eb3f65dec9063332d2f69bf3093bbfab GIT binary patch literal 138 zcmeAS@N?(olHy`uVBq!ia0vp^>_9Bd!3HEZxJ@+%Qh}Z>jv*C{$p!i!8j}?a+@3A= zIAGwzjijN=FBi!|L1t?LM;Q;gkwn>2cAy-KV{dn nf0J1DIvEHQu*n~6U}x}qyky7vi4|9XhBJ7&`njxgN@xNA8m%nc literal 0 HcmV?d00001 diff --git a/packages/runtime/coverage/sorter.js b/packages/runtime/coverage/sorter.js new file mode 100644 index 00000000..2bb296a8 --- /dev/null +++ b/packages/runtime/coverage/sorter.js @@ -0,0 +1,196 @@ +/* eslint-disable */ +var addSorting = (function() { + 'use strict'; + var cols, + currentSort = { + index: 0, + desc: false + }; + + // returns the summary table element + function getTable() { + return document.querySelector('.coverage-summary'); + } + // returns the thead element of the summary table + function getTableHeader() { + return getTable().querySelector('thead tr'); + } + // returns the tbody element of the summary table + function getTableBody() { + return getTable().querySelector('tbody'); + } + // returns the th element for nth column + function getNthColumn(n) { + return getTableHeader().querySelectorAll('th')[n]; + } + + function onFilterInput() { + const searchValue = document.getElementById('fileSearch').value; + const rows = document.getElementsByTagName('tbody')[0].children; + for (let i = 0; i < rows.length; i++) { + const row = rows[i]; + if ( + row.textContent + .toLowerCase() + .includes(searchValue.toLowerCase()) + ) { + row.style.display = ''; + } else { + row.style.display = 'none'; + } + } + } + + // loads the search box + function addSearchBox() { + var template = document.getElementById('filterTemplate'); + var templateClone = template.content.cloneNode(true); + templateClone.getElementById('fileSearch').oninput = onFilterInput; + template.parentElement.appendChild(templateClone); + } + + // loads all columns + function loadColumns() { + var colNodes = getTableHeader().querySelectorAll('th'), + colNode, + cols = [], + col, + i; + + for (i = 0; i < colNodes.length; i += 1) { + colNode = colNodes[i]; + col = { + key: colNode.getAttribute('data-col'), + sortable: !colNode.getAttribute('data-nosort'), + type: colNode.getAttribute('data-type') || 'string' + }; + cols.push(col); + if (col.sortable) { + col.defaultDescSort = col.type === 'number'; + colNode.innerHTML = + colNode.innerHTML + ''; + } + } + return cols; + } + // attaches a data attribute to every tr element with an object + // of data values keyed by column name + function loadRowData(tableRow) { + var tableCols = tableRow.querySelectorAll('td'), + colNode, + col, + data = {}, + i, + val; + for (i = 0; i < tableCols.length; i += 1) { + colNode = tableCols[i]; + col = cols[i]; + val = colNode.getAttribute('data-value'); + if (col.type === 'number') { + val = Number(val); + } + data[col.key] = val; + } + return data; + } + // loads all row data + function loadData() { + var rows = getTableBody().querySelectorAll('tr'), + i; + + for (i = 0; i < rows.length; i += 1) { + rows[i].data = loadRowData(rows[i]); + } + } + // sorts the table using the data for the ith column + function sortByIndex(index, desc) { + var key = cols[index].key, + sorter = function(a, b) { + a = a.data[key]; + b = b.data[key]; + return a < b ? -1 : a > b ? 1 : 0; + }, + finalSorter = sorter, + tableBody = document.querySelector('.coverage-summary tbody'), + rowNodes = tableBody.querySelectorAll('tr'), + rows = [], + i; + + if (desc) { + finalSorter = function(a, b) { + return -1 * sorter(a, b); + }; + } + + for (i = 0; i < rowNodes.length; i += 1) { + rows.push(rowNodes[i]); + tableBody.removeChild(rowNodes[i]); + } + + rows.sort(finalSorter); + + for (i = 0; i < rows.length; i += 1) { + tableBody.appendChild(rows[i]); + } + } + // removes sort indicators for current column being sorted + function removeSortIndicators() { + var col = getNthColumn(currentSort.index), + cls = col.className; + + cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); + col.className = cls; + } + // adds sort indicators for current column being sorted + function addSortIndicators() { + getNthColumn(currentSort.index).className += currentSort.desc + ? ' sorted-desc' + : ' sorted'; + } + // adds event listeners for all sorter widgets + function enableUI() { + var i, + el, + ithSorter = function ithSorter(i) { + var col = cols[i]; + + return function() { + var desc = col.defaultDescSort; + + if (currentSort.index === i) { + desc = !currentSort.desc; + } + sortByIndex(i, desc); + removeSortIndicators(); + currentSort.index = i; + currentSort.desc = desc; + addSortIndicators(); + }; + }; + for (i = 0; i < cols.length; i += 1) { + if (cols[i].sortable) { + // add the click event handler on the th so users + // dont have to click on those tiny arrows + el = getNthColumn(i).querySelector('.sorter').parentElement; + if (el.addEventListener) { + el.addEventListener('click', ithSorter(i)); + } else { + el.attachEvent('onclick', ithSorter(i)); + } + } + } + } + // adds sorting functionality to the UI + return function() { + if (!getTable()) { + return; + } + cols = loadColumns(); + loadData(); + addSearchBox(); + addSortIndicators(); + enableUI(); + }; +})(); + +window.addEventListener('load', addSorting); diff --git a/packages/runtime/coverage/src/index.html b/packages/runtime/coverage/src/index.html new file mode 100644 index 00000000..a0f242ce --- /dev/null +++ b/packages/runtime/coverage/src/index.html @@ -0,0 +1,161 @@ + + + + + + Code coverage report for src + + + + + + + + + +
+
+

All files src

+
+ +
+ 55.82% + Statements + 254/455 +
+ + +
+ 44.77% + Branches + 30/67 +
+ + +
+ 63.15% + Functions + 24/38 +
+ + +
+ 55.82% + Lines + 254/455 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.ts +
+
0%0/10%0/10%0/10%0/1
lesson-files.ts +
+
76.03%92/12151.72%15/29100%11/1176.03%92/121
tasks.ts +
+
64%16/2575%3/433.33%1/364%16/25
tutorial-runner.ts +
+
47.4%146/30836.36%12/3352.17%12/2347.4%146/308
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/runtime/coverage/src/index.ts.html b/packages/runtime/coverage/src/index.ts.html new file mode 100644 index 00000000..9f849d3a --- /dev/null +++ b/packages/runtime/coverage/src/index.ts.html @@ -0,0 +1,100 @@ + + + + + + Code coverage report for src/index.ts + + + + + + + + + +
+
+

All files / src index.ts

+
+ +
+ 0% + Statements + 0/1 +
+ + +
+ 0% + Branches + 0/1 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 0% + Lines + 0/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6  +  +  +  +  + 
export { LessonFilesFetcher } from './lesson-files.js';
+export { TutorialRunner } from './tutorial-runner.js';
+export type { Command, Commands, PreviewInfo, Step, Steps } from './webcontainer/index.js';
+export { safeBoot } from './webcontainer/index.js';
+export { TutorialStore } from './store/index.js';
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/runtime/coverage/src/lesson-files.ts.html b/packages/runtime/coverage/src/lesson-files.ts.html new file mode 100644 index 00000000..eec96f36 --- /dev/null +++ b/packages/runtime/coverage/src/lesson-files.ts.html @@ -0,0 +1,613 @@ + + + + + + Code coverage report for src/lesson-files.ts + + + + + + + + + +
+
+

All files / src lesson-files.ts

+
+ +
+ 76.03% + Statements + 92/121 +
+ + +
+ 51.72% + Branches + 15/29 +
+ + +
+ 100% + Functions + 11/11 +
+ + +
+ 76.03% + Lines + 92/121 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +1771x +1x +1x +  +  +  +  +  +  +  +  +1x +6x +6x +6x +  +6x +6x +1x +1x +6x +  +6x +2x +1x +1x +  +1x +  +1x +  +2x +  +2x +1x +1x +  +1x +1x +1x +1x +2x +  +6x +2x +  +2x +  +  +  +2x +  +  +  +2x +  +2x +2x +  +6x +2x +2x +  +6x +1x +1x +  +6x +2x +  +2x +2x +  +2x +  +  +  +2x +  +2x +  +2x +  +2x +2x +  +2x +2x +  +2x +2x +  +6x +  +3x +  +  +  +3x +  +3x +  +  +  +3x +  +3x +3x +  +6x +4x +  +4x +4x +4x +  +4x +  +  +  +4x +  +4x +  +4x +4x +  +  +  +  +  +  +  +  +  +  +  +  +4x +6x +  +6x +6x +  +6x +  +  +  +6x +6x +  +6x +  +6x +  +6x +6x +6x +  +6x +6x +  +6x +6x +  +1x +1x +  +  +  +1x +1x +1x +  +  +  + 
import type { Files, FilesRefList, Lesson } from '@tutorialkit/types';
+import { newTask, type Task } from './tasks.js';
+import { wait } from './utils/promises.js';
+ 
+type InvalidationResult =
+  | {
+      type: 'template' | 'files' | 'solution';
+      files: Files;
+    }
+  | { type: 'none' };
+ 
+export class LessonFilesFetcher {
+  private _map = new Map<string, Files>();
+  private _templateLoadTask?: Task<Files>;
+  private _templateLoaded: string | undefined;
+ 
+  constructor(private _basePathname: string = '/') {
+    if (!this._basePathname.endsWith('/')) {
+      this._basePathname = this._basePathname + '/';
+    }
+  }
+ 
+  async invalidate(filesRef: string): Promise<InvalidationResult> {
+    if (!this._map.has(filesRef)) {
+      return { type: 'none' };
+    }
+ 
+    const type = getTypeFromFilesRef(filesRef);
+ 
+    let files: Files;
+ 
+    if (this._templateLoaded === filesRef) {
+      files = await this._fetchTemplate(filesRef).promise;
+    } else {
+      files = await this._fetchFiles(filesRef);
+    }
+ 
+    return {
+      type,
+      files,
+    };
+  }
+ 
+  async getLessonTemplate(lesson: Lesson): Promise<Files> {
+    const templatePathname = `template-${lesson.data.template}.json`;
+ 
+    if (this._map.has(templatePathname)) {
+      return this._map.get(templatePathname)!;
+    }
+ 
+    if (this._templateLoadTask && this._templateLoaded === templatePathname) {
+      return this._templateLoadTask.promise;
+    }
+ 
+    const task = this._fetchTemplate(templatePathname);
+ 
+    return task.promise;
+  }
+ 
+  getLessonFiles(lesson: Lesson): Promise<Files> {
+    return this._getFilesFromFilesRefList(lesson.files);
+  }
+ 
+  getLessonSolution(lesson: Lesson): Promise<Files> {
+    return this._getFilesFromFilesRefList(lesson.solution);
+  }
+ 
+  private _fetchTemplate(templatePathname: string) {
+    this._templateLoadTask?.cancel();
+ 
+    const task = newTask(async (signal) => {
+      const response = await fetch(`${this._basePathname}${templatePathname}`, { signal });
+ 
+      if (!response.ok) {
+        throw new Error(`Failed to fetch: status ${response.status}`);
+      }
+ 
+      const body = convertToFiles(await response.json());
+ 
+      this._map.set(templatePathname, body);
+ 
+      signal.throwIfAborted();
+ 
+      return body;
+    });
+ 
+    this._templateLoadTask = task;
+    this._templateLoaded = templatePathname;
+ 
+    return task;
+  }
+ 
+  private async _getFilesFromFilesRefList(filesRefList: FilesRefList): Promise<Files> {
+    // the ref does not have any content
+    if (filesRefList[1].length === 0) {
+      return {};
+    }
+ 
+    const pathname = filesRefList[0];
+ 
+    if (this._map.has(pathname)) {
+      return this._map.get(pathname)!;
+    }
+ 
+    const promise = this._fetchFiles(pathname);
+ 
+    return promise;
+  }
+ 
+  private async _fetchFiles(pathname: string): Promise<Files> {
+    let retry = 2;
+ 
+    while (true) {
+      try {
+        const response = await fetch(`${this._basePathname}${pathname}`);
+ 
+        if (!response.ok) {
+          throw new Error(`Failed to fetch ${pathname}: ${response.status} ${response.statusText}`);
+        }
+ 
+        const body = convertToFiles(await response.json());
+ 
+        this._map.set(pathname, body);
+ 
+        return body;
+      } catch (error) {
+        if (retry <= 0) {
+          console.error(`Failed to fetch ${pathname} after 3 attempts.`);
+          console.error(error);
+ 
+          return {};
+        }
+      }
+ 
+      retry -= 1;
+ 
+      await wait(1000);
+    }
+  }
+}
+ 
+function convertToFiles(json: Record<string, string | { base64: string }>): Files {
+  const result: Files = {};
+ 
+  if (typeof json !== 'object') {
+    return result;
+  }
+ 
+  for (const property in json) {
+    const value = json[property];
+ 
+    let transformedValue;
+ 
+    if (typeof value === 'object') {
+      transformedValue = Uint8Array.from(atob(value.base64), (char) => char.charCodeAt(0));
+    } else {
+      transformedValue = value;
+    }
+ 
+    result[property] = transformedValue;
+  }
+ 
+  return result;
+}
+ 
+function getTypeFromFilesRef(filesRef: string): 'template' | 'files' | 'solution' {
+  if (filesRef.startsWith('template-')) {
+    return 'template';
+  }
+ 
+  if (filesRef.endsWith('files.json')) {
+    return 'files';
+  }
+ 
+  return 'solution';
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/runtime/coverage/src/store/editor.ts.html b/packages/runtime/coverage/src/store/editor.ts.html new file mode 100644 index 00000000..4b1aca5f --- /dev/null +++ b/packages/runtime/coverage/src/store/editor.ts.html @@ -0,0 +1,499 @@ + + + + + + Code coverage report for src/store/editor.ts + + + + + + + + + +
+
+

All files / src/store editor.ts

+
+ +
+ 0% + Statements + 0/95 +
+ + +
+ 0% + Branches + 0/1 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 0% + Lines + 0/95 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import type { FilesRefList, Files } from '@tutorialkit/types';
+import { atom, map, computed } from 'nanostores';
+ 
+export interface EditorDocument {
+  value: string | Uint8Array;
+  loading: boolean;
+  filePath: string;
+  scroll?: ScrollPosition;
+}
+ 
+export interface ScrollPosition {
+  top: number;
+  left: number;
+}
+ 
+export type EditorDocuments = Record<string, EditorDocument>;
+ 
+export class EditorStore {
+  selectedFile = atom<string | undefined>();
+  documents = map<EditorDocuments>({});
+ 
+  currentDocument = computed([this.documents, this.selectedFile], (documents, selectedFile) => {
+    if (!selectedFile) {
+      return undefined;
+    }
+ 
+    return documents[selectedFile];
+  });
+ 
+  setSelectedFile(filePath: string | undefined) {
+    this.selectedFile.set(filePath);
+  }
+ 
+  setDocuments(files: FilesRefList | Files) {
+    // check if it is a FilesRef
+    if (Array.isArray(files)) {
+      this.documents.set(
+        Object.fromEntries(
+          files[1].map((filePath) => {
+            return [
+              filePath,
+              {
+                value: '',
+                loading: true,
+                filePath,
+              },
+            ];
+          }),
+        ),
+      );
+    } else {
+      const previousDocuments = this.documents.value;
+ 
+      this.documents.set(
+        Object.fromEntries(
+          Object.entries(files).map(([filePath, value]) => {
+            return [
+              filePath,
+              {
+                value,
+                loading: false,
+                filePath,
+                scroll: previousDocuments?.[filePath]?.scroll,
+              },
+            ];
+          }),
+        ) satisfies EditorDocuments,
+      );
+    }
+  }
+ 
+  updateScrollPosition(filePath: string, position: ScrollPosition) {
+    const documentState = this.documents.get()[filePath];
+ 
+    if (!documentState) {
+      return;
+    }
+ 
+    this.documents.setKey(filePath, {
+      ...documentState,
+      scroll: position,
+    });
+  }
+ 
+  updateFile(filePath: string, content: string): boolean {
+    const documentState = this.documents.get()[filePath];
+ 
+    if (!documentState) {
+      return false;
+    }
+ 
+    const currentContent = documentState.value;
+    const contentChanged = currentContent !== content;
+ 
+    if (contentChanged) {
+      this.documents.setKey(filePath, {
+        ...documentState,
+        value: content,
+      });
+    }
+ 
+    return contentChanged;
+  }
+ 
+  onDocumentChanged(filePath: string, callback: (document: Readonly<EditorDocument>) => void) {
+    const unsubscribeFromCurrentDocument = this.currentDocument.subscribe((document) => {
+      if (document?.filePath === filePath) {
+        callback(document);
+      }
+    });
+ 
+    const unsubscribeFromDocuments = this.documents.subscribe((documents) => {
+      const document = documents[filePath];
+ 
+      /**
+       * We grab the document from the store, but only call the callback if it is not loading anymore which means
+       * the content is loaded.
+       */
+      if (document && !document.loading) {
+        /**
+         * Call this in a `queueMicrotask` because the subscribe callback is called synchronoulsy,
+         * which causes the `unsubscribeFromDocuments` to not exist yet.
+         */
+        queueMicrotask(() => {
+          callback(document);
+ 
+          unsubscribeFromDocuments();
+        });
+      }
+    });
+ 
+    return () => {
+      unsubscribeFromDocuments();
+ 
+      unsubscribeFromCurrentDocument();
+    };
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/runtime/coverage/src/store/index.html b/packages/runtime/coverage/src/store/index.html new file mode 100644 index 00000000..5c3dc234 --- /dev/null +++ b/packages/runtime/coverage/src/store/index.html @@ -0,0 +1,161 @@ + + + + + + Code coverage report for src/store + + + + + + + + + +
+
+

All files src/store

+
+ +
+ 5.48% + Statements + 29/529 +
+ + +
+ 57.14% + Branches + 4/7 +
+ + +
+ 25% + Functions + 3/12 +
+ + +
+ 5.48% + Lines + 29/529 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
editor.ts +
+
0%0/950%0/10%0/10%0/95
index.ts +
+
0%0/2510%0/10%0/10%0/251
previews.ts +
+
0%0/670%0/10%0/10%0/67
terminal.ts +
+
25%29/116100%4/433.33%3/925%29/116
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/runtime/coverage/src/store/index.ts.html b/packages/runtime/coverage/src/store/index.ts.html new file mode 100644 index 00000000..0114a4c4 --- /dev/null +++ b/packages/runtime/coverage/src/store/index.ts.html @@ -0,0 +1,1174 @@ + + + + + + Code coverage report for src/store/index.ts + + + + + + + + + +
+
+

All files / src/store index.ts

+
+ +
+ 0% + Statements + 0/251 +
+ + +
+ 0% + Branches + 0/1 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 0% + Lines + 0/251 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import type { Files, Lesson } from '@tutorialkit/types';
+import type { WebContainer } from '@webcontainer/api';
+import { atom, type ReadableAtom } from 'nanostores';
+import { LessonFilesFetcher } from '../lesson-files.js';
+import { newTask, type Task } from '../tasks.js';
+import { TutorialRunner } from '../tutorial-runner.js';
+import type { ITerminal } from '../utils/terminal.js';
+import { bootStatus, unblockBoot, type BootStatus } from '../webcontainer/on-demand-boot.js';
+import type { PreviewInfo } from '../webcontainer/preview-info.js';
+import { StepsController } from '../webcontainer/steps.js';
+import type { TerminalConfig } from '../webcontainer/terminal-config.js';
+import { EditorStore, type EditorDocument, type EditorDocuments, type ScrollPosition } from './editor.js';
+import { PreviewsStore } from './previews.js';
+import { TerminalStore } from './terminal.js';
+ 
+interface StoreOptions {
+  webcontainer: Promise<WebContainer>;
+ 
+  /**
+   * Whether or not authentication is used for the WebContainer API.
+   */
+  useAuth: boolean;
+ 
+  /**
+   * The base path to use when fetching files.
+   */
+  basePathname?: string;
+}
+ 
+export class TutorialStore {
+  private _webcontainer: Promise<WebContainer>;
+ 
+  private _runner: TutorialRunner;
+  private _previewsStore: PreviewsStore;
+  private _editorStore: EditorStore;
+  private _terminalStore: TerminalStore;
+ 
+  private _stepController = new StepsController();
+  private _lessonFilesFetcher: LessonFilesFetcher;
+  private _lessonTask: Task<unknown> | undefined;
+  private _lesson: Lesson | undefined;
+  private _ref: number = 1;
+  private _themeRef = atom(1);
+ 
+  private _lessonFiles: Files | undefined;
+  private _lessonSolution: Files | undefined;
+  private _lessonTemplate: Files | undefined;
+ 
+  /**
+   * Whether or not the current lesson is fully loaded in WebContainer
+   * and in every stores.
+   */
+  readonly lessonFullyLoaded = atom<boolean>(false);
+ 
+  constructor({ useAuth, webcontainer, basePathname }: StoreOptions) {
+    this._webcontainer = webcontainer;
+    this._editorStore = new EditorStore();
+    this._lessonFilesFetcher = new LessonFilesFetcher(basePathname);
+    this._previewsStore = new PreviewsStore(this._webcontainer);
+    this._terminalStore = new TerminalStore(this._webcontainer, useAuth);
+    this._runner = new TutorialRunner(this._webcontainer, this._terminalStore, this._stepController);
+ 
+    /**
+     * By having this code under `import.meta.hot`, it gets:
+     *  - ignored on server side where it shouldn't run
+     *  - discarded when doing a production build
+     */
+    if (import.meta.hot) {
+      import.meta.hot.on('tk:refresh-wc-files', async (hotFilesRefs: string[]) => {
+        let shouldUpdate = false;
+ 
+        for (const filesRef of hotFilesRefs) {
+          const result = await this._lessonFilesFetcher.invalidate(filesRef);
+ 
+          switch (result.type) {
+            case 'none': {
+              break;
+            }
+            case 'files': {
+              if (this._lesson?.files[0] === filesRef) {
+                shouldUpdate = true;
+ 
+                this._lesson.files[1] = Object.keys(result.files).sort();
+                this._lessonFiles = result.files;
+              }
+ 
+              break;
+            }
+            case 'solution': {
+              if (this._lesson?.solution[0] === filesRef) {
+                shouldUpdate = true;
+ 
+                this._lesson.solution[1] = Object.keys(result.files).sort();
+                this._lessonSolution = result.files;
+              }
+ 
+              break;
+            }
+            case 'template': {
+              shouldUpdate = true;
+ 
+              this._lessonTemplate = result.files;
+ 
+              break;
+            }
+          }
+        }
+ 
+        if (shouldUpdate && this._lesson) {
+          this._lessonTask?.cancel();
+ 
+          const files = this._lessonFiles ?? {};
+          const template = this._lessonTemplate;
+ 
+          this._lessonTask = newTask(
+            async (signal) => {
+              const preparePromise = this._runner.prepareFiles({ template, files, signal });
+ 
+              this._runner.runCommands();
+              this._editorStore.setDocuments(files);
+ 
+              await preparePromise;
+            },
+            { ignoreCancel: true },
+          );
+        }
+      });
+    }
+  }
+ 
+  setLesson(lesson: Lesson, options: { ssr?: boolean } = {}) {
+    if (lesson === this._lesson) {
+      return;
+    }
+ 
+    this._lessonTask?.cancel();
+ 
+    this._ref += 1;
+    this._lesson = lesson;
+    this.lessonFullyLoaded.set(false);
+ 
+    this._previewsStore.setPreviews(lesson.data.previews ?? true);
+    this._terminalStore.setTerminalConfiguration(lesson.data.terminal);
+    this._runner.setCommands(lesson.data);
+    this._editorStore.setDocuments(lesson.files);
+ 
+    if (options.ssr) {
+      return;
+    }
+ 
+    this._lessonTask = newTask(
+      async (signal) => {
+        const templatePromise = this._lessonFilesFetcher.getLessonTemplate(lesson);
+        const filesPromise = this._lessonFilesFetcher.getLessonFiles(lesson);
+ 
+        const preparePromise = this._runner.prepareFiles({ template: templatePromise, files: filesPromise, signal });
+ 
+        this._runner.runCommands();
+ 
+        const [template, solution, files] = await Promise.all([
+          templatePromise,
+          this._lessonFilesFetcher.getLessonSolution(lesson),
+          filesPromise,
+        ]);
+ 
+        signal.throwIfAborted();
+ 
+        this._lessonTemplate = template;
+        this._lessonFiles = files;
+        this._lessonSolution = solution;
+ 
+        this._editorStore.setDocuments(files);
+ 
+        if (lesson.data.focus === undefined) {
+          this._editorStore.setSelectedFile(undefined);
+        } else if (files[lesson.data.focus] !== undefined) {
+          this._editorStore.setSelectedFile(lesson.data.focus);
+        }
+ 
+        await preparePromise;
+ 
+        signal.throwIfAborted();
+ 
+        this.lessonFullyLoaded.set(true);
+      },
+      { ignoreCancel: true },
+    );
+  }
+ 
+  get previews(): ReadableAtom<PreviewInfo[]> {
+    return this._previewsStore.previews;
+  }
+ 
+  get terminalConfig(): ReadableAtom<TerminalConfig> {
+    return this._terminalStore.terminalConfig;
+  }
+ 
+  get currentDocument(): ReadableAtom<EditorDocument | undefined> {
+    return this._editorStore.currentDocument;
+  }
+ 
+  get bootStatus(): ReadableAtom<BootStatus> {
+    return bootStatus;
+  }
+ 
+  get documents(): ReadableAtom<EditorDocuments> {
+    return this._editorStore.documents;
+  }
+ 
+  get template(): Files | undefined {
+    return this._lessonTemplate;
+  }
+ 
+  get selectedFile(): ReadableAtom<string | undefined> {
+    return this._editorStore.selectedFile;
+  }
+ 
+  get lesson(): Readonly<Lesson> | undefined {
+    return this._lesson;
+  }
+ 
+  get ref(): unknown {
+    return this._ref;
+  }
+ 
+  get themeRef(): ReadableAtom<unknown> {
+    return this._themeRef;
+  }
+ 
+  /**
+   * Steps that the runner is or will be executing.
+   */
+  get steps() {
+    return this._stepController.steps;
+  }
+ 
+  hasFileTree(): boolean {
+    if (!this._lesson) {
+      return false;
+    }
+ 
+    const { editor } = this._lesson.data;
+ 
+    return editor === undefined || editor === true || (editor !== false && editor?.fileTree !== false);
+  }
+ 
+  hasEditor(): boolean {
+    if (!this._lesson) {
+      return false;
+    }
+ 
+    const { editor } = this._lesson.data;
+ 
+    return editor !== false;
+  }
+ 
+  hasPreviews(): boolean {
+    if (!this._lesson) {
+      return false;
+    }
+ 
+    const { previews } = this._lesson.data;
+ 
+    return previews !== false;
+  }
+ 
+  hasTerminalPanel(): boolean {
+    return this._terminalStore.hasTerminalPanel();
+  }
+ 
+  hasSolution(): boolean {
+    return !!this._lesson && Object.keys(this._lesson.solution[1]).length >= 1;
+  }
+ 
+  unblockBoot() {
+    unblockBoot();
+  }
+ 
+  reset() {
+    const isReady = this.lessonFullyLoaded.value;
+ 
+    if (!isReady || !this._lessonFiles) {
+      return;
+    }
+ 
+    this._editorStore.setDocuments(this._lessonFiles);
+    this._runner.updateFiles(this._lessonFiles);
+  }
+ 
+  solve() {
+    const isReady = this.lessonFullyLoaded.value;
+ 
+    if (!isReady || !this._lessonSolution) {
+      return;
+    }
+ 
+    const files = { ...this._lessonFiles, ...this._lessonSolution };
+ 
+    this._editorStore.setDocuments(files);
+    this._runner.updateFiles(files);
+  }
+ 
+  setSelectedFile(filePath: string | undefined) {
+    this._editorStore.setSelectedFile(filePath);
+  }
+ 
+  updateFile(filePath: string, content: string) {
+    const hasChanged = this._editorStore.updateFile(filePath, content);
+ 
+    if (hasChanged) {
+      this._runner.updateFile(filePath, content);
+    }
+  }
+ 
+  updateFiles(files: Files) {
+    this._runner.updateFiles(files);
+  }
+ 
+  setCurrentDocumentContent(newContent: string) {
+    const filePath = this.currentDocument.get()?.filePath;
+ 
+    if (!filePath) {
+      return;
+    }
+ 
+    this.updateFile(filePath, newContent);
+  }
+ 
+  setCurrentDocumentScrollPosition(position: ScrollPosition) {
+    const editorDocument = this.currentDocument.get();
+ 
+    if (!editorDocument) {
+      return;
+    }
+ 
+    const { filePath } = editorDocument;
+ 
+    this._editorStore.updateScrollPosition(filePath, position);
+  }
+ 
+  attachTerminal(id: string, terminal: ITerminal) {
+    this._terminalStore.attachTerminal(id, terminal);
+  }
+ 
+  onTerminalResize(cols: number, rows: number) {
+    if (cols && rows) {
+      this._terminalStore.onTerminalResize(cols, rows);
+      this._runner.onTerminalResize(cols, rows);
+    }
+  }
+ 
+  onDocumentChanged(filePath: string, callback: (document: Readonly<EditorDocument>) => void) {
+    return this._editorStore.onDocumentChanged(filePath, callback);
+  }
+ 
+  refreshStyles() {
+    this._themeRef.set(this._themeRef.get() + 1);
+  }
+ 
+  takeSnapshot() {
+    return this._runner.takeSnapshot();
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/runtime/coverage/src/store/previews.ts.html b/packages/runtime/coverage/src/store/previews.ts.html new file mode 100644 index 00000000..847c0d1c --- /dev/null +++ b/packages/runtime/coverage/src/store/previews.ts.html @@ -0,0 +1,400 @@ + + + + + + Code coverage report for src/store/previews.ts + + + + + + + + + +
+
+

All files / src/store previews.ts

+
+ +
+ 0% + Statements + 0/67 +
+ + +
+ 0% + Branches + 0/1 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 0% + Lines + 0/67 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import type { PreviewSchema } from '@tutorialkit/types';
+import { atom } from 'nanostores';
+import { PreviewInfo } from '../webcontainer/preview-info.js';
+import type { WebContainer } from '@webcontainer/api';
+ 
+export class PreviewsStore {
+  private _availablePreviews: PreviewInfo[] = [];
+  private _previewsLayout: PreviewInfo[] = [];
+ 
+  /**
+   * Atom representing the current previews. If it's an empty array or none of
+   * the previews are ready, then no preview can be shown.
+   */
+  previews = atom<PreviewInfo[]>([]);
+ 
+  constructor(webcontainerPromise: Promise<WebContainer>) {
+    this._init(webcontainerPromise);
+  }
+ 
+  private async _init(webcontainerPromise: Promise<WebContainer>) {
+    const webcontainer = await webcontainerPromise;
+ 
+    webcontainer.on('port', (port, type, url) => {
+      const previewInfos = this._availablePreviews.filter((preview) => preview.port === port);
+ 
+      if (previewInfos.length === 0) {
+        const info = new PreviewInfo(port, type === 'open');
+        previewInfos.push(info);
+        this._availablePreviews.push(info);
+      }
+ 
+      previewInfos.forEach((info) => {
+        info.ready = type === 'open';
+        info.baseUrl = url;
+      });
+ 
+      if (this._previewsLayout.length === 0) {
+        this.previews.set(previewInfos);
+      } else {
+        this._previewsLayout = [...this._previewsLayout];
+        this.previews.set(this._previewsLayout);
+      }
+    });
+  }
+ 
+  /**
+   * Set the expected port for the preview to show. If this is not set,
+   * the port of the first server that is ready will be used.
+   */
+  setPreviews(config: PreviewSchema) {
+    if (config === false) {
+      // clear the previews if they are turned off
+      this.previews.set([]);
+ 
+      return;
+    }
+ 
+    // if the schema is `true`, we just use the default empty array
+    const previews = config === true ? [] : config ?? [];
+ 
+    const previewInfos = previews.map((preview) => {
+      const info = new PreviewInfo(preview);
+ 
+      let previewInfo = this._availablePreviews.find((availablePreview) => PreviewInfo.equals(info, availablePreview));
+ 
+      if (!previewInfo) {
+        previewInfo = info;
+ 
+        this._availablePreviews.push(previewInfo);
+      }
+ 
+      return previewInfo;
+    });
+ 
+    let areDifferent = previewInfos.length != this._previewsLayout.length;
+ 
+    if (!areDifferent) {
+      for (let i = 0; i < previewInfos.length; i++) {
+        areDifferent = !PreviewInfo.equals(previewInfos[i], this._previewsLayout[i]);
+ 
+        if (areDifferent) {
+          break;
+        }
+      }
+    }
+ 
+    if (!areDifferent) {
+      return;
+    }
+ 
+    this._previewsLayout = previewInfos;
+ 
+    /**
+     * If a port is provided and the preview is already ready we update the previewUrl.
+     * If no port is provided we default to the first preview ever to ready if there are any.
+     */
+    if (previews.length === 0) {
+      const firstPreview = this._availablePreviews.values().next().value as PreviewInfo | undefined;
+ 
+      this.previews.set(firstPreview ? [firstPreview] : []);
+    } else {
+      this.previews.set(this._previewsLayout);
+    }
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/runtime/coverage/src/store/terminal.ts.html b/packages/runtime/coverage/src/store/terminal.ts.html new file mode 100644 index 00000000..41826ef6 --- /dev/null +++ b/packages/runtime/coverage/src/store/terminal.ts.html @@ -0,0 +1,571 @@ + + + + + + Code coverage report for src/store/terminal.ts + + + + + + + + + +
+
+

All files / src/store terminal.ts

+
+ +
+ 25% + Statements + 29/116 +
+ + +
+ 100% + Branches + 4/4 +
+ + +
+ 33.33% + Functions + 3/9 +
+ + +
+ 25% + Lines + 29/116 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +1631x +1x +1x +1x +1x +1x +1x +1x +  +1x +2x +  +2x +2x +  +2x +2x +2x +2x +2x +2x +2x +2x +  +2x +1x +1x +  +2x +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import type { TerminalSchema } from '@tutorialkit/types';
+import { WebContainer, auth } from '@webcontainer/api';
+import { atom } from 'nanostores';
+import { tick } from '../utils/promises.js';
+import { isWebContainerSupported } from '../utils/support.js';
+import { clearTerminal, escapeCodes, type ITerminal } from '../utils/terminal.js';
+import { newJSHProcess } from '../webcontainer/shell.js';
+import { TerminalConfig, TerminalPanel } from '../webcontainer/terminal-config.js';
+ 
+export class TerminalStore {
+  terminalConfig = atom<TerminalConfig>(new TerminalConfig());
+ 
+  private _output: ITerminal | undefined = undefined;
+  private _webcontainerLoaded = false;
+ 
+  constructor(
+    private _webcontainer: Promise<WebContainer>,
+    private _useAuth: boolean,
+  ) {
+    this._webcontainer.then(() => {
+      this._webcontainerLoaded = true;
+    });
+  }
+ 
+  getOutputPanel(): ITerminal | undefined {
+    return this._output;
+  }
+ 
+  hasTerminalPanel() {
+    return this.terminalConfig.get().panels.length > 0;
+  }
+ 
+  setTerminalConfiguration(config?: TerminalSchema) {
+    const oldTerminalConfig = this.terminalConfig.get();
+    const newTerminalConfig = new TerminalConfig(config);
+ 
+    // iterate over the old terminal config and make a list of all terminal panels
+    const panelMap = new Map<string, TerminalPanel>(oldTerminalConfig.panels.map((panel) => [panel.id, panel]));
+ 
+    // iterate over the new terminal panels and try to re-use the old terminal with the new panel
+    for (const panel of newTerminalConfig.panels) {
+      const oldPanel = panelMap.get(panel.id);
+ 
+      panelMap.delete(panel.id);
+ 
+      if (oldPanel?.terminal) {
+        // if we found a previous panel with the same id, attach that terminal to the new panel
+        panel.attachTerminal(oldPanel.terminal);
+      }
+ 
+      if (panel.type === 'output') {
+        this._output = panel;
+      }
+ 
+      if (panel.type === 'terminal' && !oldPanel) {
+        // if the panel is a terminal panel, and this panel didn't exist before, spawn a new JSH process
+        this._bootWebContainer(panel)
+          .then(async (webcontainerInstance) => {
+            panel.attachProcess(await newJSHProcess(webcontainerInstance, panel, panel.processOptions));
+          })
+          .catch(() => {
+            // do nothing
+          });
+      }
+    }
+ 
+    // kill all old processes which we couldn't re-use
+    for (const panel of panelMap.values()) {
+      panel.process?.kill();
+    }
+ 
+    this.terminalConfig.set(newTerminalConfig);
+  }
+ 
+  /**
+   * Attaches the provided terminal with the panel matching the provided ID.
+   *
+   * @param id The ID of the panel to attach the terminal with.
+   * @param terminal The terminal to hook up to the JSH process.
+   */
+  async attachTerminal(id: string, terminal: ITerminal) {
+    const panel = this.terminalConfig.get().panels.find((panel) => panel.id === id);
+ 
+    if (!panel) {
+      // if we don't have a panel with the provided id, just exit
+      return;
+    }
+ 
+    panel.attachTerminal(terminal);
+  }
+ 
+  onTerminalResize(cols: number, rows: number) {
+    // iterate over all terminal panels and resize all processes
+    for (const panel of this.terminalConfig.get().panels) {
+      panel.process?.resize({ cols, rows });
+    }
+  }
+ 
+  private async _bootWebContainer(terminal: ITerminal) {
+    validateWebContainerSupported(terminal);
+ 
+    const isLoaded = this._webcontainerLoaded;
+ 
+    if (this._useAuth && !isLoaded) {
+      terminal.write('Waiting for authentication to complete...');
+ 
+      await auth.loggedIn();
+ 
+      clearTerminal(terminal);
+    }
+ 
+    if (!isLoaded) {
+      terminal.write('Booting WebContainer...');
+    }
+ 
+    try {
+      const webcontainerInstance = await this._webcontainer;
+ 
+      if (!isLoaded) {
+        clearTerminal(terminal);
+      }
+ 
+      return webcontainerInstance;
+    } catch (error) {
+      clearTerminal(terminal);
+ 
+      await tick();
+ 
+      terminal.write(
+        [
+          escapeCodes.red(`Looks like your browser's configuration is blocking WebContainers.`),
+          '',
+          `Let's troubleshoot this!`,
+          '',
+          'Read more at:',
+          'https://webcontainers.io/guides/browser-config',
+          '',
+        ].join('\n'),
+      );
+ 
+      throw error;
+    }
+  }
+}
+ 
+function validateWebContainerSupported(terminal: ITerminal) {
+  if (!isWebContainerSupported()) {
+    terminal.write(
+      [
+        escapeCodes.red('Incompatible Web Browser'),
+        '',
+        `WebContainers currently work in Chromium-based browsers, Firefox, and Safari 16.4. We're hoping to add support for more browsers as they implement the necessary Web Platform features.`,
+        '',
+        'Read more about browser support:',
+        'https://webcontainers.io/guides/browser-support',
+        '',
+      ].join('\n'),
+    );
+ 
+    throw new Error('Incompatible Web Browser');
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/runtime/coverage/src/tasks.ts.html b/packages/runtime/coverage/src/tasks.ts.html new file mode 100644 index 00000000..84667e90 --- /dev/null +++ b/packages/runtime/coverage/src/tasks.ts.html @@ -0,0 +1,262 @@ + + + + + + Code coverage report for src/tasks.ts + + + + + + + + + +
+
+

All files / src tasks.ts

+
+ +
+ 64% + Statements + 16/25 +
+ + +
+ 75% + Branches + 3/4 +
+ + +
+ 33.33% + Functions + 1/3 +
+ + +
+ 64% + Lines + 16/25 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +601x +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +5x +  +5x +5x +  +5x +  +5x +  +  +  +  +5x +5x +2x +3x +  +  +  +  +  +3x +5x +  +  +5x +5x + 
export const kTaskCancelled = Symbol('kTaskCancelled');
+ 
+export type TaskCancelled = typeof kTaskCancelled;
+ 
+export interface Task<T> {
+  promise: Promise<T>;
+  cancel(): void;
+}
+ 
+export class AbortError extends Error {}
+ 
+interface NewTaskOptions {
+  // if set to true then the promise resolves with the `kTaskCancelled` symbol
+  ignoreCancel?: boolean;
+ 
+  // an abort signal that this task will listen to and will abort if that signal trigger
+  signal?: AbortSignal;
+}
+ 
+/**
+ * A helper function to easily create "cancellable" promises where
+ * once a promise is cancelled it resolves to the "cancel" symbol.
+ *
+ * @param task - A function that return a promise.
+ * @returns The newly created task.
+ */
+export function newTask<T>(
+  task: (abortSignal: AbortSignal) => Promise<T>,
+  opts: { ignoreCancel: true; signal?: AbortSignal },
+): Task<T | TaskCancelled>;
+export function newTask<T>(task: (abortSignal: AbortSignal) => Promise<T>, opts?: { signal?: AbortSignal }): Task<T>;
+export function newTask<T>(task: (abortSignal: AbortSignal) => Promise<T>, opts: NewTaskOptions = {}): Task<unknown> {
+  const abortController = new AbortController();
+ 
+  const abortListener = () => abortController.abort(new AbortError());
+  const signal = opts.signal;
+ 
+  let runningTask = task(abortController.signal);
+ 
+  if (signal) {
+    runningTask = runningTask.finally(() => signal.removeEventListener('abort', abortListener));
+    signal.addEventListener('abort', abortListener, { once: true });
+  }
+ 
+  return {
+    promise: !opts.ignoreCancel
+      ? runningTask
+      : runningTask.catch((reason) => {
+          if (!(reason instanceof AbortError)) {
+            throw reason;
+          }
+ 
+          return kTaskCancelled;
+        }),
+    cancel() {
+      abortController.abort(new AbortError());
+    },
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/runtime/coverage/src/tutorial-runner.ts.html b/packages/runtime/coverage/src/tutorial-runner.ts.html new file mode 100644 index 00000000..1d68c03d --- /dev/null +++ b/packages/runtime/coverage/src/tutorial-runner.ts.html @@ -0,0 +1,1690 @@ + + + + + + Code coverage report for src/tutorial-runner.ts + + + + + + + + + +
+
+

All files / src tutorial-runner.ts

+
+ +
+ 47.4% + Statements + 146/308 +
+ + +
+ 36.36% + Branches + 12/33 +
+ + +
+ 52.17% + Functions + 12/23 +
+ + +
+ 47.4% + Lines + 146/308 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514 +515 +516 +517 +518 +519 +520 +521 +522 +523 +524 +525 +526 +527 +528 +529 +530 +531 +532 +533 +534 +535 +5361x +  +  +1x +1x +1x +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +2x +2x +2x +2x +2x +2x +2x +2x +  +  +2x +2x +  +2x +2x +2x +2x +2x +  +  +  +  +  +  +  +  +  +  +2x +1x +1x +  +  +1x +1x +1x +1x +1x +1x +  +2x +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +2x +  +2x +2x +2x +  +2x +2x +2x +  +2x +  +2x +  +2x +  +2x +  +2x +  +  +  +  +  +2x +2x +2x +  +2x +2x +  +2x +2x +2x +2x +  +2x +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +1x +1x +1x +1x +  +1x +  +  +  +1x +1x +  +  +  +  +  +1x +  +1x +  +  +  +1x +  +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +1x +1x +1x +  +1x +  +1x +  +1x +  +1x +1x +1x +1x +1x +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +1x +  +1x +  +1x +1x +  +1x +  +1x +1x +  +1x +  +  +1x +  +1x +1x +  +1x +  +  +  +  +  +  +  +  +1x +1x +1x +1x +  +  +1x +  +  +  +1x +  +1x +  +1x +1x +1x +  +  +  +  +1x +1x +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +1x +  +  +1x +  +2x +1x +  +1x +  +  +  +  +  +1x +1x +  +  +  +  +1x +1x +  +1x +  +1x +1x +  +2x +2x +2x +2x +2x +2x +  +2x +2x +2x +2x +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +2x +1x +1x +  +2x +1x +  +  +  +1x +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import type { CommandsSchema, Files } from '@tutorialkit/types';
+import type { WebContainer, WebContainerProcess } from '@webcontainer/api';
+import type { TerminalStore } from './store/terminal.js';
+import { newTask, type Task, type TaskCancelled } from './tasks.js';
+import { clearTerminal, escapeCodes, type ITerminal } from './utils/terminal.js';
+import { Command, Commands } from './webcontainer/command.js';
+import { StepsController } from './webcontainer/steps.js';
+import { diffFiles, toFileTree } from './webcontainer/utils/files.js';
+ 
+interface LoadFilesOptions {
+  /**
+   * The list of files to load.
+   */
+  files: Files | Promise<Files>;
+ 
+  /**
+   * The template to load.
+   */
+  template?: Files | Promise<Files>;
+ 
+  /**
+   * If true, all files will be removed (except for `node_modules`).
+   *
+   * @default false
+   */
+  removeAllFiles?: boolean;
+ 
+  /**
+   * Abort the previous load files operation.
+   *
+   * @default true
+   */
+  abortPreviousLoad?: boolean;
+ 
+  /**
+   * A signal to abort this operation.
+   */
+  signal?: AbortSignal;
+}
+ 
+interface RunCommandsOptions {
+  /**
+   * Abort the previous run commands operation.
+   *
+   * @default true
+   */
+  abortPreviousRun?: boolean;
+}
+ 
+/**
+ * The idea behind this class is that it manages the state of WebContainer and exposes
+ * an interface that makes sense to every component of TutorialKit.
+ *
+ * There should be only a single instance of this class.
+ */
+export class TutorialRunner {
+  private _currentLoadTask: Task<void | TaskCancelled> | undefined = undefined;
+  private _currentProcessTask: Task<void | TaskCancelled> | undefined = undefined;
+  private _currentCommandProcess: WebContainerProcess | undefined = undefined;
+  private _currentTemplate: Files | undefined = undefined;
+  private _currentFiles: Files | undefined = undefined;
+  private _currentRunCommands: Commands | undefined = undefined;
+  private _packageJsonDirty = false;
+  private _commandsChanged = false;
+ 
+  // this strongly assumes that there's a single package json which might not be true
+  private _packageJsonContent = '';
+  private _packageJsonPath = '';
+ 
+  constructor(
+    private _webcontainer: Promise<WebContainer>,
+    private _terminalStore: TerminalStore,
+    private _stepController: StepsController,
+  ) {}
+ 
+  /**
+   * Set the commands to run. This updates the reported `steps` if any have changed.
+   *
+   * This function is safe to call server side.
+   *
+   * To actually run them in WebContainer see `runCommands`.
+   *
+   * @param commands The commands schema.
+   */
+  setCommands(commands: CommandsSchema) {
+    const newCommands = new Commands(commands);
+    const anyChange = this._changeDetection(commands);
+ 
+    // if we already know that there's a change we can update the steps now
+    if (anyChange) {
+      this._stepController.setFromCommands([...newCommands]);
+      this._currentRunCommands = newCommands;
+      this._commandsChanged = true;
+    }
+  }
+ 
+  onTerminalResize(cols: number, rows: number) {
+    this._currentCommandProcess?.resize({ cols, rows });
+  }
+ 
+  /**
+   * Update the content of a single file in WebContainer.
+   *
+   * @param filePath path of the file
+   * @param content new content of the file
+   */
+  updateFile(filePath: string, content: string): void {
+    const previousLoadPromise = this._currentLoadTask?.promise;
+ 
+    this._currentLoadTask = newTask(
+      async (signal) => {
+        await previousLoadPromise;
+ 
+        const webcontainer = await this._webcontainer;
+ 
+        signal.throwIfAborted();
+ 
+        await webcontainer.fs.writeFile(filePath, content);
+ 
+        this._updateCurrentFiles({ [filePath]: content });
+      },
+      { ignoreCancel: true },
+    );
+  }
+ 
+  /**
+   * Update the provided files in WebContainer.
+   *
+   * @param files Files to update.
+   */
+  updateFiles(files: Files): void {
+    const previousLoadPromise = this._currentLoadTask?.promise;
+ 
+    this._currentLoadTask = newTask(
+      async (signal) => {
+        await previousLoadPromise;
+ 
+        const webcontainer = await this._webcontainer;
+ 
+        signal.throwIfAborted();
+ 
+        await webcontainer.mount(toFileTree(files));
+ 
+        this._updateCurrentFiles(files);
+      },
+      { ignoreCancel: true },
+    );
+  }
+ 
+  /**
+   * Load the provided files into WebContainer and remove any other files that had been loaded previously.
+   *
+   * This function always waits for any previous `prepareFiles` or `updateFile(s)` call to have completed
+   * before sending the next one.
+   *
+   * Previous load operations will be cancelled if `options.abortPreviousLoad` was set to true (which is the default).
+   *
+   * @see {LoadFilesOptions}
+   */
+  prepareFiles({ files, template, signal, abortPreviousLoad = true }: LoadFilesOptions): Promise<void | TaskCancelled> {
+    const previousLoadPromise = this._currentLoadTask?.promise;
+ 
+    if (abortPreviousLoad) {
+      this._currentLoadTask?.cancel();
+    }
+ 
+    this._currentLoadTask = newTask(
+      async (signal) => {
+        await previousLoadPromise;
+ 
+        const webcontainer = await this._webcontainer;
+ 
+        signal.throwIfAborted();
+ 
+        [template, files] = await Promise.all([template, files]);
+ 
+        signal.throwIfAborted();
+ 
+        if (this._currentFiles || this._currentTemplate) {
+          await updateFiles(
+            webcontainer,
+            { ...this._currentTemplate, ...this._currentFiles },
+            { ...template, ...files },
+          );
+        } else {
+          await webcontainer.mount(toFileTree({ ...template, ...files }));
+        }
+ 
+        this._currentTemplate = { ...template };
+        this._currentFiles = { ...files };
+ 
+        this._updateDirtyState({ ...template, ...files });
+      },
+      { ignoreCancel: true, signal },
+    );
+ 
+    return this._currentLoadTask.promise;
+  }
+ 
+  /**
+   * Runs the list of commands set with `setCommands`.
+   *
+   * This function always wait for any previous `runCommands` call to have completed before sending the next one.
+   * It will cancel the previous operation if `options.abortPreviousRun` was set to true.
+   *
+   * Commands are split into two:
+   *
+   *  - `prepareCommands`: For example commands like `npm install`, `mkdir -p src/foobar`, etc.
+   *  - `mainCommand`: Used to for example run a dev server or equivalent.
+   *
+   * @see {LoadFilesOptions}
+   */
+  runCommands({ abortPreviousRun = true }: RunCommandsOptions = {}): void {
+    const previousTask = this._currentProcessTask;
+    const loadPromise = this._currentLoadTask?.promise;
+    const newCommands = this._currentRunCommands;
+    const commandsChanged = this._commandsChanged;
+ 
+    if (!newCommands) {
+      throw new Error('setCommands should be called before runCommands');
+    }
+ 
+    this._currentProcessTask = newTask(
+      async (signal) => {
+        /**
+         * Make sure we wait for everything to be loaded on the fs before
+         * checking for changes. We do this because we want to know if the
+         * `package.json` changed.
+         */
+        await loadPromise;
+ 
+        if (signal.aborted && abortPreviousRun) {
+          previousTask?.cancel();
+        }
+ 
+        signal.throwIfAborted();
+ 
+        const anyChange = this._packageJsonDirty || commandsChanged;
+ 
+        if (!anyChange) {
+          /**
+           * If there are no changes and we have a previous task, then
+           * we must link this new task to that previous one, otherwise
+           * the link is broken and that task will never ends.
+           *
+           * We create that link here by awaiting it. Note that this `if`
+           * here should always evaluate to true.
+           */
+          if (previousTask) {
+            const abortListener = () => previousTask.cancel();
+            signal.addEventListener('abort', abortListener, { once: true });
+ 
+            return previousTask.promise;
+          }
+ 
+          return undefined;
+        }
+ 
+        // there were changes so we reset the "commands changed"
+        this._commandsChanged = false;
+ 
+        if (abortPreviousRun) {
+          previousTask?.cancel();
+        }
+ 
+        await previousTask?.promise;
+ 
+        const webcontainer = await this._webcontainer;
+ 
+        signal.throwIfAborted();
+ 
+        return this._runCommands(webcontainer, newCommands, signal);
+      },
+      { ignoreCancel: true },
+    );
+  }
+ 
+  /**
+   * Restart the last run commands that were submitted.
+   */
+  restartLastRunCommands() {
+    if (!this._currentRunCommands || !this._currentProcessTask) {
+      return;
+    }
+ 
+    const previousRunCommands = this._currentRunCommands;
+    const previousProcessPromise = this._currentProcessTask.promise;
+    const loadPromise = this._currentLoadTask?.promise;
+ 
+    this._currentProcessTask.cancel();
+ 
+    this._currentProcessTask = newTask(
+      async (signal) => {
+        await Promise.all([previousProcessPromise, loadPromise]);
+ 
+        const webcontainer = await this._webcontainer;
+ 
+        signal.throwIfAborted();
+ 
+        return this._runCommands(webcontainer, previousRunCommands, signal);
+      },
+      { ignoreCancel: true },
+    );
+  }
+ 
+  /**
+   * Get snapshot of runner's current files.
+   * Also prepares `package.json`'s `stackblitz.startCommand` with runner's commands.
+   *
+   * Note that file paths do not contain the leading `/`.
+   */
+  takeSnapshot() {
+    const files: Record<string, string> = {};
+ 
+    // first add template files
+    for (const [filePath, value] of Object.entries(this._currentTemplate || {})) {
+      if (typeof value === 'string') {
+        files[filePath.slice(1)] = value;
+      }
+    }
+ 
+    // next overwrite with files from editor
+    for (const [filePath, value] of Object.entries(this._currentFiles || {})) {
+      if (typeof value === 'string') {
+        files[filePath.slice(1)] = value;
+      }
+    }
+ 
+    if (this._packageJsonContent) {
+      let packageJson;
+ 
+      try {
+        packageJson = JSON.parse(this._packageJsonContent);
+      } catch {}
+ 
+      // add start commands when missing
+      if (packageJson && !packageJson.stackblitz?.startCommand) {
+        const mainCommand = this._currentRunCommands?.mainCommand?.shellCommand;
+        const prepareCommands = (this._currentRunCommands?.prepareCommands || []).map((c) => c.shellCommand);
+        const startCommand = [...prepareCommands, mainCommand].filter(Boolean).join(' && ');
+ 
+        files[this._packageJsonPath.slice(1)] = JSON.stringify(
+          { ...packageJson, stackblitz: { startCommand } },
+          null,
+          2,
+        );
+      }
+    }
+ 
+    return { files };
+  }
+ 
+  private async _runCommands(webcontainer: WebContainer, commands: Commands, signal: AbortSignal) {
+    const output = this._terminalStore.getOutputPanel();
+ 
+    clearTerminal(output);
+ 
+    const abortListener = () => this._currentCommandProcess?.kill();
+    signal.addEventListener('abort', abortListener, { once: true });
+ 
+    const hasMainCommand = !!commands.mainCommand;
+ 
+    try {
+      const commandList = [...commands];
+ 
+      this._stepController.setFromCommands(commandList);
+ 
+      // keep track of the current runnable command we are on
+      let runnableCommands = 0;
+ 
+      for (const [index, command] of commandList.entries()) {
+        const isMainCommand = index === commandList.length - 1 && !!commands.mainCommand;
+ 
+        if (!command.isRunnable()) {
+          this._stepController.updateStep(index, {
+            title: command.title,
+            status: 'skipped',
+          });
+ 
+          continue;
+        }
+ 
+        this._stepController.updateStep(index, {
+          title: command.title,
+          status: 'running',
+        });
+ 
+        // print newlines between commands to visually separate them from one another
+        if (runnableCommands > 0) {
+          output?.write('\n');
+        }
+ 
+        runnableCommands++;
+ 
+        this._currentCommandProcess = await this._newProcess(webcontainer, output, command.shellCommand);
+ 
+        try {
+          signal.throwIfAborted();
+        } catch (error) {
+          this._stepController.skipRemaining(index);
+          throw error;
+        }
+ 
+        if (isMainCommand) {
+          this._clearDirtyState();
+        }
+ 
+        const exitCode = await this._currentCommandProcess.exit;
+ 
+        if (exitCode !== 0) {
+          this._stepController.updateStep(index, {
+            title: command.title,
+            status: 'failed',
+          });
+ 
+          this._stepController.skipRemaining(index + 1);
+          break;
+        } else {
+          this._stepController.updateStep(index, {
+            title: command.title,
+            status: 'completed',
+          });
+        }
+ 
+        try {
+          signal.throwIfAborted();
+        } catch (error) {
+          this._stepController.skipRemaining(index + 1);
+          throw error;
+        }
+      }
+ 
+      if (!hasMainCommand) {
+        this._clearDirtyState();
+      }
+    } finally {
+      signal.removeEventListener('abort', abortListener);
+    }
+  }
+ 
+  private async _newProcess(webcontainer: WebContainer, output: ITerminal | undefined, shellCommand: string) {
+    const [command, ...args] = shellCommand.split(' ');
+ 
+    output?.write(`${escapeCodes.magenta('❯')} ${escapeCodes.green(command)} ${args.join(' ')}\n`);
+ 
+    /**
+     * We spawn the process and use a fallback for cols and rows in case the output is not connected to a visible
+     * terminal yet.
+     */
+    const process = await webcontainer.spawn(command, args, {
+      terminal: output
+        ? {
+            cols: output.cols ?? 80,
+            rows: output.rows ?? 15,
+          }
+        : undefined,
+    });
+ 
+    process.output.pipeTo(new WritableStream({ write: (data) => output?.write(data) }));
+ 
+    return process;
+  }
+ 
+  private _updateDirtyState(files: Files) {
+    for (const filePath in files) {
+      if (filePath.endsWith('/package.json') && files[filePath] != this._packageJsonContent) {
+        this._packageJsonContent = files[filePath] as string;
+        this._packageJsonPath = filePath;
+        this._packageJsonDirty = true;
+ 
+        return;
+      }
+    }
+  }
+ 
+  private _updateCurrentFiles(files: Files) {
+    // if the file was not tracked by the existing list of files, add it
+    if (this._currentFiles) {
+      for (const filePath in files) {
+        this._currentFiles[filePath] = files[filePath];
+      }
+    } else {
+      this._currentFiles = { ...files };
+    }
+ 
+    this._updateDirtyState(files);
+  }
+ 
+  private _clearDirtyState() {
+    this._packageJsonDirty = false;
+  }
+ 
+  private _changeDetection(newCommands: CommandsSchema) {
+    if (this._packageJsonDirty) {
+      return true;
+    }
+ 
+    if (!this._currentRunCommands) {
+      return true;
+    }
+ 
+    const prevCommandList = commandsToList(this._currentRunCommands);
+    const newCommandList = commandsToList(newCommands);
+ 
+    if (prevCommandList.length !== newCommandList.length) {
+      return true;
+    }
+ 
+    for (let i = 0; i < prevCommandList.length; ++i) {
+      if (!Command.equals(prevCommandList[i], newCommandList[i])) {
+        return true;
+      }
+    }
+ 
+    return false;
+  }
+}
+ 
+function commandsToList(commands: Commands | CommandsSchema) {
+  if (commands instanceof Commands) {
+    return [...commands].filter((command) => command.isRunnable());
+  }
+ 
+  return commandsToList(new Commands(commands));
+}
+ 
+async function updateFiles(webcontainer: WebContainer, previousFiles: Files, newFiles: Files) {
+  const { removed, addedOrModified } = diffFiles(previousFiles, newFiles);
+ 
+  for (const filePath of removed) {
+    await webcontainer.fs.rm(filePath, { force: true });
+  }
+ 
+  await webcontainer.mount(toFileTree(addedOrModified));
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/runtime/coverage/src/utils/index.html b/packages/runtime/coverage/src/utils/index.html new file mode 100644 index 00000000..a90c9586 --- /dev/null +++ b/packages/runtime/coverage/src/utils/index.html @@ -0,0 +1,146 @@ + + + + + + Code coverage report for src/utils + + + + + + + + + +
+
+

All files src/utils

+
+ +
+ 52.63% + Statements + 30/57 +
+ + +
+ 50% + Branches + 3/6 +
+ + +
+ 22.22% + Functions + 2/9 +
+ + +
+ 52.63% + Lines + 30/57 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
promises.ts +
+
66.66%16/2466.66%2/333.33%1/366.66%16/24
support.ts +
+
5%1/20100%0/00%0/15%1/20
terminal.ts +
+
100%13/1333.33%1/320%1/5100%13/13
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/runtime/coverage/src/utils/promises.ts.html b/packages/runtime/coverage/src/utils/promises.ts.html new file mode 100644 index 00000000..18ed79cf --- /dev/null +++ b/packages/runtime/coverage/src/utils/promises.ts.html @@ -0,0 +1,187 @@ + + + + + + Code coverage report for src/utils/promises.ts + + + + + + + + + +
+
+

All files / src/utils promises.ts

+
+ +
+ 66.66% + Statements + 16/24 +
+ + +
+ 66.66% + Branches + 2/3 +
+ + +
+ 33.33% + Functions + 1/3 +
+ + +
+ 66.66% + Lines + 16/24 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +351x +1x +  +  +  +1x +1x +  +1x +1x +1x +1x +  +1x +1x +1x +1x +1x +1x +  +1x +  +  +  +  +  +  +  +  +1x +  +  +  +  + 
export function withResolvers<T>(): PromiseWithResolvers<T> {
+  if (typeof Promise.withResolvers === 'function') {
+    return Promise.withResolvers();
+  }
+ 
+  let resolve!: (value: T | PromiseLike<T>) => void;
+  let reject!: (reason?: any) => void;
+ 
+  const promise = new Promise<T>((_resolve, _reject) => {
+    resolve = _resolve;
+    reject = _reject;
+  });
+ 
+  return {
+    resolve,
+    reject,
+    promise,
+  };
+}
+ 
+export function wait(ms: number): Promise<void> {
+  return new Promise((resolve) => setTimeout(resolve, ms));
+}
+ 
+/**
+ * Simulates a single tick of the event loop.
+ *
+ * @returns A promise that resolves after the tick.
+ */
+export function tick() {
+  return new Promise((resolve) => {
+    setTimeout(resolve);
+  });
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/runtime/coverage/src/utils/support.ts.html b/packages/runtime/coverage/src/utils/support.ts.html new file mode 100644 index 00000000..ea353a83 --- /dev/null +++ b/packages/runtime/coverage/src/utils/support.ts.html @@ -0,0 +1,163 @@ + + + + + + Code coverage report for src/utils/support.ts + + + + + + + + + +
+
+

All files / src/utils support.ts

+
+ +
+ 5% + Statements + 1/20 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 5% + Lines + 1/20 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +271x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
export function isWebContainerSupported() {
+  try {
+    const hasSharedArrayBuffer = 'SharedArrayBuffer' in globalThis;
+    const looksLikeChrome = navigator.userAgent.includes('Chrome');
+    const looksLikeFirefox = navigator.userAgent.includes('Firefox');
+    const looksLikeSafari = navigator.userAgent.includes('Safari');
+ 
+    if (hasSharedArrayBuffer && (looksLikeChrome || looksLikeFirefox)) {
+      return true;
+    }
+ 
+    if (hasSharedArrayBuffer && looksLikeSafari) {
+      // we only support Safari 16.4 and up so we check for the version here
+      const match = navigator.userAgent.match(/Version\/(\d+)\.(\d+) (?:Mobile\/.*?)?Safari/);
+      const majorVersion = match ? Number(match?.[1]) : 0;
+      const minorVersion = match ? Number(match?.[2]) : 0;
+ 
+      return majorVersion > 16 || (majorVersion === 16 && minorVersion >= 4);
+    }
+ 
+    // allow overriding the support check with localStorage.webcontainer_any_ua = 1
+    return Boolean(localStorage.getItem('webcontainer_any_ua'));
+  } catch {
+    return false;
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/runtime/coverage/src/utils/terminal.ts.html b/packages/runtime/coverage/src/utils/terminal.ts.html new file mode 100644 index 00000000..360df85d --- /dev/null +++ b/packages/runtime/coverage/src/utils/terminal.ts.html @@ -0,0 +1,157 @@ + + + + + + Code coverage report for src/utils/terminal.ts + + + + + + + + + +
+
+

All files / src/utils terminal.ts

+
+ +
+ 100% + Statements + 13/13 +
+ + +
+ 33.33% + Branches + 1/3 +
+ + +
+ 20% + Functions + 1/5 +
+ + +
+ 100% + Lines + 13/13 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25  +  +  +  +  +  +  +  +  +1x +  +1x +1x +1x +1x +1x +1x +1x +1x +  +1x +1x +1x +1x + 
export interface ITerminal {
+  readonly cols?: number;
+  readonly rows?: number;
+ 
+  reset: () => void;
+  write: (data: string) => void;
+  onData: (cb: (data: string) => void) => void;
+}
+ 
+const reset = '\x1b[0m';
+ 
+export const escapeCodes = {
+  reset,
+  clear: '\x1b[g',
+  red: (text: string) => `\x1b[1;31m${text}${reset}`,
+  gray: (text: string) => `\x1b[37m${text}${reset}`,
+  green: (text: string) => `\x1b[1;32m${text}${reset}`,
+  magenta: (text: string) => `\x1b[35m${text}${reset}`,
+};
+ 
+export function clearTerminal(terminal?: ITerminal) {
+  terminal?.reset();
+  terminal?.write(escapeCodes.clear);
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/runtime/coverage/src/webcontainer/command.ts.html b/packages/runtime/coverage/src/webcontainer/command.ts.html new file mode 100644 index 00000000..c7035004 --- /dev/null +++ b/packages/runtime/coverage/src/webcontainer/command.ts.html @@ -0,0 +1,337 @@ + + + + + + Code coverage report for src/webcontainer/command.ts + + + + + + + + + +
+
+

All files / src/webcontainer command.ts

+
+ +
+ 100% + Statements + 53/53 +
+ + +
+ 95.83% + Branches + 23/24 +
+ + +
+ 100% + Functions + 8/8 +
+ + +
+ 100% + Lines + 53/53 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85  +  +1x +  +  +  +  +5x +  +  +  +  +5x +  +5x +5x +5x +5x +  +5x +3x +  +3x +3x +2x +2x +  +3x +3x +3x +3x +3x +5x +  +1x +  +  +  +23x +  +  +  +  +23x +  +23x +23x +23x +23x +  +23x +3x +3x +  +23x +2x +2x +  +23x +23x +  +23x +17x +23x +2x +6x +4x +4x +  +23x +23x +  +23x +23x +17x +17x +  +16x +2x +2x +  +4x +23x +23x + 
import type { CommandSchema, CommandsSchema } from '@tutorialkit/types';
+ 
+export class Commands implements Iterable<Command> {
+  /**
+   * List of commands executed before the main command.
+   */
+ 
+  readonly prepareCommands?: Command[];
+ 
+  /**
+   * Main command to run. Typically a dev server, e.g. `npm run start`.
+   */
+  readonly mainCommand?: Command;
+ 
+  constructor({ prepareCommands, mainCommand }: CommandsSchema) {
+    this.prepareCommands = prepareCommands?.map((command) => new Command(command));
+    this.mainCommand = mainCommand ? new Command(mainCommand) : undefined;
+  }
+ 
+  [Symbol.iterator]() {
+    const _this = this;
+ 
+    return (function* () {
+      for (const command of _this.prepareCommands ?? []) {
+        yield command;
+      }
+ 
+      if (_this.mainCommand) {
+        yield _this.mainCommand;
+      }
+    })();
+  }
+}
+ 
+export class Command {
+  /**
+   * The underlying shell command.
+   */
+  readonly shellCommand: string;
+ 
+  /**
+   * Title describing what this command does, e.g., "Installing dependencies".
+   */
+  readonly title: string;
+ 
+  constructor(command: CommandSchema) {
+    this.shellCommand = Command.toShellCommand(command);
+    this.title = Command.toTitle(command);
+  }
+ 
+  isRunnable() {
+    return this.shellCommand !== '';
+  }
+ 
+  static equals(a: Command, b: Command) {
+    return a.shellCommand === b.shellCommand;
+  }
+ 
+  static toTitle(command: CommandSchema) {
+    let title = '';
+ 
+    if (typeof command === 'string') {
+      title = command;
+    } else if (Array.isArray(command)) {
+      title = command[1];
+    } else {
+      title = command.title;
+    }
+ 
+    return title;
+  }
+ 
+  static toShellCommand(command: CommandSchema) {
+    if (typeof command === 'string') {
+      return command;
+    }
+ 
+    if (Array.isArray(command)) {
+      return command[0];
+    }
+ 
+    return command.command;
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/runtime/coverage/src/webcontainer/index.html b/packages/runtime/coverage/src/webcontainer/index.html new file mode 100644 index 00000000..6617852f --- /dev/null +++ b/packages/runtime/coverage/src/webcontainer/index.html @@ -0,0 +1,206 @@ + + + + + + Code coverage report for src/webcontainer + + + + + + + + + +
+
+

All files src/webcontainer

+
+ +
+ 65.32% + Statements + 243/372 +
+ + +
+ 88.63% + Branches + 78/88 +
+ + +
+ 67.56% + Functions + 25/37 +
+ + +
+ 65.32% + Lines + 243/372 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
command.ts +
+
100%53/5395.83%23/24100%8/8100%53/53
index.ts +
+
0%0/10%0/10%0/10%0/1
on-demand-boot.ts +
+
0%0/310%0/10%0/10%0/31
preview-info.ts +
+
97.05%33/3485.71%12/14100%4/497.05%33/34
shell.ts +
+
4.34%2/46100%0/00%0/14.34%2/46
steps.ts +
+
83.33%30/3666.66%6/9100%4/483.33%30/36
terminal-config.ts +
+
73.09%125/17194.87%37/3950%9/1873.09%125/171
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/runtime/coverage/src/webcontainer/index.ts.html b/packages/runtime/coverage/src/webcontainer/index.ts.html new file mode 100644 index 00000000..2a6547bc --- /dev/null +++ b/packages/runtime/coverage/src/webcontainer/index.ts.html @@ -0,0 +1,97 @@ + + + + + + Code coverage report for src/webcontainer/index.ts + + + + + + + + + +
+
+

All files / src/webcontainer index.ts

+
+ +
+ 0% + Statements + 0/1 +
+ + +
+ 0% + Branches + 0/1 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 0% + Lines + 0/1 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5  +  +  +  + 
export { Command, Commands } from './command.js';
+export { safeBoot } from './on-demand-boot.js';
+export { PreviewInfo } from './preview-info.js';
+export { StepsController, type Step, type Steps } from './steps.js';
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/runtime/coverage/src/webcontainer/on-demand-boot.ts.html b/packages/runtime/coverage/src/webcontainer/on-demand-boot.ts.html new file mode 100644 index 00000000..6430a270 --- /dev/null +++ b/packages/runtime/coverage/src/webcontainer/on-demand-boot.ts.html @@ -0,0 +1,247 @@ + + + + + + Code coverage report for src/webcontainer/on-demand-boot.ts + + + + + + + + + +
+
+

All files / src/webcontainer on-demand-boot.ts

+
+ +
+ 0% + Statements + 0/31 +
+ + +
+ 0% + Branches + 0/1 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 0% + Lines + 0/31 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
/**
+ * Lightweight wrapper around WebContainer.boot
+ * to only boot if there's no risk on crashing the browser.
+ *
+ * This typicall might happen on iOS.
+ *
+ * When iOS is detected, a call to `unblock()` is required
+ * to move forward with the boot.
+ */
+import { WebContainer, type BootOptions } from '@webcontainer/api';
+import { atom, type ReadableAtom } from 'nanostores';
+import { withResolvers } from '../utils/promises.js';
+ 
+export type BootStatus = 'unknown' | 'blocked' | 'booting' | 'booted';
+ 
+const localBootStatus = atom<BootStatus>('unknown');
+const blockingStatus = withResolvers<void>();
+ 
+export const bootStatus: ReadableAtom<BootStatus> = localBootStatus;
+ 
+export async function safeBoot(options: BootOptions) {
+  if (localBootStatus.get() === 'unknown') {
+    localBootStatus.set(isRestricted() ? 'blocked' : 'booting');
+  }
+ 
+  if (localBootStatus.get() === 'blocked') {
+    await blockingStatus.promise;
+ 
+    localBootStatus.set('booting');
+  }
+ 
+  const webcontainer = await WebContainer.boot(options);
+ 
+  localBootStatus.set('booted');
+ 
+  return webcontainer;
+}
+ 
+export function unblockBoot() {
+  if (localBootStatus.get() !== 'blocked') {
+    return;
+  }
+ 
+  blockingStatus.resolve();
+}
+ 
+function isRestricted() {
+  const { userAgent, maxTouchPoints, platform } = navigator;
+ 
+  const iOS = /iPhone/.test(userAgent) || platform === 'iPhone';
+  const iPadOS = (platform === 'MacIntel' && maxTouchPoints > 1) || platform === 'iPad';
+ 
+  return iOS || iPadOS;
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/runtime/coverage/src/webcontainer/preview-info.ts.html b/packages/runtime/coverage/src/webcontainer/preview-info.ts.html new file mode 100644 index 00000000..28f12673 --- /dev/null +++ b/packages/runtime/coverage/src/webcontainer/preview-info.ts.html @@ -0,0 +1,208 @@ + + + + + + Code coverage report for src/webcontainer/preview-info.ts + + + + + + + + + +
+
+

All files / src/webcontainer preview-info.ts

+
+ +
+ 97.05% + Statements + 33/34 +
+ + +
+ 85.71% + Branches + 12/14 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 97.05% + Lines + 33/34 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42  +  +1x +19x +19x +19x +19x +19x +  +19x +1x +1x +1x +  +  +1x +  +19x +19x +9x +19x +4x +4x +4x +10x +4x +4x +4x +6x +2x +2x +2x +2x +  +19x +19x +  +19x +5x +5x +19x + 
import type { PreviewSchema } from '@tutorialkit/types';
+ 
+export class PreviewInfo {
+  port: number;
+  ready: boolean;
+  title?: string;
+  baseUrl?: string;
+  pathname?: string;
+ 
+  get url(): string | undefined {
+    if (this.baseUrl) {
+      return new URL(this.pathname ?? '/', this.baseUrl).toString();
+    }
+ 
+    return undefined;
+  }
+ 
+  constructor(preview: Exclude<PreviewSchema, boolean>[0], ready?: boolean) {
+    if (typeof preview === 'number') {
+      this.port = preview;
+    } else if (typeof preview === 'string') {
+      const [port, ...rest] = preview.split('/');
+      this.port = parseInt(port);
+      this.pathname = rest.join('/');
+    } else if (Array.isArray(preview)) {
+      this.port = preview[0];
+      this.title = preview[1];
+      this.pathname = preview[2];
+    } else {
+      this.port = preview.port;
+      this.title = preview.title;
+      this.pathname = preview.pathname;
+    }
+ 
+    this.ready = !!ready;
+  }
+ 
+  static equals(a: PreviewInfo, b: PreviewInfo) {
+    return a.port === b.port && a.pathname === b.pathname && a.title === b.title;
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/runtime/coverage/src/webcontainer/shell.ts.html b/packages/runtime/coverage/src/webcontainer/shell.ts.html new file mode 100644 index 00000000..467c47f6 --- /dev/null +++ b/packages/runtime/coverage/src/webcontainer/shell.ts.html @@ -0,0 +1,313 @@ + + + + + + Code coverage report for src/webcontainer/shell.ts + + + + + + + + + +
+
+

All files / src/webcontainer shell.ts

+
+ +
+ 4.34% + Statements + 2/46 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 0% + Functions + 0/1 +
+ + +
+ 4.34% + Lines + 2/46 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +771x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import type { WebContainer } from '@webcontainer/api';
+import { withResolvers } from '../utils/promises.js';
+import type { ITerminal } from '../utils/terminal.js';
+ 
+interface ProcessOptions {
+  /**
+   * Set to `true` if you want to allow redirecting output (e.g. `echo foo > bar`).
+   */
+  allowRedirects: boolean;
+ 
+  /**
+   * List of commands that are allowed by the JSH process.
+   */
+  allowCommands?: string[];
+}
+ 
+export async function newJSHProcess(
+  webcontainer: WebContainer,
+  terminal: ITerminal,
+  options: ProcessOptions | undefined,
+) {
+  const args: string[] = [];
+ 
+  if (!options?.allowRedirects) {
+    // if redirects are turned off, start JSH with `--no-redirects`
+    args.push('--no-redirects');
+  }
+ 
+  if (Array.isArray(options?.allowCommands)) {
+    // if only a subset of commands is allowed, pass it down to JSH
+    args.push('--allow-commands', options.allowCommands.join(','));
+  }
+ 
+  // we spawn a JSH process with a fallback cols and rows in case the process is not attached yet to a visible terminal
+  const process = await webcontainer.spawn('/bin/jsh', ['--osc', ...args], {
+    terminal: {
+      cols: terminal.cols ?? 80,
+      rows: terminal.rows ?? 15,
+    },
+  });
+ 
+  const input = process.input.getWriter();
+  const output = process.output;
+ 
+  const jshReady = withResolvers<void>();
+  let isInteractive = false;
+ 
+  output.pipeTo(
+    new WritableStream({
+      write(data) {
+        if (!isInteractive) {
+          const [, osc] = data.match(/\x1b\]654;([^\x07]+)\x07/) || [];
+ 
+          if (osc === 'interactive') {
+            // wait until we see the interactive OSC
+            isInteractive = true;
+ 
+            jshReady.resolve();
+          }
+        }
+ 
+        terminal.write(data);
+      },
+    }),
+  );
+ 
+  terminal.onData((data) => {
+    if (isInteractive) {
+      input.write(data);
+    }
+  });
+ 
+  await jshReady.promise;
+ 
+  return process;
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/runtime/coverage/src/webcontainer/steps.ts.html b/packages/runtime/coverage/src/webcontainer/steps.ts.html new file mode 100644 index 00000000..9ba799a0 --- /dev/null +++ b/packages/runtime/coverage/src/webcontainer/steps.ts.html @@ -0,0 +1,250 @@ + + + + + + Code coverage report for src/webcontainer/steps.ts + + + + + + + + + +
+
+

All files / src/webcontainer steps.ts

+
+ +
+ 83.33% + Statements + 30/36 +
+ + +
+ 66.66% + Branches + 6/9 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 83.33% + Lines + 30/36 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +561x +  +  +  +  +  +  +  +  +  +1x +  +  +  +5x +  +5x +5x +5x +5x +8x +8x +5x +5x +5x +  +  +5x +  +5x +2x +  +2x +  +  +  +2x +2x +  +5x +1x +  +1x +  +  +  +1x +1x +1x +2x +2x +1x +1x +1x +5x + 
import { atom } from 'nanostores';
+import type { Command } from './command.js';
+ 
+export type Steps = Step[];
+ 
+export interface Step {
+  title: string;
+  status: 'completed' | 'running' | 'failed' | 'skipped' | 'idle';
+}
+ 
+export class StepsController {
+  /**
+   * Steps that the runner is or will be executing.
+   */
+  steps = atom<Steps | undefined>(undefined);
+ 
+  setFromCommands(commands: Command[]) {
+    if (commands.length > 0) {
+      this.steps.set(
+        commands.map((command) => ({
+          title: command.title,
+          status: 'idle',
+        })),
+      );
+    } else {
+      this.steps.set(undefined);
+    }
+  }
+ 
+  updateStep(index: number, step: Step) {
+    const currentSteps = this.steps.value;
+ 
+    if (!currentSteps) {
+      return;
+    }
+ 
+    this.steps.set([...currentSteps.slice(0, index), step, ...currentSteps.slice(index + 1)]);
+  }
+ 
+  skipRemaining(index: number) {
+    const currentSteps = this.steps.value;
+ 
+    if (!currentSteps) {
+      return;
+    }
+ 
+    this.steps.set([
+      ...currentSteps.slice(0, index),
+      ...currentSteps.slice(index).map((step) => ({
+        ...step,
+        status: 'skipped' as const,
+      })),
+    ]);
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/runtime/coverage/src/webcontainer/terminal-config.ts.html b/packages/runtime/coverage/src/webcontainer/terminal-config.ts.html new file mode 100644 index 00000000..970fd03a --- /dev/null +++ b/packages/runtime/coverage/src/webcontainer/terminal-config.ts.html @@ -0,0 +1,859 @@ + + + + + + Code coverage report for src/webcontainer/terminal-config.ts + + + + + + + + + +
+
+

All files / src/webcontainer terminal-config.ts

+
+ +
+ 73.09% + Statements + 125/171 +
+ + +
+ 94.87% + Branches + 37/39 +
+ + +
+ 50% + Functions + 9/18 +
+ + +
+ 73.09% + Lines + 125/171 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +14x +  +14x +14x +  +14x +14x +  +14x +43x +43x +  +14x +1x +1x +14x +  +1x +1x +1x +1x +  +1x +  +  +  +  +  +1x +26x +26x +26x +26x +  +26x +13x +13x +13x +13x +13x +  +26x +26x +  +26x +26x +26x +26x +  +26x +26x +26x +26x +26x +  +  +26x +13x +  +  +13x +  +13x +2x +2x +  +13x +13x +  +26x +26x +26x +  +26x +  +  +  +26x +  +  +  +26x +15x +4x +4x +  +11x +15x +15x +15x +15x +  +  +26x +  +  +  +  +26x +  +  +  +26x +  +  +  +  +  +  +  +26x +  +  +  +  +  +  +  +26x +  +  +  +  +  +  +  +  +  +  +  +  +  +26x +  +  +  +  +  +  +  +  +  +  +  +  +26x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +26x +  +  +  +  +  +  +  +14x +14x +  +14x +  +1x +1x +1x +1x +1x +  +  +13x +  +  +14x +4x +4x +4x +4x +4x +  +9x +  +9x +9x +9x +9x +  +9x +9x +  +9x +1x +9x +8x +21x +  +21x +8x +21x +5x +5x +5x +5x +13x +8x +8x +8x +8x +8x +8x +8x +  +21x +21x +8x +9x +  +12x +1x +  +1x +  +  +1x +  +9x +9x +9x +9x +9x + 
import type { TerminalPanelType, TerminalSchema } from '@tutorialkit/types';
+import type { WebContainerProcess } from '@webcontainer/api';
+import type { ITerminal } from '../utils/terminal.js';
+ 
+interface NormalizedTerminalConfig {
+  panels: TerminalPanel[];
+  activePanel: number;
+}
+ 
+interface TerminalPanelOptions {
+  id?: string;
+  title?: string;
+  allowRedirects?: boolean;
+  allowCommands?: string[];
+}
+ 
+export class TerminalConfig {
+  private _config: NormalizedTerminalConfig;
+ 
+  constructor(config?: TerminalSchema) {
+    const normalized = normalizeTerminalConfig(config);
+ 
+    this._config = normalized;
+  }
+ 
+  get panels() {
+    return this._config.panels;
+  }
+ 
+  get activePanel() {
+    return this._config.activePanel;
+  }
+}
+ 
+const TERMINAL_PANEL_TITLES: Record<TerminalPanelType, string> = {
+  output: 'Output',
+  terminal: 'Terminal',
+};
+ 
+let globalId = 0;
+ 
+/**
+ * This class contains the state for a terminal panel. This is a panel which is attached to a process and renders
+ * the process output to a screen.
+ */
+export class TerminalPanel implements ITerminal {
+  static panelCount: Record<TerminalPanelType, number> = {
+    output: 0,
+    terminal: 0,
+  };
+ 
+  static resetCount() {
+    this.panelCount = {
+      output: 0,
+      terminal: 0,
+    };
+  }
+ 
+  readonly id: string;
+  readonly title: string;
+ 
+  private _terminal?: ITerminal;
+  private _process?: WebContainerProcess;
+  private _data: string[] = [];
+  private _onData?: (data: string) => void;
+ 
+  constructor(
+    readonly type: TerminalPanelType,
+    private readonly _options?: TerminalPanelOptions,
+  ) {
+    let title = _options?.title;
+ 
+    // automatically infer a title if no title is provided
+    if (!title) {
+      title = TERMINAL_PANEL_TITLES[type];
+ 
+      // we keep track of all untitled panel and add an index to the title
+      const count = TerminalPanel.panelCount[type];
+ 
+      if (count > 0) {
+        title += ` ${count}`;
+      }
+ 
+      TerminalPanel.panelCount[type]++;
+    }
+ 
+    this.title = title;
+    this.id = _options?.id ?? (type === 'output' ? 'output' : `${type}-${globalId++}`);
+  }
+ 
+  get terminal() {
+    return this._terminal;
+  }
+ 
+  get process() {
+    return this._process;
+  }
+ 
+  get processOptions() {
+    if (this.type === 'output') {
+      return undefined;
+    }
+ 
+    return {
+      allowRedirects: this._options?.allowRedirects ?? false,
+      allowCommands: this._options?.allowCommands,
+    };
+  }
+ 
+  // #region ITerminal methods
+  get cols() {
+    // we fallback to a default
+    return this._terminal?.cols;
+  }
+ 
+  get rows() {
+    return this._terminal?.rows;
+  }
+ 
+  reset() {
+    if (this._terminal) {
+      this._terminal.reset();
+    } else {
+      this._data = [];
+    }
+  }
+ 
+  write(data: string) {
+    if (this._terminal) {
+      this._terminal.write(data);
+    } else {
+      this._data.push(data);
+    }
+  }
+ 
+  onData(callback: (data: string) => void) {
+    if (this._terminal) {
+      this._terminal.onData(callback);
+    } else {
+      this._onData = callback;
+    }
+  }
+  // #endregion
+ 
+  /**
+   * Attach a WebContainer process to this panel.
+   *
+   * @param process The WebContainer process
+   */
+  attachProcess(process: WebContainerProcess) {
+    this._process = process;
+ 
+    if (this.cols != null && this.rows != null) {
+      this._process.resize({ cols: this.cols, rows: this.rows });
+    }
+  }
+ 
+  /**
+   * Attach a terminal to this panel.
+   *
+   * @param terminal The terminal.
+   */
+  attachTerminal(terminal: ITerminal) {
+    for (const data of this._data) {
+      terminal.write(data);
+    }
+ 
+    this._data = [];
+    this._terminal = terminal;
+ 
+    if (this._onData) {
+      terminal.onData(this._onData);
+    }
+ 
+    if (this.cols != null && this.rows != null) {
+      this._process?.resize({ cols: this.cols, rows: this.rows });
+    }
+  }
+}
+ 
+/**
+ * Normalize the provided configuration to a configuration which is easier to parse.
+ *
+ * @param config The terminal configuration.
+ * @returns A normalized terminal configuration.
+ */
+function normalizeTerminalConfig(config?: TerminalSchema): NormalizedTerminalConfig {
+  let activePanel = 0;
+ 
+  if (config === false) {
+    // if the value is `false`, we don't render anything
+    return {
+      panels: [],
+      activePanel,
+    };
+  }
+ 
+  // reset the count so that the auto-infered titles are indexed properly
+  TerminalPanel.resetCount();
+ 
+  // if no config is set, or the value is `true`, we just render the output panel
+  if (config === undefined || config === true) {
+    return {
+      panels: [new TerminalPanel('output')],
+      activePanel,
+    };
+  }
+ 
+  const panels: TerminalPanel[] = [];
+ 
+  const options = {
+    allowRedirects: config.allowRedirects,
+    allowCommands: config.allowCommands,
+  };
+ 
+  if (config.panels) {
+    if (config.panels === 'output') {
+      panels.push(new TerminalPanel('output'));
+    } else if (config.panels === 'terminal') {
+      panels.push(new TerminalPanel('terminal', options));
+    } else if (Array.isArray(config.panels)) {
+      for (const panel of config.panels) {
+        let terminalPanel: TerminalPanel;
+ 
+        if (typeof panel === 'string') {
+          terminalPanel = new TerminalPanel(panel, options);
+        } else if (Array.isArray(panel)) {
+          terminalPanel = new TerminalPanel(panel[0], {
+            title: panel[1],
+            ...options,
+          });
+        } else {
+          terminalPanel = new TerminalPanel(panel.type, {
+            id: panel.id,
+            title: panel.title,
+            allowRedirects: panel.allowRedirects ?? config.allowRedirects,
+            allowCommands: panel.allowCommands ?? config.allowCommands,
+          });
+        }
+ 
+        panels.push(terminalPanel);
+      }
+    }
+  }
+ 
+  if (typeof config.activePanel === 'number') {
+    activePanel = config.activePanel;
+ 
+    if (activePanel >= panels.length) {
+      activePanel = 0;
+    }
+  }
+ 
+  return {
+    activePanel,
+    panels,
+  };
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/runtime/coverage/src/webcontainer/utils/files.ts.html b/packages/runtime/coverage/src/webcontainer/utils/files.ts.html new file mode 100644 index 00000000..aafc17f7 --- /dev/null +++ b/packages/runtime/coverage/src/webcontainer/utils/files.ts.html @@ -0,0 +1,403 @@ + + + + + + Code coverage report for src/webcontainer/utils/files.ts + + + + + + + + + +
+
+

All files / src/webcontainer/utils files.ts

+
+ +
+ 97.29% + Statements + 72/74 +
+ + +
+ 95.83% + Branches + 23/24 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 97.29% + Lines + 72/74 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107  +  +  +  +  +1x +4x +4x +  +4x +1x +1x +  +3x +3x +  +3x +3x +  +3x +1x +1x +  +3x +1x +1x +3x +  +1x +1x +  +  +  +  +  +  +1x +4x +4x +  +4x +5x +5x +  +5x +2x +5x +2x +2x +5x +  +4x +5x +2x +2x +5x +  +4x +4x +4x +4x +4x +  +1x +3x +  +3x +9x +  +9x +  +9x +14x +  +14x +9x +9x +9x +9x +9x +14x +5x +  +5x +  +5x +3x +3x +3x +  +3x +3x +  +5x +5x +14x +9x +  +3x +3x +  +5x +5x +  +  +5x + 
import type { Files } from '@tutorialkit/types';
+import type { DirectoryNode, FileNode, FileSystemTree } from '@webcontainer/api';
+ 
+type FileSystemTreeNode = DirectoryNode | FileNode | undefined;
+ 
+export function areFilesEqual(a: Files, b: Files) {
+  const aFilePaths = Object.keys(a);
+  const bFilePaths = Object.keys(b);
+ 
+  if (aFilePaths.length !== bFilePaths.length) {
+    return false;
+  }
+ 
+  aFilePaths.sort();
+  bFilePaths.sort();
+ 
+  for (let i = 0; i < aFilePaths.length; ++i) {
+    const filePath = aFilePaths[i];
+ 
+    if (bFilePaths[i] !== filePath) {
+      return false;
+    }
+ 
+    if (a[filePath] !== b[filePath]) {
+      return false;
+    }
+  }
+ 
+  return true;
+}
+ 
+interface FilesDiff {
+  addedOrModified: Files;
+  removed: string[];
+}
+ 
+export function diffFiles(before: Files, after: Files): FilesDiff {
+  const addedOrModified: Files = {};
+  const removed: string[] = [];
+ 
+  for (const filePath in before) {
+    const beforeFile = before[filePath];
+    const afterFile = after[filePath];
+ 
+    if (typeof afterFile == 'undefined') {
+      removed.push(filePath);
+    } else if (beforeFile !== afterFile) {
+      addedOrModified[filePath] = afterFile;
+    }
+  }
+ 
+  for (const filePath in after) {
+    if (!(filePath in before)) {
+      addedOrModified[filePath] = after[filePath];
+    }
+  }
+ 
+  return {
+    addedOrModified,
+    removed,
+  };
+}
+ 
+export function toFileTree(files: Files): FileSystemTree {
+  const root: FileSystemTree = {};
+ 
+  for (const filePath in files) {
+    const segments = filePath.split('/').filter((segment) => segment);
+ 
+    let currentTree: FileSystemTree = root;
+ 
+    for (let i = 0; i < segments.length; ++i) {
+      const name = segments[i];
+ 
+      if (i === segments.length - 1) {
+        currentTree[name] = {
+          file: {
+            contents: files[filePath],
+          },
+        };
+      } else {
+        let folder = currentTree[name] as FileSystemTreeNode;
+ 
+        assertDirectoryNode(folder);
+ 
+        if (!folder) {
+          folder = {
+            directory: {},
+          };
+ 
+          currentTree[name] = folder;
+        }
+ 
+        currentTree = folder.directory;
+      }
+    }
+  }
+ 
+  return root;
+}
+ 
+function assertDirectoryNode(node: FileSystemTreeNode): asserts node is DirectoryNode | undefined {
+  if (node && !('directory' in node)) {
+    throw new Error('Expected directory node');
+  }
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/runtime/coverage/src/webcontainer/utils/index.html b/packages/runtime/coverage/src/webcontainer/utils/index.html new file mode 100644 index 00000000..bfccfdd9 --- /dev/null +++ b/packages/runtime/coverage/src/webcontainer/utils/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/webcontainer/utils + + + + + + + + + +
+
+

All files src/webcontainer/utils

+
+ +
+ 97.29% + Statements + 72/74 +
+ + +
+ 95.83% + Branches + 23/24 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 97.29% + Lines + 72/74 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
files.ts +
+
97.29%72/7495.83%23/24100%4/497.29%72/74
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/packages/runtime/src/store/previews.ts b/packages/runtime/src/store/previews.ts index acbf5b5c..bd7c791f 100644 --- a/packages/runtime/src/store/previews.ts +++ b/packages/runtime/src/store/previews.ts @@ -4,7 +4,7 @@ import { PreviewInfo } from '../webcontainer/preview-info.js'; import type { WebContainer } from '@webcontainer/api'; export class PreviewsStore { - private _availablePreviews = new Map(); + private _availablePreviews: PreviewInfo[] = []; private _previewsLayout: PreviewInfo[] = []; /** @@ -21,18 +21,21 @@ export class PreviewsStore { const webcontainer = await webcontainerPromise; webcontainer.on('port', (port, type, url) => { - let previewInfo = this._availablePreviews.get(port); + const previewInfos = this._availablePreviews.filter((preview) => preview.port === port); - if (!previewInfo) { - previewInfo = new PreviewInfo(port, type === 'open'); - this._availablePreviews.set(port, previewInfo); + if (previewInfos.length === 0) { + const info = new PreviewInfo(port, type === 'open'); + previewInfos.push(info); + this._availablePreviews.push(info); } - previewInfo.ready = type === 'open'; - previewInfo.baseUrl = url; + previewInfos.forEach((info) => { + info.ready = type === 'open'; + info.baseUrl = url; + }); if (this._previewsLayout.length === 0) { - this.previews.set([previewInfo]); + this.previews.set(previewInfos); } else { this._previewsLayout = [...this._previewsLayout]; this.previews.set(this._previewsLayout); @@ -58,14 +61,12 @@ export class PreviewsStore { const previewInfos = previews.map((preview) => { const info = new PreviewInfo(preview); - let previewInfo = this._availablePreviews.get(info.port); + let previewInfo = this._availablePreviews.find((availablePreview) => PreviewInfo.equals(info, availablePreview)); if (!previewInfo) { previewInfo = info; - this._availablePreviews.set(previewInfo.port, previewInfo); - } else { - previewInfo.title = info.title; + this._availablePreviews.push(previewInfo); } return previewInfo; diff --git a/packages/runtime/src/webcontainer/preview-info.spec.ts b/packages/runtime/src/webcontainer/preview-info.spec.ts index 6dfe3e4b..3096a928 100644 --- a/packages/runtime/src/webcontainer/preview-info.spec.ts +++ b/packages/runtime/src/webcontainer/preview-info.spec.ts @@ -2,10 +2,20 @@ import { describe, it, expect } from 'vitest'; import { PreviewInfo } from './preview-info.js'; describe('PreviewInfo', () => { - it('should accept a port', () => { + it('should accept a number for port', () => { const previewInfo = new PreviewInfo(3000); expect(previewInfo.port).toBe(3000); + expect(previewInfo.title).toBe(undefined); + expect(previewInfo.pathname).toBe(undefined); + }); + + it('should accept a string for port and pathname', () => { + const previewInfo = new PreviewInfo('3000/some/nested/path'); + + expect(previewInfo.port).toBe(3000); + expect(previewInfo.pathname).toBe('some/nested/path'); + expect(previewInfo.title).toBe(undefined); }); it('should accept a tuple of [port, title]', () => { @@ -13,6 +23,15 @@ describe('PreviewInfo', () => { expect(previewInfo.port).toBe(3000); expect(previewInfo.title).toBe('Local server'); + expect(previewInfo.pathname).toBe(undefined); + }); + + it('should accept a tuple of [port, title, pathname]', () => { + const previewInfo = new PreviewInfo([3000, 'Local server', '/docs']); + + expect(previewInfo.port).toBe(3000); + expect(previewInfo.title).toBe('Local server'); + expect(previewInfo.pathname).toBe('/docs'); }); it('should accept an object with { port, title }', () => { @@ -20,6 +39,15 @@ describe('PreviewInfo', () => { expect(previewInfo.port).toBe(3000); expect(previewInfo.title).toBe('Local server'); + expect(previewInfo.pathname).toBe(undefined); + }); + + it('should accept an object with { port, title, pathname }', () => { + const previewInfo = new PreviewInfo({ port: 3000, title: 'Local server', pathname: '/docs' }); + + expect(previewInfo.port).toBe(3000); + expect(previewInfo.title).toBe('Local server'); + expect(previewInfo.pathname).toBe('/docs'); }); it('should not be ready by default', () => { @@ -41,9 +69,8 @@ describe('PreviewInfo', () => { }); it('should have a url with a custom pathname and baseUrl', () => { - const previewInfo = new PreviewInfo(3000); + const previewInfo = new PreviewInfo('3000/foo'); previewInfo.baseUrl = 'https://example.com'; - previewInfo.pathname = '/foo'; expect(previewInfo.url).toBe('https://example.com/foo'); }); @@ -71,10 +98,10 @@ describe('PreviewInfo', () => { it('should not be equal to another preview info with a different pathname', () => { const a = new PreviewInfo(3000); - const b = new PreviewInfo(3000); - - a.pathname = '/foo'; + const b = new PreviewInfo('3000/b'); + const c = new PreviewInfo('3000/c'); expect(PreviewInfo.equals(a, b)).toBe(false); + expect(PreviewInfo.equals(b, c)).toBe(false); }); }); diff --git a/packages/runtime/src/webcontainer/preview-info.ts b/packages/runtime/src/webcontainer/preview-info.ts index 55c781e7..050cc326 100644 --- a/packages/runtime/src/webcontainer/preview-info.ts +++ b/packages/runtime/src/webcontainer/preview-info.ts @@ -18,12 +18,18 @@ export class PreviewInfo { constructor(preview: Exclude[0], ready?: boolean) { if (typeof preview === 'number') { this.port = preview; + } else if (typeof preview === 'string') { + const [port, ...rest] = preview.split('/'); + this.port = parseInt(port); + this.pathname = rest.join('/'); } else if (Array.isArray(preview)) { this.port = preview[0]; this.title = preview[1]; + this.pathname = preview[2]; } else { this.port = preview.port; this.title = preview.title; + this.pathname = preview.pathname; } this.ready = !!ready; diff --git a/packages/template/src/content/tutorial/1-basics/1-introduction/2-foo/content.mdx b/packages/template/src/content/tutorial/1-basics/1-introduction/2-foo/content.mdx index b60458a2..614725e1 100644 --- a/packages/template/src/content/tutorial/1-basics/1-introduction/2-foo/content.mdx +++ b/packages/template/src/content/tutorial/1-basics/1-introduction/2-foo/content.mdx @@ -4,9 +4,10 @@ title: Foo from part 1 slug: foo focus: /src/index.html previews: - - [8080, 'Main Page'] + - { title: 'Main Page', port: 8080, pathname: '/src'} - [1, 'Test Runner'] - - [2, 'Bar'] + - '2/some/custom/pathname' + - '2/another/pathname' terminal: panels: 'terminal' editPageLink: 'https://tutorialkit.dev' diff --git a/packages/template/src/templates/default/src/index.js b/packages/template/src/templates/default/src/index.js index b942c5c9..1c72cdef 100644 --- a/packages/template/src/templates/default/src/index.js +++ b/packages/template/src/templates/default/src/index.js @@ -15,7 +15,7 @@ createServer((_req, res) => { `); }).listen(1); -createServer((_req, res) => res.end('Server 2')).listen(2); +createServer((req, res) => res.end(`Server 2\n${req.method} ${req.url}`)).listen(2); servor({ root: 'src/', diff --git a/packages/types/src/schemas/common.ts b/packages/types/src/schemas/common.ts index 06d36ec5..56c56c2c 100644 --- a/packages/types/src/schemas/common.ts +++ b/packages/types/src/schemas/common.ts @@ -37,12 +37,17 @@ export const previewSchema = z.union([ // a single number, the port for the preview z.number(), - // a tuple, the port followed by a title + // a string, the port and pathname + z.string(), + + // a tuple, the port followed by a title and optional pathname z.tuple([z.number(), z.string()]), + z.tuple([z.number(), z.string(), z.string()]), z.strictObject({ port: z.number().describe('Port number of the preview.'), title: z.string().describe('Title of the preview.'), + pathname: z.string().optional().describe('Pathname of the preview URL.'), }), ]) .array(),