├── .github └── workflows │ ├── build-docs.yml │ └── npm-publish.yml ├── .gitignore ├── LICENSE ├── README.md ├── docs_src ├── .gitignore ├── README.md ├── fix.js ├── package-lock.json ├── package.json ├── rollup.config.js ├── src │ ├── client.js │ ├── components │ │ ├── Docs.svelte │ │ ├── Example.svelte │ │ └── Repl │ │ │ ├── Bundler.js │ │ │ ├── CodeMirror.svelte │ │ │ ├── Input │ │ │ ├── ComponentSelector.svelte │ │ │ └── ModuleEditor.svelte │ │ │ ├── Message.svelte │ │ │ ├── Output │ │ │ ├── Compiler.js │ │ │ ├── CompilerOptions.svelte │ │ │ ├── ReplProxy.js │ │ │ ├── Viewer.svelte │ │ │ ├── getLocationFromStack.js │ │ │ ├── index.svelte │ │ │ └── srcdoc │ │ │ │ ├── index.html │ │ │ │ ├── index.js │ │ │ │ └── styles.css │ │ │ ├── Repl.svelte │ │ │ ├── SplitPane.svelte │ │ │ ├── codemirror.css │ │ │ ├── codemirror.js │ │ │ ├── env.js │ │ │ └── utils.js │ ├── pages │ │ ├── examples.js │ │ ├── install.md │ │ ├── intro.md │ │ ├── list.js │ │ ├── styling.md │ │ └── usage.md │ ├── routes │ │ ├── _error.svelte │ │ ├── _layout.svelte │ │ ├── index.svelte │ │ └── playground │ │ │ └── index.svelte │ ├── server.js │ ├── service-worker.js │ └── template.html ├── static │ ├── fonts │ │ ├── fira-mono-400.woff2 │ │ ├── overpass-300.woff2 │ │ ├── overpass-400.woff2 │ │ └── overpass-600.woff2 │ ├── global.css │ ├── manifest.json │ └── solarized-light.css └── utils.js ├── package-lock.json ├── package.json ├── rollup.config.js ├── src ├── handlers │ ├── code.js │ ├── interpolation.js │ ├── logic.js │ ├── meta.js │ ├── systemTags.js │ └── tags.js ├── index.js ├── store.js └── utils.js └── tests ├── 1-simple-component.md ├── 10-checkbox.md ├── 11-renderer.js ├── 11-renderer.md ├── 2-setting-options.js ├── 2-setting-options.md ├── 3-markdown-testing.md ├── 4-logic-blocks.md ├── 5-mdsv-parsing.md ├── 6-codeblocks.md ├── 7-highlight.js ├── 7-highlight.md ├── 8-each-blocks.md ├── 9-table-in-each.md ├── helpers ├── new.js ├── snapshots.js ├── testing.js └── visual.js ├── snapshots ├── 1-simple-component.svelte ├── 10-checkbox.svelte ├── 11-renderer.svelte ├── 2-setting-options.svelte ├── 3-markdown-testing.svelte ├── 4-logic-blocks.svelte ├── 5-mdsv-parsing.svelte ├── 6-codeblocks.svelte ├── 7-highlight.svelte ├── 8-each-blocks.svelte └── 9-table-in-each.svelte └── test.js /.github/workflows/build-docs.yml: -------------------------------------------------------------------------------- 1 | name: Build Documentation 2 | 3 | on: 4 | push: 5 | paths: 6 | - '.github/workflows/build-docs.yml' 7 | - 'docs_src/*' 8 | - 'docs_src/*/*' 9 | - 'docs_src/*/*/*' 10 | - 'docs_src/*/*/*/*' 11 | - 'src/*' 12 | - 'src/*/*' 13 | 14 | jobs: 15 | docs-build-deploy: 16 | runs-on: ubuntu-18.04 17 | steps: 18 | - uses: actions/checkout@master 19 | 20 | - name: Setup Node 21 | uses: actions/setup-node@v1 22 | with: 23 | node-version: 12.x 24 | 25 | - name: Build 26 | run: npm i && npm run build && cd docs_src && npm i && npm run export 27 | 28 | - name: Deploy 29 | uses: peaceiris/actions-gh-pages@v2.4.0 30 | env: 31 | ACTIONS_DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }} 32 | PUBLISH_BRANCH: gh-pages 33 | PUBLISH_DIR: ./docs_src/__sapper__/export/svelte-preprocess-markdown -------------------------------------------------------------------------------- /.github/workflows/npm-publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish on NPM 2 | 3 | on: 4 | push: 5 | paths: 6 | - '.github/workflows/npm-publish.yml' 7 | - 'package.json' 8 | 9 | jobs: 10 | test: 11 | runs-on: ubuntu-18.04 12 | steps: 13 | - uses: actions/checkout@v1 14 | - name: Setup Node 15 | uses: actions/setup-node@v1 16 | with: 17 | node-version: 12 18 | - name: Installing NPM deps 19 | run: npm install 20 | - name: Testing 21 | run: npm run test 22 | 23 | publish-npm: 24 | needs: test 25 | runs-on: ubuntu-18.04 26 | steps: 27 | - uses: actions/checkout@v1 28 | - name: Setup Node 29 | uses: actions/setup-node@v1 30 | with: 31 | node-version: 12 32 | registry-url: https://registry.npmjs.org/ 33 | - name: Installing NPM deps 34 | run: npm install 35 | - name: Building & publishing on NPM 36 | run: npm publish 37 | env: 38 | NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | bundle* 4 | tests/visual -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Alexey Schebelev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # svelte-preprocess-markdown 2 | Allows to import `*.md` files as Svelte component. Very useful when your components have a lot of formatted texts and you doesn't want to write it in HTML. It is based on superfast [Marked](https://www.npmjs.com/package/marked) markdown parser. 3 | 4 | [![npm](https://img.shields.io/npm/v/svelte-preprocess-markdown)](https://www.npmjs.com/package/svelte-preprocess-markdown) [![npm](https://img.shields.io/npm/dt/svelte-preprocess-markdown)](https://www.npmjs.com/package/svelte-preprocess-markdown) [![](https://github.com/AlexxNB/svelte-preprocess-markdown/workflows/Publish%20on%20NPM/badge.svg)](https://github.com/AlexxNB/svelte-preprocess-markdown/actions?workflow=Publish+on+NPM) 5 | 6 | # Documentaton 7 | 8 | * Please, see the [Docs](https://alexxnb.github.io/svelte-preprocess-markdown) for more info 9 | * Or try yourself in the our [Playground](https://alexxnb.github.io/svelte-preprocess-markdown/playground) 10 | 11 | # Installation 12 | 13 | Install package: 14 | 15 | ```bash 16 | npm i -D svelte-preprocess-markdown 17 | ``` 18 | 19 | Then, edit `rollup.config.js` file: 20 | 21 | ```js 22 | 23 | // 1. import package 24 | const {markdown} = require('svelte-preprocess-markdown'); 25 | 26 | export default { 27 | // ... 28 | plugins: [ 29 | svelte({ 30 | // 2. add '.md', to the extensions 31 | extensions: ['.svelte','.md'], 32 | // 3. add markdown preprocessor 33 | preprocess: markdown() 34 | }) 35 | ] 36 | } 37 | ``` 38 | 39 | # Usage 40 | 41 | ## Common usage 42 | 43 | ```markdown 44 | 48 | 49 | # Hello {name}! 50 | 51 | This is text in `markdown` **notation** 52 | 53 | 54 | 55 | 60 | ``` 61 | ## MDSv usage 62 | 63 | The `MDSv` format is [MDX](https://mdxjs.com/)-like way to write documents using imported Svelte-components. 64 | 65 | ```markdown 66 | import Block from './Block.svelte'; 67 | import { data } from './my_data.js'; 68 | 69 | # The MDSv example 70 | 71 | You can use *components* and a *logic* inside doc: 72 | 73 | 74 | My `data` list: 75 | {#each data as item} 76 | {item} 77 | {/each} 78 | 79 | ``` 80 | 81 | 82 | # Options 83 | 84 | You can pass any [options](https://marked.js.org/#/USING_ADVANCED.md#options) that are accepted by [Marked](https://www.npmjs.com/package/marked). 85 | 86 | ```js 87 | ... 88 | plugins: [ 89 | svelte({ 90 | ... 91 | preprocess: markdown({ 92 | headerIds: false 93 | }) 94 | ... 95 | }) 96 | ] 97 | ... 98 | ``` 99 | 100 | ## Renderer 101 | If you need `renderer` object for options, you can get it from the package: 102 | 103 | ```js 104 | const {Renderer} = require('svelte-preprocess-markdown'); 105 | 106 | const renderer = Renderer(); 107 | 108 | renderer.heading = function (text, level) { 109 | ... 110 | }; 111 | 112 | const options = {renderer}; 113 | ``` 114 | -------------------------------------------------------------------------------- /docs_src/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | yarn-error.log 4 | /cypress/screenshots/ 5 | /__sapper__/ 6 | -------------------------------------------------------------------------------- /docs_src/README.md: -------------------------------------------------------------------------------- 1 | # sapper-template 2 | 3 | The default [Sapper](https://github.com/sveltejs/sapper) template, with branches for Rollup and webpack. To clone it and get started: 4 | 5 | ```bash 6 | # for Rollup 7 | npx degit sveltejs/sapper-template#rollup my-app 8 | # for webpack 9 | npx degit sveltejs/sapper-template#webpack my-app 10 | cd my-app 11 | npm install # or yarn! 12 | npm run dev 13 | ``` 14 | 15 | Open up [localhost:3000](http://localhost:3000) and start clicking around. 16 | 17 | Consult [sapper.svelte.dev](https://sapper.svelte.dev) for help getting started. 18 | 19 | 20 | ## Structure 21 | 22 | Sapper expects to find two directories in the root of your project — `src` and `static`. 23 | 24 | 25 | ### src 26 | 27 | The [src](src) directory contains the entry points for your app — `client.js`, `server.js` and (optionally) a `service-worker.js` — along with a `template.html` file and a `routes` directory. 28 | 29 | 30 | #### src/routes 31 | 32 | This is the heart of your Sapper app. There are two kinds of routes — *pages*, and *server routes*. 33 | 34 | **Pages** are Svelte components written in `.html` files. When a user first visits the application, they will be served a server-rendered version of the route in question, plus some JavaScript that 'hydrates' the page and initialises a client-side router. From that point forward, navigating to other pages is handled entirely on the client for a fast, app-like feel. (Sapper will preload and cache the code for these subsequent pages, so that navigation is instantaneous.) 35 | 36 | **Server routes** are modules written in `.js` files, that export functions corresponding to HTTP methods. Each function receives Express `request` and `response` objects as arguments, plus a `next` function. This is useful for creating a JSON API, for example. 37 | 38 | There are three simple rules for naming the files that define your routes: 39 | 40 | * A file called `src/routes/about.html` corresponds to the `/about` route. A file called `src/routes/blog/[slug].html` corresponds to the `/blog/:slug` route, in which case `params.slug` is available to the route 41 | * The file `src/routes/index.html` (or `src/routes/index.js`) corresponds to the root of your app. `src/routes/about/index.html` is treated the same as `src/routes/about.html`. 42 | * Files and directories with a leading underscore do *not* create routes. This allows you to colocate helper modules and components with the routes that depend on them — for example you could have a file called `src/routes/_helpers/datetime.js` and it would *not* create a `/_helpers/datetime` route 43 | 44 | 45 | ### static 46 | 47 | The [static](static) directory contains any static assets that should be available. These are served using [sirv](https://github.com/lukeed/sirv). 48 | 49 | In your [service-worker.js](app/service-worker.js) file, you can import these as `files` from the generated manifest... 50 | 51 | ```js 52 | import { files } from '../__sapper__/service-worker.js'; 53 | ``` 54 | 55 | ...so that you can cache them (though you can choose not to, for example if you don't want to cache very large files). 56 | 57 | 58 | ## Bundler config 59 | 60 | Sapper uses Rollup or webpack to provide code-splitting and dynamic imports, as well as compiling your Svelte components. With webpack, it also provides hot module reloading. As long as you don't do anything daft, you can edit the configuration files to add whatever plugins you'd like. 61 | 62 | 63 | ## Production mode and deployment 64 | 65 | To start a production version of your app, run `npm run build && npm start`. This will disable live reloading, and activate the appropriate bundler plugins. 66 | 67 | You can deploy your application to any environment that supports Node 8 or above. As an example, to deploy to [Now](https://zeit.co/now), run these commands: 68 | 69 | ```bash 70 | npm install -g now 71 | now 72 | ``` 73 | 74 | 75 | ## Using external components with webpack 76 | 77 | When using Svelte components installed from npm, such as [@sveltejs/svelte-virtual-list](https://github.com/sveltejs/svelte-virtual-list), Svelte needs the original component source (rather than any precompiled JavaScript that ships with the component). This allows the component to be rendered server-side, and also keeps your client-side app smaller. 78 | 79 | Because of that, it's essential that webpack doesn't treat the package as an *external dependency*. You can either modify the `externals` option in [webpack/server.config.js](webpack/server.config.js), or simply install the package to `devDependencies` rather than `dependencies`, which will cause it to get bundled (and therefore compiled) with your app: 80 | 81 | ```bash 82 | yarn add -D @sveltejs/svelte-virtual-list 83 | ``` 84 | 85 | 86 | ## Bugs and feedback 87 | 88 | Sapper is in early development, and may have the odd rough edge here and there. Please be vocal over on the [Sapper issue tracker](https://github.com/sveltejs/sapper/issues). 89 | -------------------------------------------------------------------------------- /docs_src/fix.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | const dir = path.resolve('./__sapper__/export/svelte-preprocess-markdown'); 5 | 6 | 7 | console.log('Renaming all dashed files'); 8 | 9 | 10 | function rename_files(dir) { 11 | 12 | let renamed = []; 13 | 14 | fs.readdirSync(path.join(dir,'client')).forEach(filename => { 15 | if(filename.startsWith('_')){ 16 | let file = { 17 | from: filename, 18 | to: filename.replace(/^_/,'') 19 | } 20 | 21 | renamed.push(file); 22 | 23 | console.log(file.from+' -> '+file.to); 24 | fs.renameSync( path.join(dir,'client',file.from), path.join(dir,'client',file.to) ); 25 | } 26 | }); 27 | 28 | return renamed; 29 | } 30 | 31 | function replace_filename(dir,renames) { 32 | fs.readdirSync(path.join(dir)).forEach(file => { 33 | const filepath = path.join(dir,file); 34 | const stat = fs.lstatSync(filepath); 35 | if(stat.isDirectory()) { 36 | replace_filename(filepath,renames); 37 | }else{ 38 | let source = fs.readFileSync(filepath,{encoding:'utf-8'}); 39 | let changed = false; 40 | renames.forEach(rpl => { 41 | if(source.includes(rpl.from)){ 42 | changed = true; 43 | console.log(filepath); 44 | source = source.replace(new RegExp(rpl.from, 'g'),rpl.to); 45 | } 46 | }); 47 | if(changed) fs.writeFileSync(filepath,source); 48 | 49 | } 50 | 51 | }) 52 | } 53 | 54 | replace_filename(dir,rename_files(dir)); 55 | -------------------------------------------------------------------------------- /docs_src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte-preprocess-markdown-docs", 3 | "description": "svelte-preprocess-markdown documentation", 4 | "version": "0.0.1", 5 | "scripts": { 6 | "dev": "sapper dev", 7 | "build": "sapper build --legacy", 8 | "export": "sapper export --basepath /svelte-preprocess-markdown && node fix", 9 | "start": "npx serve __sapper__/export", 10 | "cy:run": "cypress run", 11 | "cy:open": "cypress open", 12 | "test": "run-p --race dev cy:run" 13 | }, 14 | "dependencies": { 15 | "codemirror": "^5.53.2", 16 | "compression": "^1.7.4", 17 | "highlight.js": "^10.0.3", 18 | "path-browserify": "^1.0.1", 19 | "polka": "^0.5.2", 20 | "punycode": "^2.1.1", 21 | "sirv": "^0.4.2", 22 | "sourcemap-codec": "^1.4.8", 23 | "yootils": "0.0.16" 24 | }, 25 | "devDependencies": { 26 | "@babel/core": "^7.9.6", 27 | "@babel/plugin-syntax-dynamic-import": "^7.8.3", 28 | "@babel/plugin-transform-runtime": "^7.9.6", 29 | "@babel/preset-env": "^7.9.6", 30 | "@babel/runtime": "^7.9.6", 31 | "@rollup/plugin-node-resolve": "^7.1.3", 32 | "npm-run-all": "^4.1.5", 33 | "rollup": "^1.27.11", 34 | "rollup-plugin-babel": "^4.4.0", 35 | "rollup-plugin-commonjs": "^10.1.0", 36 | "rollup-plugin-node-resolve": "^5.2.0", 37 | "rollup-plugin-replace": "^2.2.0", 38 | "rollup-plugin-svelte": "^5.2.1", 39 | "rollup-plugin-terser": "^7.0.0", 40 | "sapper": "^0.27.13", 41 | "svelte": "^3.22.2" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /docs_src/rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from 'rollup-plugin-node-resolve'; 2 | import replace from 'rollup-plugin-replace'; 3 | import commonjs from 'rollup-plugin-commonjs'; 4 | import svelte from 'rollup-plugin-svelte'; 5 | import babel from 'rollup-plugin-babel'; 6 | import config from 'sapper/config/rollup.js'; 7 | import pkg from './package.json'; 8 | import {markdown} from './../dist/index.mjs'; 9 | import {renderer,highlight,bugremover} from './utils' 10 | 11 | const mode = process.env.NODE_ENV; 12 | const dev = mode === 'development'; 13 | const legacy = !!process.env.SAPPER_LEGACY_BUILD; 14 | 15 | export default { 16 | client: { 17 | input: config.client.input(), 18 | output: config.client.output(), 19 | plugins: [ 20 | replace({ 21 | 'process.browser': true, 22 | 'process.env.NODE_ENV': JSON.stringify(mode) 23 | }), 24 | svelte({ 25 | dev, 26 | hydratable: true, 27 | emitCss: true, 28 | extensions: ['.svelte','.md'], 29 | preprocess: markdown({ 30 | renderer:renderer(), 31 | highlight, 32 | langPrefix:'hljs language-' 33 | }) 34 | }), 35 | resolve({preferBuiltins: false}), 36 | commonjs(), 37 | 38 | legacy && babel({ 39 | extensions: ['.js', '.mjs', '.html', '.svelte'], 40 | runtimeHelpers: true, 41 | exclude: ['node_modules/@babel/**'], 42 | presets: [ 43 | ['@babel/preset-env', { 44 | targets: '> 0.25%, not dead' 45 | }] 46 | ], 47 | plugins: [ 48 | '@babel/plugin-syntax-dynamic-import', 49 | ['@babel/plugin-transform-runtime', { 50 | useESModules: true 51 | }] 52 | ] 53 | }) 54 | ], 55 | }, 56 | 57 | server: { 58 | input: config.server.input(), 59 | output: config.server.output(), 60 | plugins: [ 61 | replace({ 62 | 'process.browser': false, 63 | 'process.env.NODE_ENV': JSON.stringify(mode) 64 | }), 65 | svelte({ 66 | generate: 'ssr', 67 | dev, 68 | extensions: ['.svelte','.md'], 69 | preprocess: markdown({ 70 | renderer:renderer(), 71 | highlight, 72 | langPrefix:'hljs language-' 73 | }) 74 | }), 75 | resolve(), 76 | commonjs() 77 | ], 78 | external: Object.keys(pkg.dependencies).concat( 79 | require('module').builtinModules || Object.keys(process.binding('natives')) 80 | ), 81 | }, 82 | 83 | serviceworker: { 84 | input: config.serviceworker.input(), 85 | output: config.serviceworker.output(), 86 | plugins: [ 87 | resolve(), 88 | replace({ 89 | 'process.browser': true, 90 | 'process.env.NODE_ENV': JSON.stringify(mode) 91 | }), 92 | commonjs() 93 | ] 94 | } 95 | }; 96 | -------------------------------------------------------------------------------- /docs_src/src/client.js: -------------------------------------------------------------------------------- 1 | import * as sapper from '@sapper/app'; 2 | 3 | sapper.start({ 4 | target: document.querySelector('#sapper') 5 | }); -------------------------------------------------------------------------------- /docs_src/src/components/Docs.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | {#each pages as page} 6 | 7 |
8 | {/each} 9 | 10 | -------------------------------------------------------------------------------- /docs_src/src/components/Example.svelte: -------------------------------------------------------------------------------- 1 | 26 | 27 |
28 |
29 | 33 |
34 |
35 | 36 | -------------------------------------------------------------------------------- /docs_src/src/components/Repl/Bundler.js: -------------------------------------------------------------------------------- 1 | import { create_worker } from "./utils.js"; 2 | 3 | const workers = new Map(); 4 | 5 | let uid = 1; 6 | 7 | function worker_fn() { 8 | self.window = self; // egregious hack to get magic-string to work in a worker 9 | 10 | let svelteUrl; 11 | 12 | let fulfil; 13 | let ready = new Promise(f => (fulfil = f)); 14 | 15 | self.addEventListener("message", async event => { 16 | switch (event.data.type) { 17 | case "init": 18 | svelteUrl = event.data.svelteUrl; 19 | 20 | importScripts(`${svelteUrl}/compiler.js`, event.data.rollupUrl); 21 | fulfil(); 22 | 23 | break; 24 | 25 | case "bundle": 26 | if (event.data.components.length === 0) return; 27 | 28 | await ready; 29 | const result = await bundle(event.data); 30 | if (result) { 31 | postMessage(result); 32 | } 33 | 34 | break; 35 | } 36 | }); 37 | 38 | const common_options = { 39 | dev: true 40 | }; 41 | 42 | let cached = { 43 | dom: {}, 44 | ssr: {} 45 | }; 46 | 47 | const is_svelte_module = id => id === "svelte" || id.startsWith("svelte/"); 48 | 49 | const cache = new Map(); 50 | function fetch_if_uncached(url) { 51 | if (!cache.has(url)) { 52 | cache.set( 53 | url, 54 | fetch(url) 55 | .then(r => r.text()) 56 | .catch(err => { 57 | console.error(err); 58 | cache.delete(url); 59 | }) 60 | ); 61 | } 62 | 63 | return cache.get(url); 64 | } 65 | 66 | async function get_bundle(mode, cache, lookup) { 67 | let bundle; 68 | const all_warnings = []; 69 | 70 | const new_cache = {}; 71 | 72 | try { 73 | bundle = await rollup.rollup({ 74 | input: "./App.md", 75 | external: id => { 76 | if (id[0] === ".") return false; 77 | if (is_svelte_module(id)) return false; 78 | if (id.startsWith("http://")) return false; 79 | if (id.startsWith("https://")) return false; 80 | return true; 81 | }, 82 | plugins: [ 83 | { 84 | resolveId(importee, importer) { 85 | // v3 hack 86 | // console.log(importer, importee) 87 | if (importee === `svelte`) return `${svelteUrl}/index.mjs`; 88 | if (importee.startsWith(`svelte/`)) 89 | return `${svelteUrl}/${importee.slice(7)}/index.mjs`; 90 | 91 | if ( 92 | importer && 93 | (importer.startsWith(`https://`) || 94 | importer.startsWith(`http://`)) 95 | ) { 96 | return new URL(`${importee}/index.mjs`, importer).href; 97 | } 98 | 99 | if (importee.endsWith(".html")) 100 | importee = importee.replace(/\.html$/, ".svelte"); 101 | 102 | if (importee in lookup) return importee; 103 | 104 | throw new Error( 105 | `Could not resolve "${importee}" from "${importer}"` 106 | ); 107 | }, 108 | load(id) { 109 | if (id.startsWith(`https://`) || id.startsWith(`http://`)) 110 | return fetch_if_uncached(id); 111 | if (id in lookup) return lookup[id].source; 112 | }, 113 | transform(code, id) { 114 | if (!/\.svelte$|\.md$/.test(id)) return null; 115 | const name = id 116 | .replace(/^\.\//, "") 117 | .replace(/\.svelte$|\.md$/, ""); 118 | 119 | const result = 120 | cache[id] && cache[id].code === code 121 | ? cache[id].result 122 | : svelte.compile( 123 | code, 124 | Object.assign( 125 | { 126 | generate: mode, 127 | format: "esm", 128 | name, 129 | 130 | filename: name + ".svelte" 131 | }, 132 | common_options 133 | ) 134 | ); 135 | 136 | new_cache[id] = { code, result }; 137 | 138 | (result.warnings || result.stats.warnings).forEach(warning => { 139 | // TODO remove stats post-launch 140 | all_warnings.push({ 141 | message: warning.message, 142 | filename: warning.filename, 143 | start: warning.start, 144 | end: warning.end 145 | }); 146 | }); 147 | 148 | return result.js; 149 | } 150 | } 151 | ], 152 | inlineDynamicImports: true, 153 | onwarn(warning) { 154 | all_warnings.push({ 155 | message: warning.message 156 | }); 157 | } 158 | }); 159 | } catch (error) { 160 | return { error, bundle: null, cache: new_cache, warnings: all_warnings }; 161 | } 162 | 163 | return { bundle, cache: new_cache, error: null, warnings: all_warnings }; 164 | } 165 | 166 | async function bundle({ id, components }) { 167 | // console.clear(); 168 | console.log( 169 | `running Svelte compiler version %c${svelte.VERSION}`, 170 | "font-weight: bold" 171 | ); 172 | 173 | const lookup = {}; 174 | components.forEach(component => { 175 | const path = `./${component.name}.${component.type}`; 176 | lookup[path] = component; 177 | }); 178 | 179 | const import_map = new Map(); 180 | let dom; 181 | let error; 182 | 183 | try { 184 | dom = await get_bundle("dom", cached.dom, lookup); 185 | if (dom.error) { 186 | throw dom.error; 187 | } 188 | 189 | cached.dom = dom.cache; 190 | 191 | let uid = 1; 192 | 193 | const dom_result = (await dom.bundle.generate({ 194 | format: "iife", 195 | name: "SvelteComponent", 196 | globals: id => { 197 | const name = `import_${uid++}`; 198 | import_map.set(id, name); 199 | return name; 200 | }, 201 | exports: "named", 202 | sourcemap: true 203 | })).output[0]; 204 | 205 | const ssr = false // TODO how can we do SSR? 206 | ? await get_bundle("ssr", cached.ssr, lookup) 207 | : null; 208 | 209 | if (ssr) { 210 | cached.ssr = ssr.cache; 211 | if (ssr.error) { 212 | throw ssr.error; 213 | } 214 | } 215 | 216 | const ssr_result = ssr 217 | ? (await ssr.bundle.generate({ 218 | format: "iife", 219 | name: "SvelteComponent", 220 | globals: id => import_map.get(id), 221 | exports: "named", 222 | sourcemap: true 223 | })).output[0] 224 | : null; 225 | 226 | return { 227 | id, 228 | imports: dom_result.imports, 229 | import_map, 230 | dom: dom_result, 231 | ssr: ssr_result, 232 | warnings: dom.warnings, 233 | error: null 234 | }; 235 | } catch (err) { 236 | const e = error || err; 237 | delete e.toString; 238 | 239 | return { 240 | id, 241 | imports: [], 242 | import_map, 243 | dom: null, 244 | ssr: null, 245 | warnings: dom.warnings, 246 | error: Object.assign({}, e, { 247 | message: e.message, 248 | stack: e.stack 249 | }) 250 | }; 251 | } 252 | } 253 | } 254 | 255 | export default class Bundler { 256 | constructor(svelteUrl, rollupUrl) { 257 | if (!workers.has(svelteUrl)) { 258 | const worker = create_worker(worker_fn); 259 | worker.postMessage({ type: "init", svelteUrl, rollupUrl }); 260 | workers.set(svelteUrl, worker); 261 | } 262 | 263 | this.worker = workers.get(svelteUrl); 264 | 265 | this.handlers = new Map(); 266 | 267 | this.worker.addEventListener("message", event => { 268 | const handler = this.handlers.get(event.data.id); 269 | 270 | if (handler) { 271 | // if no handler, was meant for a different REPL 272 | handler(event.data); 273 | this.handlers.delete(event.data.id); 274 | } 275 | }); 276 | } 277 | 278 | bundle(components) { 279 | return new Promise(fulfil => { 280 | const id = uid++; 281 | 282 | this.handlers.set(id, fulfil); 283 | 284 | this.worker.postMessage({ 285 | id, 286 | type: "bundle", 287 | components 288 | }); 289 | }); 290 | } 291 | 292 | destroy() { 293 | this.worker.terminate(); 294 | } 295 | } 296 | -------------------------------------------------------------------------------- /docs_src/src/components/Repl/CodeMirror.svelte: -------------------------------------------------------------------------------- 1 | 17 | 18 | 208 | 209 | 276 | 277 |
282 | 283 |