@eighty4/dank 0.0.1-3 → 0.0.1-4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -0,0 +1,61 @@
1
+ # Build DANK webpages
2
+
3
+ DANK has some perks:
4
+
5
+ - Webpage-first development for multi-page websites
6
+ - Code splitting via `esbuild` bundler across all webpages
7
+ - `dank serve` updates CSS in real-time (hot-reloading)
8
+ - `dank serve` launches development processes and merges their stdio
9
+ - `dank serve --preview` builds the website and serves the output from `dist`
10
+ - `dank build --production` optimizes with `esbuild` minifying and tree-shaking
11
+ - DANK's codebase is so tiny you can read it all in 20 mins
12
+
13
+ DANK isn't for every use case.
14
+ [Vite](https://vite.dev) is the right move for building a Single-Page Application.
15
+ For SEO optimizing dynamic content with Server-Side Rendering,
16
+ check out [Next.js](https://nextjs.org) or [Astro](https://astro.build).
17
+
18
+ DANK is an ideal choice for building multi-page websites deployed to a CDN.
19
+
20
+ ## Getting started
21
+
22
+ ```shell
23
+ bun create dank --out-dir www
24
+
25
+ npm create dank -- --out-dir www
26
+
27
+ pnpm create dank --out-dir www
28
+ ```
29
+
30
+ ## `dank.config.ts` examples
31
+
32
+ Webpages and their URLs are configured explicitly to keep your URLs
33
+ and workspace organized independently:
34
+
35
+ ```typescript
36
+ import { defineConfig } from '@eighty4/dank'
37
+
38
+ export default defineConfig({
39
+ pages: {
40
+ '/': './home.html',
41
+ },
42
+ })
43
+ ```
44
+
45
+ Streamline development with `dank serve` launching API when starting your dev server:
46
+
47
+ ```typescript
48
+ import { defineConfig } from '@eighty4/dank'
49
+
50
+ export default defineConfig({
51
+ pages: {
52
+ '/': './home.html',
53
+ },
54
+ services: [
55
+ {
56
+ command: 'node --watch --env-file-if-exists=.env.dev server.ts',
57
+ cwd: './api',
58
+ },
59
+ ],
60
+ })
61
+ ```
package/lib/build.ts CHANGED
@@ -42,7 +42,7 @@ export async function buildWebsite(c: DankConfig): Promise<DankBuild> {
42
42
  const result = new Set(buildUrls)
43
43
  await writeBuildManifest(buildTag, result)
44
44
  return {
45
- dir: buildDir,
45
+ dir: distDir,
46
46
  files: result,
47
47
  }
48
48
  }
package/lib/esbuild.ts CHANGED
@@ -21,6 +21,11 @@ const jsBuildOptions: BuildOptions & { metafile: true; write: true } = {
21
21
  const webpageBuildOptions: BuildOptions & { metafile: true; write: true } = {
22
22
  assetNames: 'assets/[name]-[hash]',
23
23
  format: 'esm',
24
+ loader: {
25
+ '.tff': 'file',
26
+ '.woff': 'file',
27
+ '.woff2': 'file',
28
+ },
24
29
  ...jsBuildOptions,
25
30
  }
26
31
 
package/lib/html.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { readFile, writeFile } from 'node:fs/promises'
2
2
  import { dirname, join, relative } from 'node:path'
3
+ import { extname } from 'node:path/posix'
3
4
  import {
4
5
  defaultTreeAdapter,
5
6
  type DefaultTreeAdapterTypes,
@@ -75,12 +76,12 @@ export class HtmlEntrypoint {
75
76
  ) {
76
77
  importScript.elem.attrs.find(
77
78
  attr => attr.name === 'src',
78
- )!.value = rewriteTo || `/${importScript.out}.js`
79
+ )!.value = rewriteTo || `/${importScript.out}`
79
80
  }
80
81
  } else if (importScript.type === 'style') {
81
82
  importScript.elem.attrs.find(
82
83
  attr => attr.name === 'href',
83
- )!.value = rewriteTo || `/${importScript.out}.css`
84
+ )!.value = rewriteTo || `/${importScript.out}`
84
85
  }
85
86
  }
86
87
  }
