@pajh/buldng 0.0.1 → 0.0.3

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/dist/layout.ts ADDED
@@ -0,0 +1,184 @@
1
+ /* --------------------------------------------------
2
+ GLOBAL VIEWPORT STATE
3
+ -------------------------------------------------- */
4
+ function applyCameraSize(mode: string) {
5
+ const cam = document.getElementById("b-camera");
6
+ if (!cam) return;
7
+
8
+ const vw = window.innerWidth;
9
+ const vh = window.innerHeight;
10
+
11
+ let width, height;
12
+
13
+ if (mode === "PORTRAIT") {
14
+ height = vh;
15
+ width = vw;
16
+ } else if (mode === "LANDSCAPE_A") {
17
+ height = vh;
18
+ width = vh * 4/3;
19
+ } else {
20
+ // LANDSCAPE_B
21
+ width = vw;
22
+ height = vw * 3/4;
23
+ }
24
+
25
+ cam.style.width = `${width}px`;
26
+ cam.style.height = `${height}px`;
27
+
28
+ // Center WITHOUT transform (no containing-block issues)
29
+ cam.style.position = "absolute";
30
+ cam.style.top = "0";
31
+ cam.style.bottom = "0";
32
+ cam.style.left = "0";
33
+ cam.style.right = "0";
34
+ cam.style.margin = "auto";
35
+ }
36
+
37
+ export const buldrViewport = {
38
+ width: window.innerWidth,
39
+ height: window.innerHeight,
40
+ aspect: window.innerWidth / window.innerHeight, // w/h
41
+ mode: "PORTRAIT", // PORTRAIT | LANDSCAPE_A | LANDSCAPE_B
42
+ };
43
+
44
+ /* --------------------------------------------------
45
+ MODE COMPUTATION
46
+ -------------------------------------------------- */
47
+
48
+ function computeMode() {
49
+ const a = buldrViewport.aspect;
50
+
51
+ if (a >= 4/3) return "LANDSCAPE_A";
52
+ if (a <= 3/4) return "PORTRAIT";
53
+ return "LANDSCAPE_B";
54
+ }
55
+
56
+ /* --------------------------------------------------
57
+ APPLY CAMERA MODE CLASS
58
+ -------------------------------------------------- */
59
+
60
+ function applyCameraMode(mode: string) {
61
+ const cam = document.getElementById("b-camera");
62
+ if (!cam) return;
63
+ const style = document.getElementById("b-camera-style");
64
+ if (!style) return;
65
+
66
+ // Remove all camera classes
67
+ cam.classList.remove("CAM-PORTRAIT", "CAM-LANDSCAPE-A", "CAM-LANDSCAPE-B");
68
+ style.classList.remove("CAM-PORTRAIT", "CAM-LANDSCAPE-A", "CAM-LANDSCAPE-B");
69
+ // Add the new one
70
+ if (mode === "PORTRAIT") {
71
+ cam.classList.add("CAM-PORTRAIT");
72
+ style.classList.add("CAM-PORTRAIT");
73
+ } else if (mode === "LANDSCAPE_A") {
74
+ cam.classList.add("CAM-LANDSCAPE-A");
75
+ style.classList.add("CAM-LANDSCAPE-A");
76
+ } else {
77
+ cam.classList.add("CAM-LANDSCAPE-B");
78
+ style.classList.add("CAM-LANDSCAPE-B");
79
+ }
80
+ }
81
+
82
+ /* --------------------------------------------------
83
+ APPLY GLOBAL CSS MODE (PORTRAIT / LANDSCAPE)
84
+ -------------------------------------------------- */
85
+ function applyCssMode(mode: string) {
86
+ const html = document.documentElement;
87
+
88
+ if (mode === "PORTRAIT") {
89
+ html.classList.remove("LANDSCAPE");
90
+ html.classList.add("PORTRAIT");
91
+ } else {
92
+ html.classList.remove("PORTRAIT");
93
+ html.classList.add("LANDSCAPE");
94
+ }
95
+ }
96
+ /* --------------------------------------------------
97
+ FONT SIZE COMPUTATION (NEW)
98
+ -------------------------------------------------- */
99
+
100
+ const FACTOR_PORTRAIT = 0.035;
101
+ const FACTOR_LANDSCAPE_B = 0.035;
102
+ const FACTOR_LANDSCAPE_A = 0.020;
103
+
104
+ function applyFontSize(mode: string) {
105
+ const cam = document.getElementById("b-camera");
106
+ if (!cam) return;
107
+
108
+ const camWidth = cam.getBoundingClientRect().width;
109
+
110
+ let factor = FACTOR_PORTRAIT;
111
+ if (mode === "LANDSCAPE_A") factor = FACTOR_LANDSCAPE_A;
112
+ else if (mode === "LANDSCAPE_B") factor = FACTOR_LANDSCAPE_B;
113
+
114
+ const size = camWidth * factor;
115
+
116
+ document.documentElement.style.setProperty("--std-font-size", `${size}px`);
117
+ }
118
+
119
+ /* --------------------------------------------------
120
+ UPDATE + DEBUG
121
+ -------------------------------------------------- */
122
+
123
+ function updateViewportInfo() {
124
+ buldrViewport.width = window.innerWidth;
125
+ buldrViewport.height = window.innerHeight;
126
+ buldrViewport.aspect = window.innerWidth / window.innerHeight;
127
+
128
+ const mode = computeMode();
129
+ buldrViewport.mode = mode;
130
+
131
+ console.log(
132
+ `[BULDR] viewport ${buldrViewport.width}x${buldrViewport.height}, `
133
+ + `aspect=${buldrViewport.aspect.toFixed(3)}, `
134
+ + `mode=${mode}`
135
+ );
136
+
137
+ applyCameraMode(mode);
138
+ applyCssMode(mode);
139
+ applyCameraSize(mode);
140
+ applyFontSize(mode);
141
+ }
142
+
143
+ /* --------------------------------------------------
144
+ THEME
145
+ -------------------------------------------------- */
146
+
147
+ function initTheme() {
148
+ const btn = document.getElementById("theme-toggle");
149
+ if (!btn) return;
150
+
151
+ const current = localStorage.getItem("theme") || "light";
152
+ document.documentElement.dataset.theme = current;
153
+
154
+ btn.addEventListener("click", () => {
155
+ const next = document.documentElement.dataset.theme === "light" ? "dark" : "light";
156
+ document.documentElement.dataset.theme = next;
157
+ localStorage.setItem("theme", next);
158
+ });
159
+ }
160
+
161
+ /* --------------------------------------------------
162
+ VIEWPORT LISTENER
163
+ -------------------------------------------------- */
164
+
165
+ function initViewportListener() {
166
+ updateViewportInfo(); // initial
167
+
168
+ window.addEventListener("resize", () => {
169
+ updateViewportInfo();
170
+ });
171
+ }
172
+
173
+ /* --------------------------------------------------
174
+ LAYOUT INIT
175
+ -------------------------------------------------- */
176
+
177
+ function initLayout() {
178
+ initTheme();
179
+ initViewportListener();
180
+ }
181
+
182
+ // Run layout immediately
183
+ initLayout();
184
+ window.__ready._resolveA();
@@ -0,0 +1,10 @@
1
+ export {};
2
+
3
+ declare global {
4
+ interface Window {
5
+ __ready: {
6
+ a: Promise<void>;
7
+ _resolveA: () => void;
8
+ };
9
+ }
10
+ }
@@ -0,0 +1,69 @@
1
+ // --------------------------------------------------
2
+ // WorkFile — immutable, lazy, tree-structured build node
3
+ // --------------------------------------------------
4
+
5
+ import fs from "node:fs";
6
+ import path from "node:path";
7
+ import esbuild from "esbuild";
8
+ import { assertDestWrite } from "./buldng-lib.js";
9
+ import { OPS } from "./buldng-ops.js";
10
+
11
+ export class WorkFile {
12
+ constructor(op, config = {}, children = [], tag = null) {
13
+ if (!OPS[op]) {
14
+ throw new Error(`Invalid WorkFile op "${op}" — not one of: ${Object.keys(OPS).join(", ")}`);
15
+ }
16
+ this.op = op; // "file", "literal", "append", "replace", "compile"
17
+ this.config = Object.freeze(config);
18
+ this.children = Object.freeze(children);
19
+ this.tag = tag; // optional tag
20
+ Object.freeze(this); // full immutability
21
+ }
22
+
23
+ // --------------------------------------------------
24
+ // execute(): recursively produce output string
25
+ // --------------------------------------------------
26
+ execute() {
27
+ return OPS[this.op](this.config, this.children);
28
+
29
+ }
30
+
31
+ // --------------------------------------------------
32
+ // save(): write output to disk
33
+ // --------------------------------------------------
34
+ save(target) {
35
+ if (!target) {
36
+ throw new Error("WorkFile.save(): target filename required");
37
+ }
38
+
39
+ const abs = assertDestWrite(target);
40
+ const out = this.execute();
41
+
42
+ // If file exists, enforce integrity rule
43
+ if (fs.existsSync(abs)) {
44
+ const existing = fs.readFileSync(abs, "utf8");
45
+
46
+ if (existing === out) {
47
+ // Byte-identical → warn but allow
48
+ console.warn(
49
+ `WorkFile.save(): attempted to overwrite '${target}' with identical content — continuing`
50
+ );
51
+ return "/" + target;
52
+ }
53
+
54
+ // Different → fatal error
55
+ throw new Error(
56
+ `WorkFile.save(): cannot overwrite '${target}' — existing file differs from generated output`
57
+ );
58
+ }
59
+
60
+ // File does not exist → write it
61
+ fs.mkdirSync(path.dirname(abs), { recursive: true });
62
+ fs.writeFileSync(abs, out, "utf8");
63
+ // NEW: mark file read-only
64
+ fs.chmodSync(abs, 0o444);
65
+
66
+ console.log(`save: ${abs}`);
67
+ return "/" + target;
68
+ }
69
+ }
@@ -0,0 +1,24 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>BULDR.IO</title>
7
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg">
8
+ <link rel="stylesheet" href="/buldng.css">
9
+
10
+ <!--CSS-->
11
+ <script>
12
+ window.__ready = {};
13
+ window.__ready.a = new Promise((resolve) => { window.__ready._resolveA = resolve; });
14
+ </script>
15
+ <script type="module" src="/layout.js"></script>
16
+ <!--SCRIPTS-->
17
+ </head>
18
+ <body>
19
+ <div id="b-camera">
20
+ <!-- Project outline (camera-style) will be stitched here -->
21
+ <!--CAMERA-STYLE-->
22
+ </div>
23
+ </body>
24
+ </html>
package/package.json CHANGED
@@ -1,10 +1,19 @@
1
1
  {
2
2
  "name": "@pajh/buldng",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "type": "module",
5
5
  "main": "dist/buldng-lib.js",
6
6
  "files": ["dist"],
7
7
  "scripts": {
8
- "build": "cp src/buldng-lib.js dist/buldng-lib.js"
9
- }
8
+ "build": "node build.js"
9
+ },
10
+ "dependencies": {
11
+ "esbuild": "^0.28.1",
12
+ "typescript": "^7.0.2"
13
+ },
14
+ "devDependencies": {
15
+ "stylelint": "^17.14.1",
16
+ "stylelint-config-standard": "^40.0.0"
17
+ }
18
+
10
19
  }