mordorjs 0.0.1 → 0.0.2

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.
Files changed (3) hide show
  1. package/README.md +53 -3
  2. package/mordor.js +117 -3
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -40,10 +40,60 @@ If no file is provided, it reads from **stdin** (piped text) or defaults to the
40
40
  | Option | Long Form | Description |
41
41
  | :--- | :--- | :--- |
42
42
  | `-w <num>` | `--wide <num>` | **Wrap into Columns:** Re-wraps the text into exactly `<num>` vertical strips. Words are preserved and distributed evenly. |
43
- | `-s` | | **Spacing:** Adds an empty space strip between each data strip for better readability. |
43
+ | `-s` | | **Separator:** Adds a space between each column strip for better readability. |
44
44
  | `-r [num]` | `--random [num]` | **Randomize:** Adds random vertical spacing (0 to `num`) before the first word and between every word in a strip. Default `num` is 3. |
45
- | `-b64` | `--base64` | **Base64 Mode:** Encodes input to Base64 first. Uses "virtual words" (2-7 chars) to allow wrapping and randomization. |
46
- | `-c` | `--copy` | **Clipboard:** Automatically copies the final vertical output to your system clipboard. |
45
+ | `-b64` | `--base64` | **Base64 Mode:** Encodes input to Base64 first. Uses "virtual words" (27 chars) to allow wrapping and randomization. |
46
+ | `-c` | `--copy` | **Clipboard:** Automatically copies the final output to your system clipboard. |
47
+ | `-mjs` | `--mordorjs` | **MordorJS Mode:** Converts a `.js` file into a self-executing 1W vertical program (`.cjs`). |
48
+ | `-pro` | `--project` | **Project Mode:** Packages an entire folder tree into a single `mordor-project` file (skips `node_modules`, hidden files, lock files; images truncated to 1KB). |
49
+ | `-h` | `--help` | **Help:** Show options in mordor-code format (`-w 31 -r 3 -s`), prefixed with `==== M\|\|D\|\|JS ====`. |
50
+ | `-ai-h` | `--ai-help` | **AI Help:** Show options in plain readable text, prefixed with `==== M\|\|D\|\|JS ====`. |
51
+
52
+ ## mordor-code
53
+
54
+ Transform any JS file into a self-executing 1-character-wide vertical program:
55
+
56
+ ```bash
57
+ mordorjs myfile.js -mjs > myfile.cjs
58
+ node myfile.cjs
59
+ ```
60
+
61
+ The generated file runs identically to the original. Shebang lines and `require()` calls are handled automatically.
62
+
63
+ ## mordor-project
64
+
65
+ Package an entire project folder into a single portable text file:
66
+
67
+ ```bash
68
+ mordorjs ./my-project -pro -w 31 -s > my-project.mordor-project.txt
69
+ ```
70
+
71
+ Each file in the folder becomes one entry: a header line followed by the file's content in wide mordor format.
72
+
73
+ **Automatically skipped:**
74
+ - Hidden files and directories (`.git`, `.env`, etc.)
75
+ - `node_modules`, `dist`, `build`, `coverage`, `.next`, `.nuxt`
76
+ - Lock files (`package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`, etc.)
77
+
78
+ **Images** (`.jpg`, `.jpeg`, `.png`): only the first 1KB is included as base64.
79
+ **Binary files**: base64-encoded automatically based on extension.
80
+ **Text files**: included as-is, rendered in the same wide mordor format as the other CLI flags produce.
81
+
82
+ Format spec:
83
+
84
+ ```
85
+ entry :=
86
+ header newline payload
87
+
88
+ header :=
89
+ /^_{4,}\s(.+)\s_{4,}$/
90
+
91
+ header content :=
92
+ <reversed-relative-path>
93
+
94
+ payload :=
95
+ all following lines until next header or EOF
96
+ ```
47
97
 
48
98
  ## License
49
99
 
package/mordor.js CHANGED
@@ -3,6 +3,7 @@
3
3
  /** MordorJS - the world's first real 1W (1-character-wide) programming language. Transforms any JS file into a vertical, executable format where each character occupies its own line. */
4
4
 
5
5
  const fs = require('fs');
6
+ const path = require('path');
6
7
  const { spawnSync } = require('child_process');
