├── LICENSE
├── README.md
├── index.js
└── test
├── hello.jsx
└── index.js
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Jed Schmidt
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # esbuild-plugin-http-fetch
2 |
3 | An esbuild plugin that resolves http(s) modules, for use with browsers and Deno.
4 |
5 | ## Example
6 | ```js
7 | // test/index.js
8 | import {build, stop} from 'https://deno.land/x/esbuild@v0.12.1/mod.js'
9 | import httpFetch from 'https://deno.land/x/esbuild_plugin_http_fetch@v1.0.2/index.js'
10 |
11 | let {outputFiles} = await build({
12 | bundle: true,
13 | entryPoints: ['test/hello.jsx'],
14 | jsxFactory: 'h',
15 | plugins: [httpFetch],
16 | write: false
17 | })
18 |
19 | eval(outputFiles[0].text)
20 | // expected:
Hello, world!
21 | // actual: Hello, world!
22 |
23 | stop()
24 | ```
25 |
26 | ```js
27 | // test/hello.jsx
28 | import {h} from 'https://unpkg.com/preact@10.5.13/dist/preact.module.js'
29 | import render from 'https://unpkg.com/preact-render-to-string@5.1.19/dist/index.module.js?module'
30 |
31 | let app = Hello, world!
32 | let html = render(app)
33 |
34 | console.log('expected: %s', 'Hello, world!
')
35 | console.log('actual: %s', html)
36 | ```
37 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | let name = 'http-fetch'
2 |
3 | let setup = ({onResolve, onLoad}) => {
4 | onResolve({filter: /^https:\/\//}, resolveFile)
5 | onResolve({filter: /.*/, namespace: 'http-fetch'}, resolveUrl)
6 | onLoad({filter: /.*/, namespace: 'http-fetch'}, loadSource)
7 | }
8 |
9 | let resolveFile = ({path}) => ({
10 | path: path,
11 | namespace: 'http-fetch'
12 | })
13 |
14 | let resolveUrl = ({path, importer}) => ({
15 | path: new URL(path, importer).href,
16 | namespace: 'http-fetch'
17 | })
18 |
19 | let loadSource = async ({path}) => {
20 | let source = await fetch(path)
21 |
22 | if (!source.ok) {
23 | let message = `GET ${path} failed: status ${source.status}`
24 | throw new Error(message)
25 | }
26 |
27 | let contents = await source.text()
28 | let pattern = /\/\/# sourceMappingURL=(\S+)/
29 | let match = contents.match(pattern)
30 | if (match) {
31 | let url = new URL(match[1], source.url)
32 | let dataurl = await loadMap(url)
33 | let comment = `//# sourceMappingURL=${dataurl}`
34 | contents = contents.replace(pattern, comment)
35 | }
36 |
37 | let {pathname} = new URL(source.url)
38 | let loader = pathname.match(/[^.]+$/)[0]
39 |
40 | return {contents, loader}
41 | }
42 |
43 | let loadMap = async url => {
44 | let map = await fetch(url)
45 | let type = map.headers.get('content-type').replace(/\s/g, '')
46 | let buffer = await map.arrayBuffer()
47 | let blob = new Blob([buffer], {type})
48 | let reader = new FileReader()
49 | return new Promise(cb => {
50 | reader.onload = e => cb(e.target.result)
51 | reader.readAsDataURL(blob)
52 | })
53 | }
54 |
55 | export default {name, setup}
56 |
--------------------------------------------------------------------------------
/test/hello.jsx:
--------------------------------------------------------------------------------
1 | import {h} from 'https://unpkg.com/preact@10.5.13/dist/preact.module.js'
2 | import render from 'https://unpkg.com/preact-render-to-string@5.1.19/dist/index.module.js?module'
3 |
4 | let app = Hello, world!
5 | let html = render(app)
6 |
7 | console.log('expected: %s', 'Hello, world!
')
8 | console.log('actual: %s', html)
9 |
--------------------------------------------------------------------------------
/test/index.js:
--------------------------------------------------------------------------------
1 | import {build, stop} from 'https://deno.land/x/esbuild@v0.12.1/mod.js'
2 | import httpFetch from '../http-fetch.js'
3 |
4 | let {outputFiles} = await build({
5 | bundle: true,
6 | entryPoints: ['test/hello.jsx'],
7 | jsxFactory: 'h',
8 | plugins: [httpFetch],
9 | write: false
10 | })
11 |
12 | eval(outputFiles[0].text)
13 | // expected: Hello, world!
14 | // actual: Hello, world!
15 |
16 | stop()
17 |
--------------------------------------------------------------------------------