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.
- package/README.md +842 -0
- package/dist/index.cjs +7613 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +7530 -0
- package/dist/index.js.map +1 -0
- package/dist/mrmd-js.iife.js +7618 -0
- package/dist/mrmd-js.iife.js.map +1 -0
- package/package.json +47 -0
- package/src/analysis/format.js +371 -0
- package/src/analysis/index.js +18 -0
- package/src/analysis/is-complete.js +394 -0
- package/src/constants.js +44 -0
- package/src/execute/css.js +205 -0
- package/src/execute/html.js +162 -0
- package/src/execute/index.js +41 -0
- package/src/execute/interface.js +144 -0
- package/src/execute/javascript.js +197 -0
- package/src/execute/registry.js +245 -0
- package/src/index.js +136 -0
- package/src/lsp/complete.js +353 -0
- package/src/lsp/format.js +310 -0
- package/src/lsp/hover.js +126 -0
- package/src/lsp/index.js +55 -0
- package/src/lsp/inspect.js +466 -0
- package/src/lsp/parse.js +455 -0
- package/src/lsp/variables.js +283 -0
- package/src/runtime.js +518 -0
- package/src/session/console-capture.js +181 -0
- package/src/session/context/iframe.js +407 -0
- package/src/session/context/index.js +12 -0
- package/src/session/context/interface.js +38 -0
- package/src/session/context/main.js +357 -0
- package/src/session/index.js +16 -0
- package/src/session/manager.js +327 -0
- package/src/session/session.js +678 -0
- package/src/transform/async.js +133 -0
- package/src/transform/extract.js +251 -0
- package/src/transform/index.js +10 -0
- package/src/transform/persistence.js +176 -0
- package/src/types/analysis.js +24 -0
- package/src/types/capabilities.js +44 -0
- package/src/types/completion.js +47 -0
- package/src/types/execution.js +62 -0
- package/src/types/index.js +16 -0
- package/src/types/inspection.js +39 -0
- package/src/types/session.js +32 -0
- package/src/types/streaming.js +74 -0
- package/src/types/variables.js +54 -0
- package/src/utils/ansi-renderer.js +301 -0
- package/src/utils/css-applicator.js +149 -0
- package/src/utils/html-renderer.js +355 -0
- 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';
|