create-textmode 1.0.6 → 1.1.0
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/LICENSE +661 -21
- package/README.md +120 -86
- package/bin/index.js +8 -8
- package/package.json +76 -54
- package/src/args.js +60 -30
- package/src/banner.js +57 -57
- package/src/cli.js +161 -154
- package/src/constants.js +59 -23
- package/src/fs-utils.js +133 -85
- package/src/packageManager.js +18 -18
- package/src/prompts.js +103 -90
- package/src/runCommand.js +46 -46
- package/src/summary.js +38 -33
- package/src/textmodeVersion.js +57 -45
- package/src/usage.js +23 -18
- package/src/versions.js +56 -52
- package/templates/vanilla-js/.prettierrc +8 -8
- package/templates/vanilla-js/_gitignore +2 -2
- package/templates/vanilla-js/eslint.config.js +22 -22
- package/templates/vanilla-js/index.html +25 -25
- package/templates/vanilla-js/package.json +26 -26
- package/templates/vanilla-js/src/sketch.js +28 -28
- package/templates/vanilla-js/vite.config.js +7 -7
- package/templates/vanilla-js-tweakpane/_gitignore +2 -2
- package/templates/vanilla-js-tweakpane/eslint.config.js +22 -22
- package/templates/vanilla-js-tweakpane/index.html +37 -37
- package/templates/vanilla-js-tweakpane/package.json +27 -27
- package/templates/vanilla-js-tweakpane/src/sketch.js +62 -62
- package/templates/vanilla-js-tweakpane/vite.config.js +7 -7
- package/templates/vanilla-ts/.prettierrc +8 -8
- package/templates/vanilla-ts/_gitignore +1 -1
- package/templates/vanilla-ts/eslint.config.js +23 -23
- package/templates/vanilla-ts/index.html +26 -26
- package/templates/vanilla-ts/package.json +30 -30
- package/templates/vanilla-ts/src/sketch.ts +28 -28
- package/templates/vanilla-ts/tsconfig.json +15 -15
- package/templates/vanilla-ts/vite.config.ts +7 -7
- package/templates/vanilla-ts-tweakpane/_gitignore +2 -2
- package/templates/vanilla-ts-tweakpane/eslint.config.js +23 -23
- package/templates/vanilla-ts-tweakpane/index.html +37 -37
- package/templates/vanilla-ts-tweakpane/package.json +32 -32
- package/templates/vanilla-ts-tweakpane/src/sketch.ts +72 -72
- package/templates/vanilla-ts-tweakpane/tsconfig.json +15 -15
- package/templates/vanilla-ts-tweakpane/vite.config.ts +7 -7
- package/templates/vanilla-js-fxhash/_gitignore +0 -2
- package/templates/vanilla-js-fxhash/eslint.config.js +0 -22
- package/templates/vanilla-js-fxhash/index.html +0 -27
- package/templates/vanilla-js-fxhash/package.json +0 -26
- package/templates/vanilla-js-fxhash/public/fxhash.min.js +0 -1
- package/templates/vanilla-js-fxhash/src/sketch.js +0 -101
- package/templates/vanilla-js-fxhash/vite.config.js +0 -7
- package/templates/vanilla-ts-fxhash/_gitignore +0 -2
- package/templates/vanilla-ts-fxhash/eslint.config.js +0 -23
- package/templates/vanilla-ts-fxhash/index.html +0 -27
- package/templates/vanilla-ts-fxhash/package.json +0 -30
- package/templates/vanilla-ts-fxhash/public/fxhash.min.js +0 -1
- package/templates/vanilla-ts-fxhash/src/fxhash.d.ts +0 -54
- package/templates/vanilla-ts-fxhash/src/sketch.ts +0 -108
- package/templates/vanilla-ts-fxhash/tsconfig.json +0 -15
- package/templates/vanilla-ts-fxhash/vite.config.ts +0 -7
package/src/versions.js
CHANGED
|
@@ -1,52 +1,56 @@
|
|
|
1
|
-
import https from 'https';
|
|
2
|
-
|
|
3
|
-
let cachedVersions = null;
|
|
4
|
-
|
|
5
|
-
function fetchJson(url) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function isStable(version) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function compareSemverDesc(a, b) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
1
|
+
import https from 'https';
|
|
2
|
+
|
|
3
|
+
let cachedVersions = null;
|
|
4
|
+
|
|
5
|
+
function fetchJson(url) {
|
|
6
|
+
return new Promise((resolve, reject) => {
|
|
7
|
+
https
|
|
8
|
+
.get(url, (res) => {
|
|
9
|
+
let data = '';
|
|
10
|
+
res.on('data', (chunk) => {
|
|
11
|
+
data += chunk;
|
|
12
|
+
});
|
|
13
|
+
res.on('end', () => {
|
|
14
|
+
try {
|
|
15
|
+
resolve(JSON.parse(data));
|
|
16
|
+
} catch (err) {
|
|
17
|
+
reject(err);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
})
|
|
21
|
+
.on('error', reject);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function isStable(version) {
|
|
26
|
+
// Exclude prerelease tags like -beta, -rc, etc.
|
|
27
|
+
return !version.includes('-');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function compareSemverDesc(a, b) {
|
|
31
|
+
const pa = a.split('.').map(Number);
|
|
32
|
+
const pb = b.split('.').map(Number);
|
|
33
|
+
for (let i = 0; i < Math.max(pa.length, pb.length); i += 1) {
|
|
34
|
+
const va = pa[i] || 0;
|
|
35
|
+
const vb = pb[i] || 0;
|
|
36
|
+
if (va > vb) return -1;
|
|
37
|
+
if (va < vb) return 1;
|
|
38
|
+
}
|
|
39
|
+
return 0;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function filterAtLeast(versions, min) {
|
|
43
|
+
return versions.filter((v) => compareSemverDesc(v, min) <= 0);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export async function getTextmodeVersions(limit = 20) {
|
|
47
|
+
if (cachedVersions) return cachedVersions.slice(0, limit);
|
|
48
|
+
|
|
49
|
+
const data = await fetchJson('https://registry.npmjs.org/textmode.js');
|
|
50
|
+
const versions = Object.keys(data.versions || {})
|
|
51
|
+
.filter(isStable)
|
|
52
|
+
.sort(compareSemverDesc);
|
|
53
|
+
|
|
54
|
+
cachedVersions = versions;
|
|
55
|
+
return versions.slice(0, limit);
|
|
56
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://json.schemastore.org/prettierrc",
|
|
3
|
-
"printWidth": 80,
|
|
4
|
-
"tabWidth": 2,
|
|
5
|
-
"singleQuote": true,
|
|
6
|
-
"trailingComma": "es5",
|
|
7
|
-
"semi": true
|
|
8
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/prettierrc",
|
|
3
|
+
"printWidth": 80,
|
|
4
|
+
"tabWidth": 2,
|
|
5
|
+
"singleQuote": true,
|
|
6
|
+
"trailingComma": "es5",
|
|
7
|
+
"semi": true
|
|
8
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
node_modules
|
|
2
|
-
dist
|
|
1
|
+
node_modules
|
|
2
|
+
dist
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import { defineConfig } from "eslint/config";
|
|
2
|
-
import js from "@eslint/js";
|
|
3
|
-
import globals from "globals";
|
|
4
|
-
import prettierConfig from "eslint-config-prettier";
|
|
5
|
-
|
|
6
|
-
export default defineConfig([
|
|
7
|
-
{
|
|
8
|
-
ignores: ["dist/**", "node_modules/**"],
|
|
9
|
-
},
|
|
10
|
-
js.configs.recommended,
|
|
11
|
-
prettierConfig,
|
|
12
|
-
{
|
|
13
|
-
files: ["**/*.js"],
|
|
14
|
-
languageOptions: {
|
|
15
|
-
ecmaVersion: "latest",
|
|
16
|
-
sourceType: "module",
|
|
17
|
-
globals: {
|
|
18
|
-
...globals.browser,
|
|
19
|
-
},
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
]);
|
|
1
|
+
import { defineConfig } from "eslint/config";
|
|
2
|
+
import js from "@eslint/js";
|
|
3
|
+
import globals from "globals";
|
|
4
|
+
import prettierConfig from "eslint-config-prettier";
|
|
5
|
+
|
|
6
|
+
export default defineConfig([
|
|
7
|
+
{
|
|
8
|
+
ignores: ["dist/**", "node_modules/**"],
|
|
9
|
+
},
|
|
10
|
+
js.configs.recommended,
|
|
11
|
+
prettierConfig,
|
|
12
|
+
{
|
|
13
|
+
files: ["**/*.js"],
|
|
14
|
+
languageOptions: {
|
|
15
|
+
ecmaVersion: "latest",
|
|
16
|
+
sourceType: "module",
|
|
17
|
+
globals: {
|
|
18
|
+
...globals.browser,
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
]);
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
|
|
4
|
-
<head>
|
|
5
|
-
<meta charset="UTF-8" />
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
-
<title>{{name}}</title>
|
|
8
|
-
|
|
9
|
-
<style>
|
|
10
|
-
html,
|
|
11
|
-
body {
|
|
12
|
-
margin: 0;
|
|
13
|
-
padding: 0;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
canvas {
|
|
17
|
-
display: block;
|
|
18
|
-
}
|
|
19
|
-
</style>
|
|
20
|
-
</head>
|
|
21
|
-
|
|
22
|
-
<body>
|
|
23
|
-
<script type="module" src="/src/sketch.js"></script>
|
|
24
|
-
</body>
|
|
25
|
-
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>{{name}}</title>
|
|
8
|
+
|
|
9
|
+
<style>
|
|
10
|
+
html,
|
|
11
|
+
body {
|
|
12
|
+
margin: 0;
|
|
13
|
+
padding: 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
canvas {
|
|
17
|
+
display: block;
|
|
18
|
+
}
|
|
19
|
+
</style>
|
|
20
|
+
</head>
|
|
21
|
+
|
|
22
|
+
<body>
|
|
23
|
+
<script type="module" src="/src/sketch.js"></script>
|
|
24
|
+
</body>
|
|
25
|
+
|
|
26
26
|
</html>
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "{{name}}",
|
|
3
|
-
"version": "0.0.0",
|
|
4
|
-
"private": true,
|
|
5
|
-
"type": "module",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"dev": "vite",
|
|
8
|
-
"build": "vite build",
|
|
9
|
-
"preview": "vite preview",
|
|
10
|
-
"format": "prettier --write \"src/**/*.{js,ts}\"",
|
|
11
|
-
"format:check": "prettier --check \"src/**/*.{js,ts}\"",
|
|
12
|
-
"lint": "eslint
|
|
13
|
-
"lint:fix": "eslint
|
|
14
|
-
},
|
|
15
|
-
"dependencies": {
|
|
16
|
-
"textmode.js": "latest"
|
|
17
|
-
},
|
|
18
|
-
"devDependencies": {
|
|
19
|
-
"@eslint/js": "^
|
|
20
|
-
"eslint": "^
|
|
21
|
-
"eslint-config-prettier": "^10.1.8",
|
|
22
|
-
"globals": "^
|
|
23
|
-
"prettier": "^3.
|
|
24
|
-
"vite": "^
|
|
25
|
-
}
|
|
26
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "{{name}}",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite",
|
|
8
|
+
"build": "vite build",
|
|
9
|
+
"preview": "vite preview",
|
|
10
|
+
"format": "prettier --write \"src/**/*.{js,ts}\"",
|
|
11
|
+
"format:check": "prettier --check \"src/**/*.{js,ts}\"",
|
|
12
|
+
"lint": "eslint .",
|
|
13
|
+
"lint:fix": "eslint . --fix"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"textmode.js": "latest"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@eslint/js": "^10.0.1",
|
|
20
|
+
"eslint": "^10.8.1",
|
|
21
|
+
"eslint-config-prettier": "^10.1.8",
|
|
22
|
+
"globals": "^16.0.0",
|
|
23
|
+
"prettier": "^3.9.5",
|
|
24
|
+
"vite": "^8.1.3"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
import { textmode } from 'textmode.js';
|
|
2
|
-
|
|
3
|
-
const tm = textmode.create({ width: window.innerWidth, height: window.innerHeight });
|
|
4
|
-
|
|
5
|
-
tm.draw(() => {
|
|
6
|
-
tm.background(0);
|
|
7
|
-
|
|
8
|
-
const halfCols = (tm.grid.cols / 2) + 1;
|
|
9
|
-
const halfRows = (tm.grid.rows / 2) + 1;
|
|
10
|
-
|
|
11
|
-
for (let y = -halfRows; y < halfRows; y++) {
|
|
12
|
-
for (let x = -halfCols; x < halfCols; x++) {
|
|
13
|
-
const dist = Math.sqrt(x * x + y * y);
|
|
14
|
-
const wave = Math.sin(dist * 0.2 - tm.frameCount * 0.1);
|
|
15
|
-
|
|
16
|
-
tm.push();
|
|
17
|
-
tm.translate(x, y, 0);
|
|
18
|
-
tm.char(wave > 0.5 ? '▓' : wave > 0 ? '▒' : '░');
|
|
19
|
-
tm.charColor(0, 150 + wave * 100, 255);
|
|
20
|
-
tm.point();
|
|
21
|
-
tm.pop();
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
tm.windowResized(() => {
|
|
27
|
-
tm.resizeCanvas(window.innerWidth, window.innerHeight);
|
|
28
|
-
});
|
|
1
|
+
import { textmode } from 'textmode.js';
|
|
2
|
+
|
|
3
|
+
const tm = textmode.create({ width: window.innerWidth, height: window.innerHeight });
|
|
4
|
+
|
|
5
|
+
tm.draw(() => {
|
|
6
|
+
tm.background(0);
|
|
7
|
+
|
|
8
|
+
const halfCols = (tm.grid.cols / 2) + 1;
|
|
9
|
+
const halfRows = (tm.grid.rows / 2) + 1;
|
|
10
|
+
|
|
11
|
+
for (let y = -halfRows; y < halfRows; y++) {
|
|
12
|
+
for (let x = -halfCols; x < halfCols; x++) {
|
|
13
|
+
const dist = Math.sqrt(x * x + y * y);
|
|
14
|
+
const wave = Math.sin(dist * 0.2 - tm.frameCount * 0.1);
|
|
15
|
+
|
|
16
|
+
tm.push();
|
|
17
|
+
tm.translate(x, y, 0);
|
|
18
|
+
tm.char(wave > 0.5 ? '▓' : wave > 0 ? '▒' : '░');
|
|
19
|
+
tm.charColor(0, 150 + wave * 100, 255);
|
|
20
|
+
tm.point();
|
|
21
|
+
tm.pop();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
tm.windowResized(() => {
|
|
27
|
+
tm.resizeCanvas(window.innerWidth, window.innerHeight);
|
|
28
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { defineConfig } from 'vite';
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
server: {
|
|
5
|
-
open: true
|
|
6
|
-
}
|
|
7
|
-
});
|
|
1
|
+
import { defineConfig } from 'vite';
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
server: {
|
|
5
|
+
open: true
|
|
6
|
+
}
|
|
7
|
+
});
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
node_modules
|
|
2
|
-
dist
|
|
1
|
+
node_modules
|
|
2
|
+
dist
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import { defineConfig } from "eslint/config";
|
|
2
|
-
import js from "@eslint/js";
|
|
3
|
-
import globals from "globals";
|
|
4
|
-
import prettierConfig from "eslint-config-prettier";
|
|
5
|
-
|
|
6
|
-
export default defineConfig([
|
|
7
|
-
{
|
|
8
|
-
ignores: ["dist/**", "node_modules/**"],
|
|
9
|
-
},
|
|
10
|
-
js.configs.recommended,
|
|
11
|
-
prettierConfig,
|
|
12
|
-
{
|
|
13
|
-
files: ["**/*.js"],
|
|
14
|
-
languageOptions: {
|
|
15
|
-
ecmaVersion: "latest",
|
|
16
|
-
sourceType: "module",
|
|
17
|
-
globals: {
|
|
18
|
-
...globals.browser,
|
|
19
|
-
},
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
]);
|
|
1
|
+
import { defineConfig } from "eslint/config";
|
|
2
|
+
import js from "@eslint/js";
|
|
3
|
+
import globals from "globals";
|
|
4
|
+
import prettierConfig from "eslint-config-prettier";
|
|
5
|
+
|
|
6
|
+
export default defineConfig([
|
|
7
|
+
{
|
|
8
|
+
ignores: ["dist/**", "node_modules/**"],
|
|
9
|
+
},
|
|
10
|
+
js.configs.recommended,
|
|
11
|
+
prettierConfig,
|
|
12
|
+
{
|
|
13
|
+
files: ["**/*.js"],
|
|
14
|
+
languageOptions: {
|
|
15
|
+
ecmaVersion: "latest",
|
|
16
|
+
sourceType: "module",
|
|
17
|
+
globals: {
|
|
18
|
+
...globals.browser,
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
]);
|
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
|
|
4
|
-
<head>
|
|
5
|
-
<meta charset="UTF-8" />
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
-
<title>{{name}}</title>
|
|
8
|
-
|
|
9
|
-
<style>
|
|
10
|
-
html,
|
|
11
|
-
body {
|
|
12
|
-
margin: 0;
|
|
13
|
-
padding: 0;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
canvas {
|
|
17
|
-
display: block;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
#pane {
|
|
21
|
-
position: fixed;
|
|
22
|
-
top: 12px;
|
|
23
|
-
right: 12px;
|
|
24
|
-
width: 260px;
|
|
25
|
-
z-index: 10;
|
|
26
|
-
pointer-events: auto;
|
|
27
|
-
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
28
|
-
}
|
|
29
|
-
</style>
|
|
30
|
-
</head>
|
|
31
|
-
|
|
32
|
-
<body>
|
|
33
|
-
<div id="pane"></div>
|
|
34
|
-
<script type="module" src="/src/sketch.js"></script>
|
|
35
|
-
</body>
|
|
36
|
-
|
|
37
|
-
</html>
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>{{name}}</title>
|
|
8
|
+
|
|
9
|
+
<style>
|
|
10
|
+
html,
|
|
11
|
+
body {
|
|
12
|
+
margin: 0;
|
|
13
|
+
padding: 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
canvas {
|
|
17
|
+
display: block;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
#pane {
|
|
21
|
+
position: fixed;
|
|
22
|
+
top: 12px;
|
|
23
|
+
right: 12px;
|
|
24
|
+
width: 260px;
|
|
25
|
+
z-index: 10;
|
|
26
|
+
pointer-events: auto;
|
|
27
|
+
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
28
|
+
}
|
|
29
|
+
</style>
|
|
30
|
+
</head>
|
|
31
|
+
|
|
32
|
+
<body>
|
|
33
|
+
<div id="pane"></div>
|
|
34
|
+
<script type="module" src="/src/sketch.js"></script>
|
|
35
|
+
</body>
|
|
36
|
+
|
|
37
|
+
</html>
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "{{name}}",
|
|
3
|
-
"version": "0.0.0",
|
|
4
|
-
"private": true,
|
|
5
|
-
"type": "module",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"dev": "vite",
|
|
8
|
-
"build": "vite build",
|
|
9
|
-
"preview": "vite preview",
|
|
10
|
-
"format": "prettier --write \"src/**/*.{js,ts}\"",
|
|
11
|
-
"format:check": "prettier --check \"src/**/*.{js,ts}\"",
|
|
12
|
-
"lint": "eslint
|
|
13
|
-
"lint:fix": "eslint
|
|
14
|
-
},
|
|
15
|
-
"dependencies": {
|
|
16
|
-
"textmode.js": "latest",
|
|
17
|
-
"tweakpane": "^4.0.5"
|
|
18
|
-
},
|
|
19
|
-
"devDependencies": {
|
|
20
|
-
"@eslint/js": "^
|
|
21
|
-
"eslint": "^
|
|
22
|
-
"eslint-config-prettier": "^10.1.8",
|
|
23
|
-
"globals": "^
|
|
24
|
-
"prettier": "^3.
|
|
25
|
-
"vite": "^
|
|
26
|
-
}
|
|
27
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "{{name}}",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite",
|
|
8
|
+
"build": "vite build",
|
|
9
|
+
"preview": "vite preview",
|
|
10
|
+
"format": "prettier --write \"src/**/*.{js,ts}\"",
|
|
11
|
+
"format:check": "prettier --check \"src/**/*.{js,ts}\"",
|
|
12
|
+
"lint": "eslint .",
|
|
13
|
+
"lint:fix": "eslint . --fix"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"textmode.js": "latest",
|
|
17
|
+
"tweakpane": "^4.0.5"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@eslint/js": "^10.0.1",
|
|
21
|
+
"eslint": "^10.8.1",
|
|
22
|
+
"eslint-config-prettier": "^10.1.8",
|
|
23
|
+
"globals": "^16.0.0",
|
|
24
|
+
"prettier": "^3.9.5",
|
|
25
|
+
"vite": "^8.1.3"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
import { textmode } from 'textmode.js';
|
|
2
|
-
import { Pane } from 'tweakpane';
|
|
3
|
-
|
|
4
|
-
const tm = textmode.create({ width: window.innerWidth, height: window.innerHeight });
|
|
5
|
-
|
|
6
|
-
const params = {
|
|
7
|
-
speed: 0.1,
|
|
8
|
-
frequency: 0.22,
|
|
9
|
-
amplitude: 1.1,
|
|
10
|
-
baseCharColor: { r: 0, g: 170, b: 255 },
|
|
11
|
-
baseCellColor: { r: 0, g: 0, b: 0 }
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
const paneContainer = document.querySelector('#pane') ?? undefined;
|
|
15
|
-
const pane = new Pane({ title: 'Controls', container: paneContainer });
|
|
16
|
-
|
|
17
|
-
pane.addBinding(params, 'speed', { min: 0, max: 0.4, step: 0.005, label: 'Speed' });
|
|
18
|
-
pane.addBinding(params, 'frequency', { min: 0.05, max: 0.8, step: 0.01, label: 'Frequency' });
|
|
19
|
-
pane.addBinding(params, 'amplitude', { min: 0.5, max: 2.0, step: 0.05, label: 'Amplitude' });
|
|
20
|
-
pane.addBinding(params, 'baseCharColor', { label: 'Base Char Color' });
|
|
21
|
-
pane.addBinding(params, 'baseCellColor', { label: 'Base Cell Color' });
|
|
22
|
-
|
|
23
|
-
const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
|
|
24
|
-
|
|
25
|
-
const getChar = (wave) => {
|
|
26
|
-
if (wave > 0.6) return '▓';
|
|
27
|
-
if (wave > 0.2) return '▒';
|
|
28
|
-
return '░';
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
tm.draw(() => {
|
|
32
|
-
const halfCols = Math.round(tm.grid.cols / 2) + 1;
|
|
33
|
-
const halfRows = Math.round(tm.grid.rows / 2) + 1;
|
|
34
|
-
|
|
35
|
-
for (let y = -halfRows; y < halfRows; y++) {
|
|
36
|
-
for (let x = -halfCols; x < halfCols; x++) {
|
|
37
|
-
const dist = Math.hypot(x, y);
|
|
38
|
-
const wave = Math.sin(dist * params.frequency - tm.frameCount * params.speed) * params.amplitude;
|
|
39
|
-
const char = getChar(wave);
|
|
40
|
-
|
|
41
|
-
const lightness = 0.35 + 0.65 * ((wave + params.amplitude) / (2 * params.amplitude));
|
|
42
|
-
const charR = clamp(params.baseCharColor.r * lightness, 0, 255);
|
|
43
|
-
const charG = clamp(params.baseCharColor.g * lightness, 0, 255);
|
|
44
|
-
const charB = clamp(params.baseCharColor.b * lightness, 0, 255);
|
|
45
|
-
const cellR = clamp(params.baseCellColor.r * lightness, 0, 255);
|
|
46
|
-
const cellG = clamp(params.baseCellColor.g * lightness, 0, 255);
|
|
47
|
-
const cellB = clamp(params.baseCellColor.b * lightness, 0, 255);
|
|
48
|
-
|
|
49
|
-
tm.push();
|
|
50
|
-
tm.translate(x, y, 0);
|
|
51
|
-
tm.char(char);
|
|
52
|
-
tm.charColor(charR, charG, charB);
|
|
53
|
-
tm.cellColor(cellR, cellG, cellB);
|
|
54
|
-
tm.point();
|
|
55
|
-
tm.pop();
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
tm.windowResized(() => {
|
|
61
|
-
tm.resizeCanvas(window.innerWidth, window.innerHeight);
|
|
62
|
-
});
|
|
1
|
+
import { textmode } from 'textmode.js';
|
|
2
|
+
import { Pane } from 'tweakpane';
|
|
3
|
+
|
|
4
|
+
const tm = textmode.create({ width: window.innerWidth, height: window.innerHeight });
|
|
5
|
+
|
|
6
|
+
const params = {
|
|
7
|
+
speed: 0.1,
|
|
8
|
+
frequency: 0.22,
|
|
9
|
+
amplitude: 1.1,
|
|
10
|
+
baseCharColor: { r: 0, g: 170, b: 255 },
|
|
11
|
+
baseCellColor: { r: 0, g: 0, b: 0 }
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const paneContainer = document.querySelector('#pane') ?? undefined;
|
|
15
|
+
const pane = new Pane({ title: 'Controls', container: paneContainer });
|
|
16
|
+
|
|
17
|
+
pane.addBinding(params, 'speed', { min: 0, max: 0.4, step: 0.005, label: 'Speed' });
|
|
18
|
+
pane.addBinding(params, 'frequency', { min: 0.05, max: 0.8, step: 0.01, label: 'Frequency' });
|
|
19
|
+
pane.addBinding(params, 'amplitude', { min: 0.5, max: 2.0, step: 0.05, label: 'Amplitude' });
|
|
20
|
+
pane.addBinding(params, 'baseCharColor', { label: 'Base Char Color' });
|
|
21
|
+
pane.addBinding(params, 'baseCellColor', { label: 'Base Cell Color' });
|
|
22
|
+
|
|
23
|
+
const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
|
|
24
|
+
|
|
25
|
+
const getChar = (wave) => {
|
|
26
|
+
if (wave > 0.6) return '▓';
|
|
27
|
+
if (wave > 0.2) return '▒';
|
|
28
|
+
return '░';
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
tm.draw(() => {
|
|
32
|
+
const halfCols = Math.round(tm.grid.cols / 2) + 1;
|
|
33
|
+
const halfRows = Math.round(tm.grid.rows / 2) + 1;
|
|
34
|
+
|
|
35
|
+
for (let y = -halfRows; y < halfRows; y++) {
|
|
36
|
+
for (let x = -halfCols; x < halfCols; x++) {
|
|
37
|
+
const dist = Math.hypot(x, y);
|
|
38
|
+
const wave = Math.sin(dist * params.frequency - tm.frameCount * params.speed) * params.amplitude;
|
|
39
|
+
const char = getChar(wave);
|
|
40
|
+
|
|
41
|
+
const lightness = 0.35 + 0.65 * ((wave + params.amplitude) / (2 * params.amplitude));
|
|
42
|
+
const charR = clamp(params.baseCharColor.r * lightness, 0, 255);
|
|
43
|
+
const charG = clamp(params.baseCharColor.g * lightness, 0, 255);
|
|
44
|
+
const charB = clamp(params.baseCharColor.b * lightness, 0, 255);
|
|
45
|
+
const cellR = clamp(params.baseCellColor.r * lightness, 0, 255);
|
|
46
|
+
const cellG = clamp(params.baseCellColor.g * lightness, 0, 255);
|
|
47
|
+
const cellB = clamp(params.baseCellColor.b * lightness, 0, 255);
|
|
48
|
+
|
|
49
|
+
tm.push();
|
|
50
|
+
tm.translate(x, y, 0);
|
|
51
|
+
tm.char(char);
|
|
52
|
+
tm.charColor(charR, charG, charB);
|
|
53
|
+
tm.cellColor(cellR, cellG, cellB);
|
|
54
|
+
tm.point();
|
|
55
|
+
tm.pop();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
tm.windowResized(() => {
|
|
61
|
+
tm.resizeCanvas(window.innerWidth, window.innerHeight);
|
|
62
|
+
});
|