purus 0.7.0 → 0.8.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/README-ja.md CHANGED
@@ -45,6 +45,7 @@ npm install -D purus
45
45
 
46
46
  ## ツール
47
47
 
48
+ - **Core** — [`purus`](https://www.npmjs.com/package/purus): Purusのコアシステム
48
49
  - **VS Code 拡張機能** — [Marketplace](https://marketplace.visualstudio.com/items?itemName=otoneko1102.purus): シンタックスハイライト、スニペット、ファイルアイコン
49
50
  - **リンター** — [`@puruslang/linter`](https://www.npmjs.com/package/@puruslang/linter): Purus の静的解析
50
51
  - **Prettier プラグイン** — [`@puruslang/prettier-plugin-purus`](https://www.npmjs.com/package/@puruslang/prettier-plugin-purus): コードフォーマッター
package/README.md CHANGED
@@ -45,6 +45,7 @@ npm install -D purus
45
45
 
46
46
  ## Tooling
47
47
 
48
+ - **Core** — [`purus`](https://www.npmjs.com/package/purus): The core-system of Purus
48
49
  - **VS Code Extension** — [Marketplace](https://marketplace.visualstudio.com/items?itemName=otoneko1102.purus): Syntax highlighting, snippets, file icons
49
50
  - **Linter** — [`@puruslang/linter`](https://www.npmjs.com/package/@puruslang/linter): Static analysis for Purus
50
51
  - **Prettier Plugin** — [`@puruslang/prettier-plugin-purus`](https://www.npmjs.com/package/@puruslang/prettier-plugin-purus): Code formatting
package/bin/purus.js CHANGED
@@ -16,6 +16,7 @@ function printHelp() {
16
16
  console.log(" .cpurus -> .cjs (CommonJS)");
17
17
  console.log(" .mpurus -> .mjs (ES Module)");
18
18
  console.log(" purus build --no-header [file] Compile without header comment");
19
+ console.log(" purus build --type <type> Set module type (module|commonjs)");
19
20
  console.log(" purus run [file|dir] Run without generating files");
20
21
  console.log(" purus run --entry <file|dir> Run entry file or directory");
21
22
  console.log(" purus run Run using config.purus");
package/index.d.ts ADDED
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Options for the Purus compiler.
3
+ */
4
+ export interface CompileOptions {
5
+ /**
6
+ * Include "Generated by Purus" header comment in the output.
7
+ * @default true
8
+ */
9
+ header?: boolean;
10
+ /**
11
+ * Enable strict mode (`"use strict";` at the top of the output).
12
+ * @default true
13
+ */
14
+ strict?: boolean;
15
+ /**
16
+ * Output module format.
17
+ * - `"module"` — ES Modules (default)
18
+ * - `"commonjs"` — CommonJS (`require` / `module.exports`)
19
+ * @default "module"
20
+ */
21
+ type?: "module" | "commonjs";
22
+ }
23
+
24
+ /**
25
+ * Compile Purus source code to JavaScript.
26
+ *
27
+ * @param source - Purus source code
28
+ * @param options - Compilation options
29
+ * @returns Generated JavaScript code
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * import { compile } from "purus";
34
+ * const js = compile('const x be 42');
35
+ * ```
36
+ */
37
+ export declare function compile(source: string, options?: CompileOptions): string;
38
+
39
+ /**
40
+ * Check Purus source code for syntax errors.
41
+ *
42
+ * @param source - Purus source code
43
+ * @returns `true` if the syntax is valid
44
+ * @throws {Error} If the source contains syntax errors
45
+ *
46
+ * @example
47
+ * ```ts
48
+ * import { check } from "purus";
49
+ * check('const x be 42'); // true
50
+ * ```
51
+ */
52
+ export declare function check(source: string): true;
53
+
54
+ /**
55
+ * The Purus compiler version.
56
+ */
57
+ export declare const version: string;
58
+
59
+ declare const purus: {
60
+ compile: typeof compile;
61
+ check: typeof check;
62
+ version: typeof version;
63
+ };
64
+
65
+ export default purus;
@@ -12,6 +12,7 @@ let output = null;
12
12
  let noHeader = false;
13
13
  let toStdout = false;
14
14
  let strict = null; // null = use config or default (true)
15
+ let moduleType = null; // null = resolve from config/package.json/default
15
16
 
16
17
  for (let i = 0; i < args.length; i++) {
17
18
  if (args[i] === "--no-header") {
@@ -24,6 +25,10 @@ for (let i = 0; i < args.length; i++) {
24
25
  } else {
25
26
  strict = true;
26
27
  }
28
+ } else if (args[i] === "--type" || args[i] === "-t") {
29
+ if (i + 1 < args.length) {
30
+ moduleType = args[++i];
31
+ }
27
32
  } else if (args[i] === "--entry" || args[i] === "-e") {
28
33
  entry = args[++i];
29
34
  } else if (args[i] === "--output" || args[i] === "-o") {
@@ -33,12 +38,46 @@ for (let i = 0; i < args.length; i++) {
33
38
  }
34
39
  }
35
40
 
41
+ /**
42
+ * Resolve module type for a file.
43
+ * For .cpurus → always "commonjs", .mpurus → always "module".
44
+ * For .purus → CLI --type > config.purus type > package.json type > "module" (default).
45
+ */
46
+ function resolveModuleType(filePath, cliModuleType, configResult) {
47
+ if (filePath && filePath.endsWith(".cpurus")) return "commonjs";
48
+ if (filePath && filePath.endsWith(".mpurus")) return "module";
49
+
50
+ // CLI option takes highest priority
51
+ if (cliModuleType) return cliModuleType;
52
+
53
+ // config.purus type
54
+ if (configResult && configResult.config.type) return configResult.config.type;
55
+
56
+ // package.json type
57
+ try {
58
+ const pkgPath = configResult
59
+ ? path.join(configResult.configDir, "package.json")
60
+ : path.resolve("package.json");
61
+ if (fs.existsSync(pkgPath)) {
62
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
63
+ if (pkg.type) return pkg.type;
64
+ }
65
+ } catch {
66
+ // ignore
67
+ }
68
+
69
+ // default: ESM
70
+ return "module";
71
+ }
72
+
36
73
  if (entry && fs.existsSync(entry) && fs.statSync(entry).isFile() && /\.(c|m)?purus$/.test(entry)) {
37
74
  // Single file - handle directly via compile API
38
75
  const source = fs.readFileSync(entry, "utf8");
39
76
  const useHeader = !noHeader;
40
77
  const useStrict = strict !== null ? strict : true;
41
- const js = compile(source, { header: useHeader, strict: useStrict });
78
+ const configResult = loadConfig();
79
+ const resolvedModule = resolveModuleType(entry, moduleType, configResult);
80
+ const js = compile(source, { header: useHeader, strict: useStrict, module: resolvedModule });
42
81
 
43
82
  if (toStdout) {
44
83
  process.stdout.write(js);
@@ -61,6 +100,7 @@ if (entry && fs.existsSync(entry) && fs.statSync(entry).isFile() && /\.(c|m)?pur
61
100
  let outputDir;
62
101
  let useHeader;
63
102
  let useStrict;
103
+ let configResult = null;
64
104
 
65
105
  if (entry) {
66
106
  entryDir = path.resolve(entry);
@@ -68,22 +108,22 @@ if (entry && fs.existsSync(entry) && fs.statSync(entry).isFile() && /\.(c|m)?pur
68
108
  useHeader = !noHeader;
69
109
  useStrict = strict !== null ? strict : true;
70
110
 
71
- const result = loadConfig();
72
- if (result) {
111
+ configResult = loadConfig();
112
+ if (configResult) {
73
113
  if (!output) {
74
114
  outputDir = path.resolve(
75
- result.configDir,
76
- result.config.output || "dist"
115
+ configResult.configDir,
116
+ configResult.config.output || "dist"
77
117
  );
78
118
  }
79
- useHeader = result.config.header !== false && !noHeader;
119
+ useHeader = configResult.config.header !== false && !noHeader;
80
120
  if (strict === null) {
81
- useStrict = result.config.strict !== false;
121
+ useStrict = configResult.config.strict !== false;
82
122
  }
83
123
  }
84
124
  } else {
85
- const result = loadConfig();
86
- if (!result) {
125
+ configResult = loadConfig();
126
+ if (!configResult) {
87
127
  console.log("Error: no input file specified and no config.purus found");
88
128
  console.log("");
89
129
  console.log("Usage:");
@@ -95,7 +135,7 @@ if (entry && fs.existsSync(entry) && fs.statSync(entry).isFile() && /\.(c|m)?pur
95
135
  process.exit(1);
96
136
  }
97
137
 
98
- const { config, configDir } = result;
138
+ const { config, configDir } = configResult;
99
139
  entryDir = path.resolve(configDir, config.entry || "src");
100
140
  outputDir = output
101
141
  ? path.resolve(output)
@@ -130,7 +170,8 @@ if (entry && fs.existsSync(entry) && fs.statSync(entry).isFile() && /\.(c|m)?pur
130
170
  let count = 0;
131
171
  for (const f of files) {
132
172
  const source = fs.readFileSync(f, "utf8");
133
- const js = compile(source, { header: useHeader, strict: useStrict });
173
+ const resolvedModule = resolveModuleType(f, moduleType, configResult);
174
+ const js = compile(source, { header: useHeader, strict: useStrict, module: resolvedModule });
134
175
  let outputPath;
135
176
 
136
177
  if (stat.isFile()) {
package/lib/create.js CHANGED
@@ -48,6 +48,7 @@ async function run() {
48
48
  const configPurus = `-- Purus Configuration
49
49
  const entry be ///src///
50
50
  const output be ///dist///
51
+ const type be ///module///
51
52
  const header be true
52
53
 
53
54
  -- Linter settings
@@ -135,10 +136,12 @@ node_modules/
135
136
  });
136
137
  }
137
138
 
138
- // Add scripts to package.json
139
+ // Add scripts to package.json and set main/type
139
140
  const pkgPath = path.join(projectDir, "package.json");
140
141
  if (fs.existsSync(pkgPath)) {
141
142
  const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
143
+ pkg.main = "dist/main.js";
144
+ pkg.type = "module";
142
145
  pkg.scripts = {
143
146
  ...(pkg.scripts || {}),
144
147
  purus: "purus",