@@ -182,12 +183,19 @@ export class HtmlEntrypoint {
182
183
 
183
184
  #addScript(type: ImportedScript['type'], href: string, elem: Element) {
184
185
  const inPath = join(dirname(this.#fsPath), href)
186
+ let outPath = inPath.replace(/^pages\//, '')
187
+ if (type === 'script' && !outPath.endsWith('.js')) {
188
+ outPath = outPath.replace(
189
+ new RegExp(extname(outPath).substring(1) + '$'),
190
+ 'js',
191
+ )
192
+ }
185
193
  this.#scripts.push({
186
194
  type,
187
195
  href,
188
196
  elem,
189
197
  in: inPath,
190
- out: inPath.replace(/^pages\//, ''),
198
+ out: outPath,
191
199
  })
192
200
  }
193
201
  }
package/lib/http.ts CHANGED
@@ -90,6 +90,12 @@ function resolveMimeType(url: URL): string {
90
90
  return 'image/svg+xml'
91
91
  case '.png':
92
92
  return 'image/png'
93
+ case '.ttf':
94
+ return 'font/ttf'
95
+ case '.woff':
96
+ return 'font/woff'
97
+ case '.woff2':
98
+ return 'font/woff2'
93
99
  default:
94
100
  console.warn('? mime type for', url.pathname)
95
101
  if (!isProductionBuild()) process.exit(1)
package/lib_js/build.js CHANGED
@@ -28,7 +28,7 @@ export async function buildWebsite(c) {
28
28
  const result = new Set(buildUrls);
29
29
  await writeBuildManifest(buildTag, result);
30
30
  return {
31
- dir: buildDir,
31
+ dir: distDir,
32
32
  files: result,
33
33
  };
34
34
  }
package/lib_js/esbuild.js CHANGED
@@ -12,6 +12,11 @@ const jsBuildOptions = {
12
12
  const webpageBuildOptions = {
13
13
  assetNames: 'assets/[name]-[hash]',
14
14
  format: 'esm',
15
+ loader: {
16
+ '.tff': 'file',
17
+ '.woff': 'file',
18
+ '.woff2': 'file',
19
+ },
15
20
  ...jsBuildOptions,
16
21
  };
17
22
  export async function esbuildDevContext(define, entryPoints, outdir) {
package/lib_js/html.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { readFile, writeFile } from 'node:fs/promises';
2
2
  import { dirname, join, relative } from 'node:path';
3
+ import { extname } from 'node:path/posix';
3
4
  import { defaultTreeAdapter, parse, parseFragment, serialize, } from 'parse5';
4
5
  // unenforced but necessary sequence:
5
6
  // injectPartials
@@ -44,11 +45,11 @@ export class HtmlEntrypoint {
44
45
  if (importScript.type === 'script') {
45
46
  if (importScript.in.endsWith('.tsx') ||
46
47
  importScript.in.endsWith('.ts')) {
47
- importScript.elem.attrs.find(attr => attr.name === 'src').value = rewriteTo || `/${importScript.out}.js`;
48
+ importScript.elem.attrs.find(attr => attr.name === 'src').value = rewriteTo || `/${importScript.out}`;
48
49
  }
49
50
  }
50
51
  else if (importScript.type === 'style') {
51
- importScript.elem.attrs.find(attr => attr.name === 'href').value = rewriteTo || `/${importScript.out}.css`;
52
+ importScript.elem.attrs.find(attr => attr.name === 'href').value = rewriteTo || `/${importScript.out}`;
52
53
  }
53
54
  }
54
55
  }
@@ -121,12 +122,16 @@ export class HtmlEntrypoint {
121
122
  }
122
123
  #addScript(type, href, elem) {
123
124
  const inPath = join(dirname(this.#fsPath), href);
125
+ let outPath = inPath.replace(/^pages\//, '');
126
+ if (type === 'script' && !outPath.endsWith('.js')) {
127
+ outPath = outPath.replace(new RegExp(extname(outPath).substring(1) + '$'), 'js');
128
+ }
124
129
  this.#scripts.push({
125
130
  type,
126
131
  href,
127
132
  elem,
128
133
  in: inPath,
129
- out: inPath.replace(/^pages\//, ''),
134
+ out: outPath,
130
135
  });
131
136
  }
132
137
  }
package/lib_js/http.js CHANGED
@@ -64,6 +64,12 @@ function resolveMimeType(url) {
64
64
  return 'image/svg+xml';
65
65
  case '.png':
66
66
  return 'image/png';
67
+ case '.ttf':
68
+ return 'font/ttf';
69
+ case '.woff':
70
+ return 'font/woff';
71
+ case '.woff2':
72
+ return 'font/woff2';
67
73
  default:
68
74
  console.warn('? mime type for', url.pathname);
69
75
  if (!isProductionBuild())
package/package.json CHANGED
@@ -1,7 +1,14 @@
1
1
  {
2
2
  "name": "@eighty4/dank",
3
- "version": "0.0.1-3",
3
+ "version": "0.0.1-4",
4
4
  "type": "module",
5
+ "description": "Multi-page development system for CDN-deployed websites",
6
+ "keywords": [
7
+ "frontend",
8
+ "bundler",
9
+ "esbuild",
10
+ "dank"
11
+ ],
5
12
  "bin": "./lib_js/bin.js",
6
13
  "exports": {
7
14
  ".": {