7
8
 
8
9
  /** @returns {string} Verticalized `code-begin.js` (base64-embedded), opens the T template literal and defines single-char variable bindings. */
@@ -169,7 +170,78 @@ function generateMordorJS(jsCode) {
169
170
  return prefix + startVert + verticalizedCode + endVert;
170
171
  }
171
172
 
172
- /** CLI entry point parses argv and dispatches to `verticalize` or `generateMordorJS`. */
173
+ /** @param {string} rootDir - Recursively walks a directory tree, returns sorted absolute file paths. Skips `node_modules`, hidden files/dirs, and lock files. @returns {string[]} */
174
+ function walkProjectTree(rootDir) {
175
+ const SKIP_DIRS = new Set(['node_modules', '.git', '.svn', '.hg', '.cache', '.next', '.nuxt', 'dist', 'build', 'coverage']);
176
+ const SKIP_FILES = new Set(['package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'bun.lockb', 'composer.lock', 'Gemfile.lock', 'poetry.lock']);
177
+ const results = [];
178
+ function walk(dir) {
179
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
180
+ entries.sort((a, b) => a.name.localeCompare(b.name));
181
+ for (const entry of entries) {
182
+ if (entry.name.startsWith('.')) continue;
183
+ if (SKIP_DIRS.has(entry.name)) continue;
184
+ if (SKIP_FILES.has(entry.name)) continue;
185
+ const fullPath = path.join(dir, entry.name);
186
+ if (entry.isDirectory() || (entry.isSymbolicLink() && fs.statSync(fullPath).isDirectory())) {
187
+ walk(fullPath);
188
+ } else if (entry.isFile() || entry.isSymbolicLink()) {
189
+ results.push(fullPath);
190
+ }
191
+ }
192
+ }
193
+ walk(rootDir);
194
+ return results;
195
+ }
196
+
197
+ const BINARY_EXTENSIONS = new Set([
198
+ '.png','.jpg','.jpeg','.gif','.ico','.webp','.bmp','.tiff',
199
+ '.pdf','.zip','.tar','.gz','.bz2','.7z','.rar',
200
+ '.woff','.woff2','.ttf','.otf','.eot',
201
+ '.mp3','.mp4','.avi','.mov','.wav','.ogg','.webm',
202
+ '.exe','.dll','.so','.dylib','.bin','.class','.pyc',
203
+ ]);
204
+
205
+ /** @param {string} filePath - Returns true if the file extension is a known binary type. @returns {boolean} */
206
+ function isBinaryExtension(filePath) {
207
+ return BINARY_EXTENSIONS.has(path.extname(filePath).toLowerCase());
208
+ }
209
+
210
+ const IMAGE_EXTENSIONS = new Set(['.jpg', '.jpeg', '.png']);
211
+ const IMAGE_PREVIEW_BYTES = 1024;
212
+
213
+ /** @param {string} filePath - Returns true if the file is an image that should be truncated to 1KB preview. @returns {boolean} */
214
+ function isPreviewImage(filePath) {
215
+ return IMAGE_EXTENSIONS.has(path.extname(filePath).toLowerCase());
216
+ }
217
+
218
+ /** @param {string} reversedPath @param {number} targetWidth - Generates a mordor-project header padded to targetWidth with underscores. @returns {string} */
219
+ function makeProjectHeader(reversedPath, targetWidth = 61) {
220
+ const available = targetWidth - reversedPath.length - 2;
221
+ const left = Math.max(4, Math.ceil(available / 2));
222
+ const right = Math.max(4, available - left);
223
+ return '_'.repeat(left) + ' ' + reversedPath + ' ' + '_'.repeat(right);
224
+ }
225
+
226
+ const HELP_HEADER = '==== M||D||JS ====\n';
227
+ const HELP_BODY = `
228
+ Usage: mordorjs [options] [file]
229
+
230
+ Options:
231
+ -w, --wide <num> Wrap output into N vertical columns
232
+ -s Add separator spaces between columns
233
+ -r, --random [num] Add random spacing between words (default max: 3)
234
+ -b64, --base64 Base64-encode input before rendering
235
+ -c, --copy Copy output to system clipboard
236
+ -mjs, --mordorjs Convert JS file to self-executing 1W .cjs program
237
+ -pro, --project Package entire folder tree into a mordor-project file
238
+ (skips node_modules, hidden files, lock files;
239
+ images truncated to 1KB preview)
240
+ -h, --help Show this help in mordor-code format (-w 31 -r 3 -s)
241
+ -ai-h, --ai-help Show this help in plain text
242
+ `;
243
+
244
+ /** CLI entry point — parses argv and dispatches to `verticalize`, `generateMordorJS`, or `buildMordorProject`. */
173
245
  function main() {
174
246
  const args = process.argv.slice(2);
175
247
  let stripCount = null;
@@ -178,10 +250,17 @@ function main() {
178
250
  let randomMax = null;
179
251
  let isBase64 = false;
180
252
  let isMordorJS = false;
253
+ let isProject = false;
181
254
  let filePath = null;
182
255
 
183
256
  for (let i = 0; i < args.length; i++) {
184
- if (args[i] === '-w' || args[i] === '--wide') {
257
+ if (args[i] === '-h' || args[i] === '--help') {
258
+ process.stdout.write(HELP_HEADER + verticalize(HELP_BODY, 31, true, 3));
259
+ process.exit(0);
260
+ } else if (args[i] === '-ai-h' || args[i] === '--ai-help') {
261
+ process.stdout.write(HELP_HEADER + HELP_BODY);
262
+ process.exit(0);
263
+ } else if (args[i] === '-w' || args[i] === '--wide') {
185
264
  stripCount = parseInt(args[i + 1], 10);
186
265
  i++;
187
266
  } else if (args[i] === '-s') {
@@ -192,6 +271,8 @@ function main() {
192
271
  isBase64 = true;
193
272
  } else if (args[i] === '-mjs' || args[i] === '--mordorjs') {
194
273
  isMordorJS = true;
274
+ } else if (args[i] === '-pro' || args[i] === '--project') {
275
+ isProject = true;
195
276
  } else if (args[i] === '-r' || args[i] === '--random') {
196
277
  const nextArg = args[i + 1];
197
278
  if (nextArg && !isNaN(parseInt(nextArg, 10)) && !nextArg.startsWith('-')) {
@@ -218,7 +299,40 @@ function main() {
218
299
  }
219
300
  };
220
301
 
221
- if (filePath) {
302
+ if (isProject) {
303
+ const rootDir = filePath || '.';
304
+ try {
305
+ const absRoot = path.resolve(rootDir);
306
+ const files = walkProjectTree(absRoot);
307
+ const strips = stripCount || 31;
308
+ const targetWidth = strips * 2 - 1;
309
+ let clipboard = shouldCopy ? '' : null;
310
+ for (const fp of files) {
311
+ const relativePath = path.relative(absRoot, fp).replace(/\\/g, '/');
312
+ const reversedPath = relativePath.split('').reverse().join('');
313
+ const header = makeProjectHeader(reversedPath, targetWidth) + '\n';
314
+
315
+ let content;
316
+ if (isPreviewImage(fp)) {
317
+ const buf = fs.readFileSync(fp).slice(0, IMAGE_PREVIEW_BYTES);
318
+ content = virtualizeWords(buf.toString('base64'));
319
+ } else if (isBinaryExtension(fp)) {
320
+ const b64 = fs.readFileSync(fp).toString('base64');
321
+ content = virtualizeWords(b64);
322
+ } else {
323
+ content = fs.readFileSync(fp, 'utf8');
324
+ }
325
+ const payload = verticalize(content, strips, addSeparator, randomMax, false);
326
+ const entry = header + payload;
327
+ process.stdout.write(entry);
328
+ if (clipboard !== null) clipboard += entry;
329
+ }
330
+ if (clipboard) copyToClipboard(clipboard);
331
+ } catch (err) {
332
+ console.error(`Error building project: ${err.message}`);
333
+ process.exit(1);
334
+ }
335
+ } else if (filePath) {
222
336
  try {
223
337
  const data = fs.readFileSync(filePath, 'utf8');
224
338
  processResult(data);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mordorjs",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "is a toolkit for first real 1D programming language and so much more",
5
5
  "main": "mordor.js",
6
6
  "bin": {