mrmd-js 2.0.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.
Files changed (52) hide show
  1. package/README.md +842 -0
  2. package/dist/index.cjs +7613 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.js +7530 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/mrmd-js.iife.js +7618 -0
  7. package/dist/mrmd-js.iife.js.map +1 -0
  8. package/package.json +47 -0
  9. package/src/analysis/format.js +371 -0
  10. package/src/analysis/index.js +18 -0
  11. package/src/analysis/is-complete.js +394 -0
  12. package/src/constants.js +44 -0
  13. package/src/execute/css.js +205 -0
  14. package/src/execute/html.js +162 -0
  15. package/src/execute/index.js +41 -0
  16. package/src/execute/interface.js +144 -0
  17. package/src/execute/javascript.js +197 -0
  18. package/src/execute/registry.js +245 -0
  19. package/src/index.js +136 -0
  20. package/src/lsp/complete.js +353 -0
  21. package/src/lsp/format.js +310 -0
  22. package/src/lsp/hover.js +126 -0
  23. package/src/lsp/index.js +55 -0
  24. package/src/lsp/inspect.js +466 -0
  25. package/src/lsp/parse.js +455 -0
  26. package/src/lsp/variables.js +283 -0
  27. package/src/runtime.js +518 -0
  28. package/src/session/console-capture.js +181 -0
  29. package/src/session/context/iframe.js +407 -0
  30. package/src/session/context/index.js +12 -0
  31. package/src/session/context/interface.js +38 -0
  32. package/src/session/context/main.js +357 -0
  33. package/src/session/index.js +16 -0
  34. package/src/session/manager.js +327 -0
  35. package/src/session/session.js +678 -0
  36. package/src/transform/async.js +133 -0
  37. package/src/transform/extract.js +251 -0
  38. package/src/transform/index.js +10 -0
  39. package/src/transform/persistence.js +176 -0
  40. package/src/types/analysis.js +24 -0
  41. package/src/types/capabilities.js +44 -0
  42. package/src/types/completion.js +47 -0
  43. package/src/types/execution.js +62 -0
  44. package/src/types/index.js +16 -0
  45. package/src/types/inspection.js +39 -0
  46. package/src/types/session.js +32 -0
  47. package/src/types/streaming.js +74 -0
  48. package/src/types/variables.js +54 -0
  49. package/src/utils/ansi-renderer.js +301 -0
  50. package/src/utils/css-applicator.js +149 -0
  51. package/src/utils/html-renderer.js +355 -0
  52. package/src/utils/index.js +25 -0
@@ -0,0 +1,245 @@
1
+ /**
2
+ * Executor Registry
3
+ *
4
+ * Manages language executors and routes execution requests
5
+ * to the appropriate executor based on language.
6
+ *
7
+ * @module execute/registry
8
+ */
9
+
10
+ /**
11
+ * @typedef {import('./interface.js').Executor} Executor
12
+ * @typedef {import('../session/context/interface.js').ExecutionContext} ExecutionContext
13
+ * @typedef {import('../types/execution.js').ExecuteOptions} ExecuteOptions
14
+ * @typedef {import('../types/execution.js').ExecutionResult} ExecutionResult
15
+ * @typedef {import('../types/streaming.js').StreamEvent} StreamEvent
16
+ */
17
+
18
+ /**
19
+ * Registry for language executors
20
+ */
21
+ export class ExecutorRegistry {
22
+ /** @type {Map<string, Executor>} */
23
+ #executors = new Map();
24
+
25
+ /** @type {Map<string, string>} */
26
+ #aliases = new Map();
27
+
28
+ /**
29
+ * Register an executor for one or more languages
30
+ * @param {Executor} executor - The executor to register
31
+ */
32
+ register(executor) {
33
+ for (const language of executor.languages) {
34
+ const lang = language.toLowerCase();
35
+ this.#executors.set(lang, executor);
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Register a single language with an executor
41
+ * @param {string} language - Language identifier
42
+ * @param {Executor} executor - The executor
43
+ */
44
+ registerLanguage(language, executor) {
45
+ this.#executors.set(language.toLowerCase(), executor);
46
+ }
47
+
48
+ /**
49
+ * Register an alias for a language
50
+ * @param {string} alias - The alias
51
+ * @param {string} language - The target language
52
+ */
53
+ registerAlias(alias, language) {
54
+ this.#aliases.set(alias.toLowerCase(), language.toLowerCase());
55
+ }
56
+
57
+ /**
58
+ * Get the executor for a language
59
+ * @param {string} language
60
+ * @returns {Executor | undefined}
61
+ */
62
+ get(language) {
63
+ const lang = language.toLowerCase();
64
+
65
+ // Check direct registration
66
+ let executor = this.#executors.get(lang);
67
+ if (executor) return executor;
68
+
69
+ // Check aliases
70
+ const aliasTarget = this.#aliases.get(lang);
71
+ if (aliasTarget) {
72
+ return this.#executors.get(aliasTarget);
73
+ }
74
+
75
+ return undefined;
76
+ }
77
+
78
+ /**
79
+ * Check if a language is supported
80
+ * @param {string} language
81
+ * @returns {boolean}
82
+ */
83
+ supports(language) {
84
+ return this.get(language) !== undefined;
85
+ }
86
+
87
+ /**
88
+ * Get all registered languages
89
+ * @returns {string[]}
90
+ */
91
+ languages() {
92
+ const langs = new Set([...this.#executors.keys(), ...this.#aliases.keys()]);
93
+ return Array.from(langs).sort();
94
+ }
95
+
96
+ /**
97
+ * Get all registered executors (deduplicated)
98
+ * @returns {Executor[]}
99
+ */
100
+ executors() {
101
+ return Array.from(new Set(this.#executors.values()));
102
+ }
103
+
104
+ /**
105
+ * Execute code using the appropriate executor
106
+ * @param {string} code - Code to execute
107
+ * @param {string} language - Language identifier
108
+ * @param {ExecutionContext} context - Execution context
109
+ * @param {ExecuteOptions} [options] - Execution options
110
+ * @returns {Promise<ExecutionResult>}
111
+ */
112
+ async execute(code, language, context, options = {}) {
113
+ const executor = this.get(language);
114
+
115
+ if (!executor) {
116
+ return {
117
+ success: false,
118
+ stdout: '',
119
+ stderr: `No executor registered for language: ${language}`,
120
+ error: {
121
+ type: 'ExecutorError',
122
+ message: `No executor registered for language: ${language}`,
123
+ },
124
+ displayData: [],
125
+ assets: [],
126
+ executionCount: 0,
127
+ duration: 0,
128
+ };
129
+ }
130
+
131
+ return executor.execute(code, context, options);
132
+ }
133
+
134
+ /**
135
+ * Execute code with streaming using the appropriate executor
136
+ * @param {string} code - Code to execute
137
+ * @param {string} language - Language identifier
138
+ * @param {ExecutionContext} context - Execution context
139
+ * @param {ExecuteOptions} [options] - Execution options
140
+ * @returns {AsyncGenerator<StreamEvent>}
141
+ */
142
+ async *executeStream(code, language, context, options = {}) {
143
+ const executor = this.get(language);
144
+
145
+ if (!executor) {
146
+ yield /** @type {import('../types/streaming.js').ErrorEvent} */ ({
147
+ type: 'error',
148
+ error: {
149
+ type: 'ExecutorError',
150
+ message: `No executor registered for language: ${language}`,
151
+ },
152
+ });
153
+ yield /** @type {import('../types/streaming.js').DoneEvent} */ ({
154
+ type: 'done',
155
+ });
156
+ return;
157
+ }
158
+
159
+ if (executor.executeStream) {
160
+ yield* executor.executeStream(code, context, options);
161
+ } else {
162
+ // Fall back to non-streaming execution wrapped in events
163
+ const execId = options.execId || `exec-${Date.now()}`;
164
+
165
+ yield /** @type {import('../types/streaming.js').StartEvent} */ ({
166
+ type: 'start',
167
+ execId,
168
+ timestamp: new Date().toISOString(),
169
+ });
170
+
171
+ try {
172
+ const result = await executor.execute(code, context, options);
173
+
174
+ if (result.stdout) {
175
+ yield /** @type {import('../types/streaming.js').StdoutEvent} */ ({
176
+ type: 'stdout',
177
+ content: result.stdout,
178
+ accumulated: result.stdout,
179
+ });
180
+ }
181
+
182
+ if (result.stderr) {
183
+ yield /** @type {import('../types/streaming.js').StderrEvent} */ ({
184
+ type: 'stderr',
185
+ content: result.stderr,
186
+ accumulated: result.stderr,
187
+ });
188
+ }
189
+
190
+ for (const display of result.displayData) {
191
+ yield /** @type {import('../types/streaming.js').DisplayEvent} */ ({
192
+ type: 'display',
193
+ data: display.data,
194
+ metadata: display.metadata,
195
+ });
196
+ }
197
+
198
+ yield /** @type {import('../types/streaming.js').ResultEvent} */ ({
199
+ type: 'result',
200
+ result,
201
+ });
202
+ } catch (error) {
203
+ yield /** @type {import('../types/streaming.js').ErrorEvent} */ ({
204
+ type: 'error',
205
+ error: {
206
+ type: error instanceof Error ? error.name : 'Error',
207
+ message: error instanceof Error ? error.message : String(error),
208
+ },
209
+ });
210
+ }
211
+
212
+ yield /** @type {import('../types/streaming.js').DoneEvent} */ ({
213
+ type: 'done',
214
+ });
215
+ }
216
+ }
217
+
218
+ /**
219
+ * Unregister a language
220
+ * @param {string} language
221
+ * @returns {boolean}
222
+ */
223
+ unregister(language) {
224
+ const lang = language.toLowerCase();
225
+ const hadExecutor = this.#executors.delete(lang);
226
+ const hadAlias = this.#aliases.delete(lang);
227
+ return hadExecutor || hadAlias;
228
+ }
229
+
230
+ /**
231
+ * Clear all registered executors
232
+ */
233
+ clear() {
234
+ this.#executors.clear();
235
+ this.#aliases.clear();
236
+ }
237
+ }
238
+
239
+ /**
240
+ * Create an executor registry
241
+ * @returns {ExecutorRegistry}
242
+ */
243
+ export function createExecutorRegistry() {
244
+ return new ExecutorRegistry();
245
+ }
package/src/index.js ADDED
@@ -0,0 +1,136 @@
1
+ /**
2
+ * mrmd-js
3
+ *
4
+ * MRP-compliant browser JavaScript runtime.
5
+ *
6
+ * @example
7
+ * import { MrpRuntime } from 'mrmd-js';
8
+ *
9
+ * const runtime = new MrpRuntime();
10
+ * const session = runtime.createSession({ language: 'javascript' });
11
+ * const result = await session.execute('const x = 1 + 2; x');
12
+ *
13
+ * @module mrmd-js
14
+ */
15
+
16
+ // Types (JSDoc only, re-exported for documentation)
17
+ export * from './types/index.js';
18
+
19
+ // Constants
20
+ export * from './constants.js';
21
+
22
+ // Session Management (Phase 2)
23
+ export {
24
+ Session,
25
+ createSession,
26
+ SessionManager,
27
+ createSessionManager,
28
+ } from './session/index.js';
29
+
30
+ // Context Infrastructure (Phase 1)
31
+ export {
32
+ ConsoleCapture,
33
+ createConsoleCapture,
34
+ IframeContext,
35
+ createIframeContext,
36
+ MainContext,
37
+ createMainContext,
38
+ } from './session/index.js';
39
+
40
+ // Transforms
41
+ export {
42
+ transformForPersistence,
43
+ wrapForAsync,
44
+ wrapWithLastExpression,
45
+ extractDeclaredVariables,
46
+ } from './transform/index.js';
47
+
48
+ // Executors (Phase 3)
49
+ export {
50
+ // Base
51
+ BaseExecutor,
52
+ // Registry
53
+ ExecutorRegistry,
54
+ createExecutorRegistry,
55
+ createDefaultExecutorRegistry,
56
+ // JavaScript
57
+ JavaScriptExecutor,
58
+ createJavaScriptExecutor,
59
+ // HTML
60
+ HtmlExecutor,
61
+ createHtmlExecutor,
62
+ extractScripts,
63
+ extractStyles,
64
+ // CSS
65
+ CssExecutor,
66
+ createCssExecutor,
67
+ scopeStyles,
68
+ generateScopeClass,
69
+ } from './execute/index.js';
70
+
71
+ // LSP Features (Phase 4)
72
+ export {
73
+ // Parsing utilities
74
+ parseIdentifierAtPosition,
75
+ parseCompletionContext,
76
+ getStringOrCommentContext,
77
+ getWordAtCursor,
78
+ splitObjectPath,
79
+ isIdentifierStart,
80
+ isIdentifierPart,
81
+ isKeyword,
82
+ getKeywords,
83
+ getCommonGlobals,
84
+ // Formatting utilities
85
+ formatValue,
86
+ formatValueShort,
87
+ getTypeName,
88
+ getCompletionKind,
89
+ isExpandable,
90
+ getFunctionSignature,
91
+ getFunctionSource,
92
+ getSizeDescription,
93
+ // Completions
94
+ getCompletions,
95
+ // Hover
96
+ getHoverInfo,
97
+ // Inspection
98
+ getInspectInfo,
99
+ inspectPath,
100
+ // Variables
101
+ listVariables,
102
+ getVariableDetail,
103
+ expandVariable,
104
+ formatVariableInfo,
105
+ getChildren,
106
+ getMethods,
107
+ getAttributes,
108
+ } from './lsp/index.js';
109
+
110
+ // Analysis Features (Phase 5)
111
+ export {
112
+ isComplete,
113
+ getSuggestedIndent,
114
+ formatCode,
115
+ basicFormat,
116
+ formatHtml,
117
+ formatCss,
118
+ setPrettier,
119
+ hasPrettier,
120
+ } from './analysis/index.js';
121
+
122
+ // MRP Runtime (Phase 6)
123
+ export { MrpRuntime, createRuntime } from './runtime.js';
124
+
125
+ // Client Utilities (Phase 7)
126
+ export {
127
+ HtmlRenderer,
128
+ createHtmlRenderer,
129
+ scopeStyles as scopeStylesUtil,
130
+ CssApplicator,
131
+ createCssApplicator,
132
+ AnsiRenderer,
133
+ ansiToHtml,
134
+ stripAnsi,
135
+ createAnsiRenderer,
136
+ } from './utils/index.js';