@mdzip/editor-ng 1.3.0 → 1.3.8

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 CHANGED
@@ -1,3 +1,8 @@
1
+ [![MDZip logo][mdzip-logo]][mdzip-url]
2
+
3
+ [mdzip-logo]: https://raw.githubusercontent.com/mdzip-project/mdzip-editor/main/resources/mdzip-mark.svg
4
+ [mdzip-url]: https://mdzip.org
5
+
1
6
  # @mdzip/editor-ng
2
7
 
3
8
  Angular component wrapper for the MDZip workspace editor.
@@ -37,6 +42,33 @@ export class AppComponent {
37
42
 
38
43
  The host element must have an explicit height. The component expands to fill it.
39
44
 
45
+ ## Archive Diff
46
+
47
+ ```ts
48
+ import { MdzipDiffComponent } from '@mdzip/editor-ng';
49
+
50
+ @Component({
51
+ imports: [MdzipDiffComponent],
52
+ template: `
53
+ <mdzip-diff
54
+ [before]="{ bytes: baseBytes, label: 'Git base' }"
55
+ [after]="{ bytes: workingBytes, label: 'Working tree' }"
56
+ [toolbarActions]="diffActions"
57
+ initialPath="index.md"
58
+ />
59
+ `,
60
+ styles: [':host { display:block; height:600px; }']
61
+ })
62
+ export class DiffComponent {}
63
+ ```
64
+
65
+ `MdzipDiffComponent` is read-only. It emits `selectionChanged` and `failed`,
66
+ and exposes `openPath`, `openPreviousChange`, `openNextChange`,
67
+ `setShowUnchanged`, `setNavigationVisible`, and `setToolbarActions`. The
68
+ built-in toolbar adds Previous/Next change buttons and a Show-unchanged
69
+ toggle; bind a `controls` input (`{ navigation?, changeTraversal?,
70
+ showUnchanged? }`) to opt any of them out.
71
+
40
72
  ## Editor Mode
41
73
 
42
74
  ```ts
@@ -64,6 +96,39 @@ The host element must have an explicit height. The component expands to fill it.
64
96
  | `initialColorScheme` | `MdzipColorScheme` | — | `'light'` or `'dark'` |
65
97
  | `navigationMode` | `MdzipNavigationMode` | `'editor'` | Package navigation mode |
66
98
  | `navigationButtonActive` | `boolean` | `true` | Whether the navigation button is shown |
99
+ | `markdownRenderer` | `MdzipMarkdownRenderer` | — | Custom markdown renderer (keep the reference stable) |
100
+ | `markdownExtensions` | `readonly MdzipMarkdownRenderExtension[]` | `[]` | Markdown pipeline extensions, diffed by `name` — new array identities with the same names are safe |
101
+ | `entryRenderers` | `readonly MdzipEntryRenderer[]` | `[]` | Entry renderers claiming the content area for matching entries, diffed by `id` — new array identities with the same ids are safe |
102
+
103
+ Rendering input changes apply in place — they never recreate the workspace
104
+ view. See the `@mdzip/editor` Rendering Extensibility docs for the contracts
105
+ and lifecycle rules.
106
+
107
+ ### Native entry rendering (template directives)
108
+
109
+ ```html
110
+ <mdzip-workspace [bytes]="bytes" mode="editable">
111
+ <ng-template mdzipEntryRenderer="manifest.json" let-context>
112
+ <app-internals
113
+ [manifest]="context.manifest"
114
+ [editable]="context.mode === 'editable'"
115
+ (manifestChange)="context.updateManifest($event)"
116
+ />
117
+ </ng-template>
118
+
119
+ <ng-template [mdzipEntryRendererMatch]="isDrawioEntry" let-context>
120
+ <app-drawio-viewer [entry]="context" />
121
+ </ng-template>
122
+ </mdzip-workspace>
123
+ ```
124
+
125
+ Import `MdzipEntryRendererDirective` alongside the component.
126
+ `mdzipEntryRenderer` matches exact archive paths (string or array,
127
+ case-insensitive); `[mdzipEntryRendererMatch]` takes a predicate. Optional
128
+ `mdzipEntryRendererId` / `mdzipEntryRendererPriority` inputs control diffing
129
+ and ordering. Embedded views are created in the component's view container —
130
+ change detection and DI work normally — and are destroyed on selection
131
+ change.
67
132
 
68
133
  ## Outputs
69
134
 
@@ -76,6 +141,8 @@ The host element must have an explicit height. The component expands to fill it.
76
141
  | `dirtyChanged` | `MdzipWorkspaceSnapshot` | Emitted when the dirty flag changes |
77
142
  | `validationChanged` | `MdzipWorkspaceSnapshot` | Emitted when validation state changes |
78
143
  | `colorSchemeChanged` | `MdzipColorScheme` | Emitted when the color scheme changes |
144
+ | `previewRendered` | `MdzipWorkspaceSnapshot` | Emitted when the preview HTML is mounted |
145
+ | `assetsHydrated` | `MdzipWorkspaceSnapshot` | Emitted once the mounted preview's images have loaded |
79
146
  | `failed` | `unknown` | Emitted on unrecoverable errors |
80
147
 
81
148
  ## Conversion hook
@@ -94,21 +161,54 @@ rename/move, duplicate, replace, download, copy markdown link, set entry point,
94
161
  image, and delete. Files can also be dragged between folders, and OS files can be dropped
95
162
  onto the pane. Copy and Download remain available in read-only mode. The same operations are
96
163
  exposed as component methods: `removeFile`, `renameFile`, `setEntryPoint`, and `setCoverImage`.
164
+ `whenRendered()` resolves once the current preview (including its images) is mounted — useful
165
+ for revealing or animating read-only preview content.
97
166
 
98
167
  ## Imperative API
99
168
 
100
- ```ts
101
- @ViewChild(MdzipWorkspaceComponent) workspace!: MdzipWorkspaceComponent;
169
+ All imperative methods are public instance methods on `MdzipWorkspaceComponent`,
170
+ so any reference to the component instance works. No view query is required: a
171
+ template reference variable can hand the instance directly to an event handler.
102
172
 
103
- // Flush pending edits and persist
104
- const snapshot = await this.workspace.flush();
105
- if (snapshot) {
106
- await save(snapshot.bytes);
107
- this.workspace.markPersisted();
173
+ ```ts
174
+ @Component({
175
+ imports: [MdzipWorkspaceComponent],
176
+ template: `
177
+ <mdzip-workspace #workspace [bytes]="bytes" mode="editable" controls="hosted-editor" />
178
+ <button (click)="save(workspace)">Save</button>
179
+ `,
180
+ })
181
+ export class AppComponent {
182
+ async save(workspace: MdzipWorkspaceComponent): Promise<void> {
183
+ // Flush pending edits and persist
184
+ const snapshot = await workspace.flush();
185
+ if (snapshot) {
186
+ await persist(snapshot.bytes);
187
+ workspace.markPersisted();
188
+ }
189
+
190
+ // Execute editor commands
191
+ await workspace.executeCommand('bold');
192
+ }
108
193
  }
194
+ ```
195
+
196
+ To call methods outside an event handler, use a view query — the signal-based
197
+ `viewChild` or the classic `@ViewChild` decorator:
109
198
 
110
- // Execute editor commands
111
- await this.workspace.executeCommand('bold');
199
+ ```ts
200
+ private readonly workspace = viewChild.required(MdzipWorkspaceComponent);
201
+
202
+ async save(): Promise<void> {
203
+ const snapshot = await this.workspace().flush();
204
+ if (snapshot) {
205
+ await persist(snapshot.bytes);
206
+ this.workspace().markPersisted();
207
+ }
208
+ }
112
209
  ```
113
210
 
211
+ Methods called before the view initializes are safe: they no-op and resolve to
212
+ `false`/`null`/empty rather than throwing.
213
+
114
214
  See the [`@mdzip/editor`](https://www.npmjs.com/package/@mdzip/editor) package for the full API reference, theming guide, and framework-agnostic usage.
package/dist/README.md CHANGED
@@ -1,3 +1,8 @@
1
+ [![MDZip logo][mdzip-logo]][mdzip-url]
2
+
3
+ [mdzip-logo]: https://raw.githubusercontent.com/mdzip-project/mdzip-editor/main/resources/mdzip-mark.svg
4
+ [mdzip-url]: https://mdzip.org
5
+
1
6
  # @mdzip/editor-ng
2
7
 
3
8
  Angular component wrapper for the MDZip workspace editor.
@@ -37,6 +42,33 @@ export class AppComponent {
37
42
 
38
43
  The host element must have an explicit height. The component expands to fill it.
39
44
 
45
+ ## Archive Diff
46
+
47
+ ```ts
48
+ import { MdzipDiffComponent } from '@mdzip/editor-ng';
49
+
50
+ @Component({
51
+ imports: [MdzipDiffComponent],
52
+ template: `
53
+ <mdzip-diff
54
+ [before]="{ bytes: baseBytes, label: 'Git base' }"
55
+ [after]="{ bytes: workingBytes, label: 'Working tree' }"
56
+ [toolbarActions]="diffActions"
57
+ initialPath="index.md"
58
+ />
59
+ `,
60
+ styles: [':host { display:block; height:600px; }']
61
+ })
62
+ export class DiffComponent {}
63
+ ```
64
+
65
+ `MdzipDiffComponent` is read-only. It emits `selectionChanged` and `failed`,
66
+ and exposes `openPath`, `openPreviousChange`, `openNextChange`,
67
+ `setShowUnchanged`, `setNavigationVisible`, and `setToolbarActions`. The
68
+ built-in toolbar adds Previous/Next change buttons and a Show-unchanged
69
+ toggle; bind a `controls` input (`{ navigation?, changeTraversal?,
70
+ showUnchanged? }`) to opt any of them out.
71
+
40
72
  ## Editor Mode
41
73
 
42
74
  ```ts
@@ -64,6 +96,39 @@ The host element must have an explicit height. The component expands to fill it.
64
96
  | `initialColorScheme` | `MdzipColorScheme` | — | `'light'` or `'dark'` |
65
97
  | `navigationMode` | `MdzipNavigationMode` | `'editor'` | Package navigation mode |
66
98
  | `navigationButtonActive` | `boolean` | `true` | Whether the navigation button is shown |
99
+ | `markdownRenderer` | `MdzipMarkdownRenderer` | — | Custom markdown renderer (keep the reference stable) |
100
+ | `markdownExtensions` | `readonly MdzipMarkdownRenderExtension[]` | `[]` | Markdown pipeline extensions, diffed by `name` — new array identities with the same names are safe |
101
+ | `entryRenderers` | `readonly MdzipEntryRenderer[]` | `[]` | Entry renderers claiming the content area for matching entries, diffed by `id` — new array identities with the same ids are safe |
102
+
103
+ Rendering input changes apply in place — they never recreate the workspace
104
+ view. See the `@mdzip/editor` Rendering Extensibility docs for the contracts
105
+ and lifecycle rules.
106
+
107
+ ### Native entry rendering (template directives)
108
+
109
+ ```html
110
+ <mdzip-workspace [bytes]="bytes" mode="editable">
111
+ <ng-template mdzipEntryRenderer="manifest.json" let-context>
112
+ <app-internals
113
+ [manifest]="context.manifest"
114
+ [editable]="context.mode === 'editable'"
115
+ (manifestChange)="context.updateManifest($event)"
116
+ />
117
+ </ng-template>
118
+
119
+ <ng-template [mdzipEntryRendererMatch]="isDrawioEntry" let-context>
120
+ <app-drawio-viewer [entry]="context" />
121
+ </ng-template>
122
+ </mdzip-workspace>
123
+ ```
124
+
125
+ Import `MdzipEntryRendererDirective` alongside the component.
126
+ `mdzipEntryRenderer` matches exact archive paths (string or array,
127
+ case-insensitive); `[mdzipEntryRendererMatch]` takes a predicate. Optional
128
+ `mdzipEntryRendererId` / `mdzipEntryRendererPriority` inputs control diffing
129
+ and ordering. Embedded views are created in the component's view container —
130
+ change detection and DI work normally — and are destroyed on selection
131
+ change.
67
132
 
68
133
  ## Outputs
69
134
 
@@ -76,6 +141,8 @@ The host element must have an explicit height. The component expands to fill it.
76
141
  | `dirtyChanged` | `MdzipWorkspaceSnapshot` | Emitted when the dirty flag changes |
77
142
  | `validationChanged` | `MdzipWorkspaceSnapshot` | Emitted when validation state changes |
78
143
  | `colorSchemeChanged` | `MdzipColorScheme` | Emitted when the color scheme changes |
144
+ | `previewRendered` | `MdzipWorkspaceSnapshot` | Emitted when the preview HTML is mounted |
145
+ | `assetsHydrated` | `MdzipWorkspaceSnapshot` | Emitted once the mounted preview's images have loaded |
79
146
  | `failed` | `unknown` | Emitted on unrecoverable errors |
80
147
 
81
148
  ## Conversion hook
@@ -94,21 +161,54 @@ rename/move, duplicate, replace, download, copy markdown link, set entry point,
94
161
  image, and delete. Files can also be dragged between folders, and OS files can be dropped
95
162
  onto the pane. Copy and Download remain available in read-only mode. The same operations are
96
163
  exposed as component methods: `removeFile`, `renameFile`, `setEntryPoint`, and `setCoverImage`.
164
+ `whenRendered()` resolves once the current preview (including its images) is mounted — useful
165
+ for revealing or animating read-only preview content.
97
166
 
98
167
  ## Imperative API
99
168
 
100
- ```ts
101
- @ViewChild(MdzipWorkspaceComponent) workspace!: MdzipWorkspaceComponent;
169
+ All imperative methods are public instance methods on `MdzipWorkspaceComponent`,
170
+ so any reference to the component instance works. No view query is required: a
171
+ template reference variable can hand the instance directly to an event handler.
102
172
 
103
- // Flush pending edits and persist
104
- const snapshot = await this.workspace.flush();
105
- if (snapshot) {
106
- await save(snapshot.bytes);
107
- this.workspace.markPersisted();
173
+ ```ts
174
+ @Component({
175
+ imports: [MdzipWorkspaceComponent],
176
+ template: `
177
+ <mdzip-workspace #workspace [bytes]="bytes" mode="editable" controls="hosted-editor" />
178
+ <button (click)="save(workspace)">Save</button>
179
+ `,
180
+ })
181
+ export class AppComponent {
182
+ async save(workspace: MdzipWorkspaceComponent): Promise<void> {
183
+ // Flush pending edits and persist
184
+ const snapshot = await workspace.flush();
185
+ if (snapshot) {
186
+ await persist(snapshot.bytes);
187
+ workspace.markPersisted();
188
+ }
189
+
190
+ // Execute editor commands
191
+ await workspace.executeCommand('bold');
192
+ }
108
193
  }
194
+ ```
195
+
196
+ To call methods outside an event handler, use a view query — the signal-based
197
+ `viewChild` or the classic `@ViewChild` decorator:
109
198
 
110
- // Execute editor commands
111
- await this.workspace.executeCommand('bold');
199
+ ```ts
200
+ private readonly workspace = viewChild.required(MdzipWorkspaceComponent);
201
+
202
+ async save(): Promise<void> {
203
+ const snapshot = await this.workspace().flush();
204
+ if (snapshot) {
205
+ await persist(snapshot.bytes);
206
+ this.workspace().markPersisted();
207
+ }
208
+ }
112
209
  ```
113
210
 
211
+ Methods called before the view initializes are safe: they no-op and resolve to
212
+ `false`/`null`/empty rather than throwing.
213
+
114
214
  See the [`@mdzip/editor`](https://www.npmjs.com/package/@mdzip/editor) package for the full API reference, theming guide, and framework-agnostic usage.
@@ -1,7 +1,111 @@
1
1
  import * as i0 from '@angular/core';
2
- import { EventEmitter, ViewChild, Output, Input, ChangeDetectionStrategy, Component } from '@angular/core';
2
+ import { inject, TemplateRef, ViewContainerRef, Input, Directive, EventEmitter, ContentChildren, ViewChild, Output, ChangeDetectionStrategy, Component } from '@angular/core';
3
3
  import { MdzipWorkspaceView } from '@mdzip/editor';
4
4
 
5
+ /**
6
+ * Declares an entry renderer template inside `<mdzip-workspace>`:
7
+ *
8
+ * ```html
9
+ * <mdzip-workspace [bytes]="bytes" mode="editable">
10
+ * <ng-template mdzipEntryRenderer="manifest.json" let-context>
11
+ * <app-internals [manifest]="context.manifest" />
12
+ * </ng-template>
13
+ * </mdzip-workspace>
14
+ * ```
15
+ *
16
+ * Match either by exact archive path(s) via `mdzipEntryRenderer`, or with a
17
+ * predicate via `[mdzipEntryRendererMatch]`. The embedded view is created in
18
+ * the workspace component's view container (so change detection and
19
+ * dependency injection work normally), its DOM is moved into the editor's
20
+ * entry pane, and the view is destroyed when the selection changes or the
21
+ * workspace is destroyed.
22
+ */
23
+ class MdzipEntryRendererDirective {
24
+ constructor() {
25
+ this.templateRef = inject((TemplateRef));
26
+ this.viewContainerRef = inject(ViewContainerRef);
27
+ /** Exact archive path(s) to claim, case-insensitive. */
28
+ this.mdzipEntryRenderer = '';
29
+ }
30
+ /** Adapts this template onto the framework-independent renderer contract. */
31
+ toEntryRenderer(index) {
32
+ const paths = (typeof this.mdzipEntryRenderer === 'string'
33
+ ? [this.mdzipEntryRenderer]
34
+ : this.mdzipEntryRenderer).filter((path) => path.length > 0).map((path) => path.toLowerCase());
35
+ return {
36
+ id: this.mdzipEntryRendererId
37
+ ?? (paths.length > 0 ? `mdzip-ng-template:${paths.join(',')}` : `mdzip-ng-template#${index}`),
38
+ priority: this.mdzipEntryRendererPriority ?? 0,
39
+ matches: (context) => this.mdzipEntryRendererMatch
40
+ ? this.mdzipEntryRendererMatch(context)
41
+ : paths.includes(context.path.toLowerCase()),
42
+ mount: (container, context) => {
43
+ const templateContext = {
44
+ $implicit: context,
45
+ context
46
+ };
47
+ const viewRef = this.viewContainerRef.createEmbeddedView(this.templateRef, templateContext);
48
+ viewRef.detectChanges();
49
+ const movedNodes = [...viewRef.rootNodes];
50
+ for (const node of movedNodes) {
51
+ container.appendChild(node);
52
+ }
53
+ return {
54
+ update: (next) => {
55
+ templateContext.$implicit = next;
56
+ templateContext.context = next;
57
+ viewRef.markForCheck();
58
+ viewRef.detectChanges();
59
+ },
60
+ destroy: () => {
61
+ viewRef.destroy();
62
+ // The nodes were moved out of Angular's host container; make
63
+ // sure none linger if the renderer did not remove them.
64
+ for (const node of movedNodes) {
65
+ node.parentNode?.removeChild(node);
66
+ }
67
+ }
68
+ };
69
+ }
70
+ };
71
+ }
72
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: MdzipEntryRendererDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
73
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.24", type: MdzipEntryRendererDirective, isStandalone: true, selector: "ng-template[mdzipEntryRenderer], ng-template[mdzipEntryRendererMatch]", inputs: { mdzipEntryRenderer: "mdzipEntryRenderer", mdzipEntryRendererMatch: "mdzipEntryRendererMatch", mdzipEntryRendererId: "mdzipEntryRendererId", mdzipEntryRendererPriority: "mdzipEntryRendererPriority" }, ngImport: i0 }); }
74
+ }
75
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: MdzipEntryRendererDirective, decorators: [{
76
+ type: Directive,
77
+ args: [{
78
+ selector: 'ng-template[mdzipEntryRenderer], ng-template[mdzipEntryRendererMatch]',
79
+ standalone: true
80
+ }]
81
+ }], propDecorators: { mdzipEntryRenderer: [{
82
+ type: Input
83
+ }], mdzipEntryRendererMatch: [{
84
+ type: Input
85
+ }], mdzipEntryRendererId: [{
86
+ type: Input
87
+ }], mdzipEntryRendererPriority: [{
88
+ type: Input
89
+ }] } });
90
+
91
+ // Generated from package.json. Do not edit by hand.
92
+ const PACKAGE_INFO = {
93
+ "name": "@mdzip/editor-ng",
94
+ "version": "1.3.8",
95
+ "repositoryUrl": "https://github.com/mdzip-project/mdzip-editor/tree/main/packages/editor-ng",
96
+ "description": "Angular UI components for the MDZip workspace engine."
97
+ };
98
+
99
+ // Identity-insensitive key for the rendering inputs: extensions and entry
100
+ // renderers are diffed by their stable name/id (and priority), so template
101
+ // expressions that build new arrays each change-detection cycle never
102
+ // trigger an update.
103
+ function renderingConfigKey(extensions, entryRenderers) {
104
+ return JSON.stringify([
105
+ extensions.map((extension) => extension.name),
106
+ entryRenderers.map((renderer) => [renderer.id, renderer.priority ?? 0]),
107
+ ]);
108
+ }
5
109
  class MdzipWorkspaceComponent {
6
110
  constructor() {
7
111
  this.bytes = null;
@@ -11,6 +115,10 @@ class MdzipWorkspaceComponent {
11
115
  this.controls = 'viewer';
12
116
  this.navigationMode = 'editor';
13
117
  this.navigationButtonActive = true;
118
+ /** Markdown pipeline extensions, diffed by `name`. */
119
+ this.markdownExtensions = [];
120
+ /** Entry renderers, diffed by `id`/`priority`. */
121
+ this.entryRenderers = [];
14
122
  this.changed = new EventEmitter();
15
123
  this.saved = new EventEmitter();
16
124
  this.workspaceChanged = new EventEmitter();
@@ -22,8 +130,19 @@ class MdzipWorkspaceComponent {
22
130
  this.dirtyChanged = new EventEmitter();
23
131
  this.validationChanged = new EventEmitter();
24
132
  this.colorSchemeChanged = new EventEmitter();
133
+ /** Emits when the preview HTML for the current selection is mounted. */
134
+ this.previewRendered = new EventEmitter();
135
+ /** Emits once the mounted preview's images have finished loading. */
136
+ this.assetsHydrated = new EventEmitter();
25
137
  this.failed = new EventEmitter();
26
138
  this.view = null;
139
+ this.renderingKey = '';
140
+ this.entryTemplatesSub = null;
141
+ }
142
+ ngAfterContentInit() {
143
+ this.entryTemplatesSub = this.entryTemplates.changes.subscribe(() => {
144
+ this.applyRenderingOptions(false);
145
+ });
27
146
  }
28
147
  ngAfterViewInit() {
29
148
  this.createView();
@@ -41,8 +160,13 @@ class MdzipWorkspaceComponent {
41
160
  || changes['sourceFormat'] || changes['fileName'])) {
42
161
  this.syncView();
43
162
  }
163
+ if (this.view && (changes['markdownRenderer'] || changes['markdownExtensions']
164
+ || changes['entryRenderers'])) {
165
+ this.applyRenderingOptions(Boolean(changes['markdownRenderer']));
166
+ }
44
167
  }
45
168
  ngOnDestroy() {
169
+ this.entryTemplatesSub?.unsubscribe();
46
170
  this.view?.destroy();
47
171
  }
48
172
  canExecuteCommand(command) {
@@ -66,6 +190,9 @@ class MdzipWorkspaceComponent {
66
190
  getCurrentSnapshot() {
67
191
  return this.view?.getCurrentSnapshot() ?? Promise.resolve(null);
68
192
  }
193
+ whenRendered() {
194
+ return this.view?.whenRendered() ?? Promise.resolve();
195
+ }
69
196
  markPersisted() {
70
197
  this.view?.markPersisted();
71
198
  }
@@ -112,6 +239,7 @@ class MdzipWorkspaceComponent {
112
239
  createView() {
113
240
  this.view?.destroy();
114
241
  this.view = new MdzipWorkspaceView(this.hostRef.nativeElement, {
242
+ libraries: [PACKAGE_INFO],
115
243
  controls: this.controls,
116
244
  initialLayout: this.initialLayout,
117
245
  initialColorScheme: this.initialColorScheme,
@@ -128,14 +256,42 @@ class MdzipWorkspaceComponent {
128
256
  onDirtyChanged: (snapshot) => this.dirtyChanged.emit(snapshot),
129
257
  onValidationChanged: (snapshot) => this.validationChanged.emit(snapshot),
130
258
  onColorSchemeChanged: (colorScheme) => this.colorSchemeChanged.emit(colorScheme),
259
+ onPreviewRendered: (snapshot) => this.previewRendered.emit(snapshot),
260
+ onAssetsHydrated: (snapshot) => this.assetsHydrated.emit(snapshot),
131
261
  onFailed: (e) => this.failed.emit(e),
132
262
  onConversionRequested: this.onConversionRequested
133
- ? (action) => this.onConversionRequested(action)
263
+ ? (action, context) => this.onConversionRequested(action, context)
134
264
  : undefined,
265
+ markdownRenderer: this.markdownRenderer,
266
+ markdownExtensions: this.markdownExtensions,
267
+ entryRenderers: this.composedEntryRenderers(),
268
+ });
269
+ this.renderingKey = renderingConfigKey(this.markdownExtensions, this.composedEntryRenderers());
270
+ }
271
+ composedEntryRenderers() {
272
+ const templates = this.entryTemplates
273
+ ? this.entryTemplates.map((directive, index) => directive.toEntryRenderer(index))
274
+ : [];
275
+ return [...this.entryRenderers, ...templates];
276
+ }
277
+ // Applies rendering input changes in place — never a view rebuild. Arrays
278
+ // re-apply only when their name/id key changes, so template expressions
279
+ // that produce new array identities each cycle are safe.
280
+ applyRenderingOptions(rendererChanged) {
281
+ const composed = this.composedEntryRenderers();
282
+ const key = renderingConfigKey(this.markdownExtensions, composed);
283
+ if (!rendererChanged && key === this.renderingKey) {
284
+ return;
285
+ }
286
+ this.renderingKey = key;
287
+ this.view?.setRenderingOptions({
288
+ markdownRenderer: this.markdownRenderer ?? null,
289
+ markdownExtensions: this.markdownExtensions,
290
+ entryRenderers: composed,
135
291
  });
136
292
  }
137
293
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: MdzipWorkspaceComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
138
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.24", type: MdzipWorkspaceComponent, isStandalone: true, selector: "mdzip-workspace", inputs: { bytes: "bytes", workspace: "workspace", fileName: "fileName", mode: "mode", sourceFormat: "sourceFormat", controls: "controls", initialLayout: "initialLayout", initialColorScheme: "initialColorScheme", navigationMode: "navigationMode", navigationButtonActive: "navigationButtonActive", onConversionRequested: "onConversionRequested" }, outputs: { changed: "changed", saved: "saved", workspaceChanged: "workspaceChanged", documentChanged: "documentChanged", assetChanged: "assetChanged", manifestChanged: "manifestChanged", snapshotChanged: "snapshotChanged", selectionChanged: "selectionChanged", dirtyChanged: "dirtyChanged", validationChanged: "validationChanged", colorSchemeChanged: "colorSchemeChanged", failed: "failed" }, viewQueries: [{ propertyName: "hostRef", first: true, predicate: ["host"], descendants: true }], usesOnChanges: true, ngImport: i0, template: '<div #host></div>', isInline: true, styles: [":host{display:block;height:100%}div{height:100%}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
294
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.24", type: MdzipWorkspaceComponent, isStandalone: true, selector: "mdzip-workspace", inputs: { bytes: "bytes", workspace: "workspace", fileName: "fileName", mode: "mode", sourceFormat: "sourceFormat", controls: "controls", initialLayout: "initialLayout", initialColorScheme: "initialColorScheme", navigationMode: "navigationMode", navigationButtonActive: "navigationButtonActive", onConversionRequested: "onConversionRequested", markdownRenderer: "markdownRenderer", markdownExtensions: "markdownExtensions", entryRenderers: "entryRenderers" }, outputs: { changed: "changed", saved: "saved", workspaceChanged: "workspaceChanged", documentChanged: "documentChanged", assetChanged: "assetChanged", manifestChanged: "manifestChanged", snapshotChanged: "snapshotChanged", selectionChanged: "selectionChanged", dirtyChanged: "dirtyChanged", validationChanged: "validationChanged", colorSchemeChanged: "colorSchemeChanged", previewRendered: "previewRendered", assetsHydrated: "assetsHydrated", failed: "failed" }, queries: [{ propertyName: "entryTemplates", predicate: MdzipEntryRendererDirective }], viewQueries: [{ propertyName: "hostRef", first: true, predicate: ["host"], descendants: true }], usesOnChanges: true, ngImport: i0, template: '<div #host></div>', isInline: true, styles: [":host{display:block;height:100%}div{height:100%}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
139
295
  }
140
296
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: MdzipWorkspaceComponent, decorators: [{
141
297
  type: Component,
@@ -162,6 +318,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
162
318
  type: Input
163
319
  }], onConversionRequested: [{
164
320
  type: Input
321
+ }], markdownRenderer: [{
322
+ type: Input
323
+ }], markdownExtensions: [{
324
+ type: Input
325
+ }], entryRenderers: [{
326
+ type: Input
165
327
  }], changed: [{
166
328
  type: Output
167
329
  }], saved: [{
@@ -184,6 +346,112 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
184
346
  type: Output
185
347
  }], colorSchemeChanged: [{
186
348
  type: Output
349
+ }], previewRendered: [{
350
+ type: Output
351
+ }], assetsHydrated: [{
352
+ type: Output
353
+ }], failed: [{
354
+ type: Output
355
+ }], hostRef: [{
356
+ type: ViewChild,
357
+ args: ['host']
358
+ }], entryTemplates: [{
359
+ type: ContentChildren,
360
+ args: [MdzipEntryRendererDirective]
361
+ }] } });
362
+
363
+ class MdzipDiffComponent {
364
+ constructor() {
365
+ this.showUnchanged = true;
366
+ this.navigationVisible = true;
367
+ this.toolbarActions = [];
368
+ this.selectionChanged = new EventEmitter();
369
+ this.failed = new EventEmitter();
370
+ this.view = null;
371
+ this.destroyed = false;
372
+ }
373
+ ngAfterViewInit() {
374
+ void this.createView();
375
+ }
376
+ ngOnChanges(changes) {
377
+ if (!this.view)
378
+ return;
379
+ if (changes['before'] || changes['after'] || changes['initialPath']) {
380
+ void this.view.open(this.options());
381
+ }
382
+ if (changes['showUnchanged'])
383
+ this.view.setShowUnchanged(this.showUnchanged);
384
+ if (changes['navigationVisible'])
385
+ this.view.setNavigationVisible(this.navigationVisible);
386
+ if (changes['toolbarActions'])
387
+ this.view.setToolbarActions(this.toolbarActions);
388
+ }
389
+ ngOnDestroy() {
390
+ this.destroyed = true;
391
+ this.view?.destroy();
392
+ this.view = null;
393
+ }
394
+ openPath(path) {
395
+ return this.view?.openPath(path) ?? Promise.resolve(false);
396
+ }
397
+ openPreviousChange() {
398
+ return this.view?.openPreviousChange() ?? Promise.resolve(false);
399
+ }
400
+ openNextChange() {
401
+ return this.view?.openNextChange() ?? Promise.resolve(false);
402
+ }
403
+ setShowUnchanged(show) {
404
+ this.view?.setShowUnchanged(show);
405
+ }
406
+ setNavigationVisible(visible) {
407
+ this.view?.setNavigationVisible(visible);
408
+ }
409
+ setToolbarActions(actions) {
410
+ this.view?.setToolbarActions(actions);
411
+ }
412
+ async createView() {
413
+ const { MdzipDiffView } = await import('@mdzip/editor/diff-view');
414
+ if (this.destroyed)
415
+ return;
416
+ this.view = new MdzipDiffView(this.hostRef.nativeElement, this.options());
417
+ }
418
+ options() {
419
+ return {
420
+ before: this.before,
421
+ after: this.after,
422
+ initialPath: this.initialPath,
423
+ showUnchanged: this.showUnchanged,
424
+ navigationVisible: this.navigationVisible,
425
+ controls: this.controls,
426
+ toolbarActions: this.toolbarActions,
427
+ onSelectionChanged: (event) => this.selectionChanged.emit(event),
428
+ onFailed: (error) => this.failed.emit(error)
429
+ };
430
+ }
431
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: MdzipDiffComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
432
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.24", type: MdzipDiffComponent, isStandalone: true, selector: "mdzip-diff", inputs: { before: "before", after: "after", initialPath: "initialPath", showUnchanged: "showUnchanged", navigationVisible: "navigationVisible", controls: "controls", toolbarActions: "toolbarActions" }, outputs: { selectionChanged: "selectionChanged", failed: "failed" }, viewQueries: [{ propertyName: "hostRef", first: true, predicate: ["host"], descendants: true }], usesOnChanges: true, ngImport: i0, template: '<div #host></div>', isInline: true, styles: [":host{display:block;height:100%}div{height:100%}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
433
+ }
434
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: MdzipDiffComponent, decorators: [{
435
+ type: Component,
436
+ args: [{ selector: 'mdzip-diff', standalone: true, template: '<div #host></div>', changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;height:100%}div{height:100%}\n"] }]
437
+ }], propDecorators: { before: [{
438
+ type: Input,
439
+ args: [{ required: true }]
440
+ }], after: [{
441
+ type: Input,
442
+ args: [{ required: true }]
443
+ }], initialPath: [{
444
+ type: Input
445
+ }], showUnchanged: [{
446
+ type: Input
447
+ }], navigationVisible: [{
448
+ type: Input
449
+ }], controls: [{
450
+ type: Input
451
+ }], toolbarActions: [{
452
+ type: Input
453
+ }], selectionChanged: [{
454
+ type: Output
187
455
  }], failed: [{
188
456
  type: Output
189
457
  }], hostRef: [{
@@ -195,5 +463,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
195
463
  * Generated bundle index. Do not edit.
196
464
  */
197
465
 
198
- export { MdzipWorkspaceComponent };
466
+ export { MdzipDiffComponent, MdzipEntryRendererDirective, MdzipWorkspaceComponent };
199
467
  //# sourceMappingURL=mdzip-editor-ng.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"mdzip-editor-ng.mjs","sources":["../../src/workspace.component.ts","../../src/mdzip-editor-ng.ts"],"sourcesContent":["import {\n AfterViewInit,\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n EventEmitter,\n Input,\n OnChanges,\n OnDestroy,\n Output,\n SimpleChanges,\n ViewChild,\n} from '@angular/core';\nimport { MdzipWorkspaceView } from '@mdzip/editor';\nimport type {\n MdzipControlPolicy,\n MdzipControlPreset,\n MdzipColorScheme,\n MdzipConversionAction,\n MdzipEditorCommand,\n MdzipDocumentChangeEvent,\n MdzipEditorSnapshot,\n MdzipNavigationMode,\n MdzipRemoveAssetOptions,\n MdzipSourceFormat,\n MdzWorkspace,\n MdzWorkspaceAsset,\n MdzipWorkspaceChange,\n MdzipWorkspaceLayout,\n MdzipWorkspaceMode,\n MdzipWorkspaceSave,\n MdzipWorkspaceSnapshot,\n} from '@mdzip/editor';\n\n@Component({\n selector: 'mdzip-workspace',\n standalone: true,\n template: '<div #host></div>',\n styles: [':host { display: block; height: 100%; } div { height: 100%; }'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class MdzipWorkspaceComponent implements AfterViewInit, OnChanges, OnDestroy {\n @Input() bytes: Uint8Array | null = null;\n @Input() workspace: MdzWorkspace | null = null;\n @Input() fileName = 'document.mdz';\n @Input() mode: MdzipWorkspaceMode = 'read-only';\n @Input() sourceFormat?: MdzipSourceFormat;\n @Input() controls: MdzipControlPreset | MdzipControlPolicy = 'viewer';\n @Input() initialLayout?: MdzipWorkspaceLayout;\n @Input() initialColorScheme?: MdzipColorScheme;\n @Input() navigationMode: MdzipNavigationMode = 'editor';\n @Input() navigationButtonActive = true;\n /**\n * Host hook for the markdown→MDZ conversion flow. An input function (not an\n * output) because it must return/resolve `true` to suppress the built-in\n * conversion dialog.\n */\n @Input() onConversionRequested?: (action: MdzipConversionAction) => boolean | Promise<boolean>;\n @Output() readonly changed = new EventEmitter<MdzipWorkspaceChange>();\n @Output() readonly saved = new EventEmitter<MdzipWorkspaceSave>();\n @Output() readonly workspaceChanged = new EventEmitter<MdzipDocumentChangeEvent>();\n @Output() readonly documentChanged = new EventEmitter<MdzipDocumentChangeEvent>();\n @Output() readonly assetChanged = new EventEmitter<MdzipDocumentChangeEvent>();\n @Output() readonly manifestChanged = new EventEmitter<MdzipDocumentChangeEvent>();\n @Output() readonly snapshotChanged = new EventEmitter<MdzipWorkspaceSnapshot>();\n @Output() readonly selectionChanged = new EventEmitter<MdzipWorkspaceSnapshot>();\n @Output() readonly dirtyChanged = new EventEmitter<MdzipWorkspaceSnapshot>();\n @Output() readonly validationChanged = new EventEmitter<MdzipWorkspaceSnapshot>();\n @Output() readonly colorSchemeChanged = new EventEmitter<MdzipColorScheme>();\n @Output() readonly failed = new EventEmitter<unknown>();\n\n @ViewChild('host') private readonly hostRef!: ElementRef<HTMLDivElement>;\n private view: MdzipWorkspaceView | null = null;\n\n ngAfterViewInit(): void {\n this.createView();\n this.syncView();\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (this.view && (changes['controls'] || changes['initialLayout']\n || changes['initialColorScheme'] || changes['navigationMode']\n || changes['navigationButtonActive'])) {\n this.createView();\n this.syncView();\n return;\n }\n if (this.view && (changes['bytes'] || changes['workspace'] || changes['mode']\n || changes['sourceFormat'] || changes['fileName'])) {\n this.syncView();\n }\n }\n\n ngOnDestroy(): void {\n this.view?.destroy();\n }\n\n canExecuteCommand(command: MdzipEditorCommand): boolean {\n return this.view?.canExecuteCommand(command) ?? false;\n }\n\n executeCommand(command: MdzipEditorCommand, file?: File): Promise<boolean> {\n return this.view?.executeCommand(command, file) ?? Promise.resolve(false);\n }\n\n convertToMdz(): Promise<boolean> {\n return this.view?.convertToMdz() ?? Promise.resolve(false);\n }\n\n focus(): void {\n this.view?.focus();\n }\n\n flush(): Promise<MdzipEditorSnapshot | null> {\n return this.view?.flush() ?? Promise.resolve(null);\n }\n\n serialize(): Promise<Blob | null> {\n return this.view?.serialize() ?? Promise.resolve(null);\n }\n\n getCurrentSnapshot(): Promise<MdzipEditorSnapshot | null> {\n return this.view?.getCurrentSnapshot() ?? Promise.resolve(null);\n }\n\n markPersisted(): void {\n this.view?.markPersisted();\n }\n\n addAsset(archivePath: string, fileBytes: Uint8Array): Promise<void> {\n return this.view?.addAsset(archivePath, fileBytes) ?? Promise.resolve();\n }\n\n replaceAsset(archivePath: string, fileBytes: Uint8Array): Promise<boolean> {\n return this.view?.replaceAsset(archivePath, fileBytes) ?? Promise.resolve(false);\n }\n\n removeAsset(archivePath: string, options?: MdzipRemoveAssetOptions): Promise<boolean> {\n return this.view?.removeAsset(archivePath, options) ?? Promise.resolve(false);\n }\n\n removeFile(archivePath: string): Promise<boolean> {\n return this.view?.removeFile(archivePath) ?? Promise.resolve(false);\n }\n\n renameFile(oldPath: string, newPath: string): Promise<boolean> {\n return this.view?.renameFile(oldPath, newPath) ?? Promise.resolve(false);\n }\n\n setEntryPoint(archivePath: string): Promise<boolean> {\n return this.view?.setEntryPoint(archivePath) ?? Promise.resolve(false);\n }\n\n setCoverImage(archivePath: string | null): Promise<boolean> {\n return this.view?.setCoverImage(archivePath) ?? Promise.resolve(false);\n }\n\n listAssets(): MdzWorkspaceAsset[] {\n return this.view?.listAssets() ?? [];\n }\n\n private syncView(): void {\n if (this.view && this.workspace) {\n void this.view.openWorkspace(this.workspace, {\n mode: this.mode,\n sourceFormat: this.sourceFormat,\n fileName: this.fileName\n });\n } else if (this.view && this.bytes) {\n void this.view.open(this.bytes, {\n mode: this.mode,\n sourceFormat: this.sourceFormat,\n fileName: this.fileName\n });\n }\n }\n\n private createView(): void {\n this.view?.destroy();\n this.view = new MdzipWorkspaceView(this.hostRef.nativeElement, {\n controls: this.controls,\n initialLayout: this.initialLayout,\n initialColorScheme: this.initialColorScheme,\n navigationMode: this.navigationMode,\n navigationButtonActive: this.navigationButtonActive,\n onChanged: (bytes, snapshot) => this.changed.emit({ bytes, snapshot }),\n onSaved: (bytes, snapshot) => this.saved.emit({ bytes, snapshot }),\n onWorkspaceChanged: (event) => this.workspaceChanged.emit(event),\n onDocumentChanged: (event) => this.documentChanged.emit(event),\n onAssetChanged: (event) => this.assetChanged.emit(event),\n onManifestChanged: (event) => this.manifestChanged.emit(event),\n onSnapshotChanged: (snapshot) => this.snapshotChanged.emit(snapshot),\n onSelectionChanged: (snapshot: MdzipWorkspaceSnapshot) => this.selectionChanged.emit(snapshot),\n onDirtyChanged: (snapshot: MdzipWorkspaceSnapshot) => this.dirtyChanged.emit(snapshot),\n onValidationChanged: (snapshot: MdzipWorkspaceSnapshot) => this.validationChanged.emit(snapshot),\n onColorSchemeChanged: (colorScheme: MdzipColorScheme) => this.colorSchemeChanged.emit(colorScheme),\n onFailed: (e: unknown) => this.failed.emit(e),\n onConversionRequested: this.onConversionRequested\n ? (action) => this.onConversionRequested!(action)\n : undefined,\n });\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;MAyCa,uBAAuB,CAAA;AAPpC,IAAA,WAAA,GAAA;QAQW,IAAA,CAAA,KAAK,GAAsB,IAAI;QAC/B,IAAA,CAAA,SAAS,GAAwB,IAAI;QACrC,IAAA,CAAA,QAAQ,GAAG,cAAc;QACzB,IAAA,CAAA,IAAI,GAAuB,WAAW;QAEtC,IAAA,CAAA,QAAQ,GAA4C,QAAQ;QAG5D,IAAA,CAAA,cAAc,GAAwB,QAAQ;QAC9C,IAAA,CAAA,sBAAsB,GAAG,IAAI;AAOnB,QAAA,IAAA,CAAA,OAAO,GAAG,IAAI,YAAY,EAAwB;AAClD,QAAA,IAAA,CAAA,KAAK,GAAG,IAAI,YAAY,EAAsB;AAC9C,QAAA,IAAA,CAAA,gBAAgB,GAAG,IAAI,YAAY,EAA4B;AAC/D,QAAA,IAAA,CAAA,eAAe,GAAG,IAAI,YAAY,EAA4B;AAC9D,QAAA,IAAA,CAAA,YAAY,GAAG,IAAI,YAAY,EAA4B;AAC3D,QAAA,IAAA,CAAA,eAAe,GAAG,IAAI,YAAY,EAA4B;AAC9D,QAAA,IAAA,CAAA,eAAe,GAAG,IAAI,YAAY,EAA0B;AAC5D,QAAA,IAAA,CAAA,gBAAgB,GAAG,IAAI,YAAY,EAA0B;AAC7D,QAAA,IAAA,CAAA,YAAY,GAAG,IAAI,YAAY,EAA0B;AACzD,QAAA,IAAA,CAAA,iBAAiB,GAAG,IAAI,YAAY,EAA0B;AAC9D,QAAA,IAAA,CAAA,kBAAkB,GAAG,IAAI,YAAY,EAAoB;AACzD,QAAA,IAAA,CAAA,MAAM,GAAG,IAAI,YAAY,EAAW;QAG/C,IAAA,CAAA,IAAI,GAA8B,IAAI;AAkI/C,IAAA;IAhIC,eAAe,GAAA;QACb,IAAI,CAAC,UAAU,EAAE;QACjB,IAAI,CAAC,QAAQ,EAAE;IACjB;AAEA,IAAA,WAAW,CAAC,OAAsB,EAAA;AAChC,QAAA,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,UAAU,CAAC,IAAI,OAAO,CAAC,eAAe;AAC3D,eAAA,OAAO,CAAC,oBAAoB,CAAC,IAAI,OAAO,CAAC,gBAAgB;AACzD,eAAA,OAAO,CAAC,wBAAwB,CAAC,CAAC,EAAE;YACvC,IAAI,CAAC,UAAU,EAAE;YACjB,IAAI,CAAC,QAAQ,EAAE;YACf;QACF;AACA,QAAA,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,MAAM;eACvE,OAAO,CAAC,cAAc,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC,EAAE;YACpD,IAAI,CAAC,QAAQ,EAAE;QACjB;IACF;IAEA,WAAW,GAAA;AACT,QAAA,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE;IACtB;AAEA,IAAA,iBAAiB,CAAC,OAA2B,EAAA;QAC3C,OAAO,IAAI,CAAC,IAAI,EAAE,iBAAiB,CAAC,OAAO,CAAC,IAAI,KAAK;IACvD;IAEA,cAAc,CAAC,OAA2B,EAAE,IAAW,EAAA;AACrD,QAAA,OAAO,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC;IAC3E;IAEA,YAAY,GAAA;AACV,QAAA,OAAO,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC;IAC5D;IAEA,KAAK,GAAA;AACH,QAAA,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;IACpB;IAEA,KAAK,GAAA;AACH,QAAA,OAAO,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;IACpD;IAEA,SAAS,GAAA;AACP,QAAA,OAAO,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;IACxD;IAEA,kBAAkB,GAAA;AAChB,QAAA,OAAO,IAAI,CAAC,IAAI,EAAE,kBAAkB,EAAE,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;IACjE;IAEA,aAAa,GAAA;AACX,QAAA,IAAI,CAAC,IAAI,EAAE,aAAa,EAAE;IAC5B;IAEA,QAAQ,CAAC,WAAmB,EAAE,SAAqB,EAAA;AACjD,QAAA,OAAO,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,WAAW,EAAE,SAAS,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE;IACzE;IAEA,YAAY,CAAC,WAAmB,EAAE,SAAqB,EAAA;AACrD,QAAA,OAAO,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,WAAW,EAAE,SAAS,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC;IAClF;IAEA,WAAW,CAAC,WAAmB,EAAE,OAAiC,EAAA;AAChE,QAAA,OAAO,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,WAAW,EAAE,OAAO,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC;IAC/E;AAEA,IAAA,UAAU,CAAC,WAAmB,EAAA;AAC5B,QAAA,OAAO,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC;IACrE;IAEA,UAAU,CAAC,OAAe,EAAE,OAAe,EAAA;AACzC,QAAA,OAAO,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC;IAC1E;AAEA,IAAA,aAAa,CAAC,WAAmB,EAAA;AAC/B,QAAA,OAAO,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC;IACxE;AAEA,IAAA,aAAa,CAAC,WAA0B,EAAA;AACtC,QAAA,OAAO,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC;IACxE;IAEA,UAAU,GAAA;QACR,OAAO,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE;IACtC;IAEQ,QAAQ,GAAA;QACd,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS,EAAE;YAC/B,KAAK,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,SAAS,EAAE;gBAC3C,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,YAAY,EAAE,IAAI,CAAC,YAAY;gBAC/B,QAAQ,EAAE,IAAI,CAAC;AAChB,aAAA,CAAC;QACJ;aAAO,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE;YAClC,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE;gBAC9B,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,YAAY,EAAE,IAAI,CAAC,YAAY;gBAC/B,QAAQ,EAAE,IAAI,CAAC;AAChB,aAAA,CAAC;QACJ;IACF;IAEQ,UAAU,GAAA;AAChB,QAAA,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE;QACpB,IAAI,CAAC,IAAI,GAAG,IAAI,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE;YAC7D,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;YAC3C,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,sBAAsB,EAAE,IAAI,CAAC,sBAAsB;AACnD,YAAA,SAAS,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AACtE,YAAA,OAAO,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AAClE,YAAA,kBAAkB,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC;AAChE,YAAA,iBAAiB,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC;AAC9D,YAAA,cAAc,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC;AACxD,YAAA,iBAAiB,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC;AAC9D,YAAA,iBAAiB,EAAE,CAAC,QAAQ,KAAK,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC;AACpE,YAAA,kBAAkB,EAAE,CAAC,QAAgC,KAAK,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC;AAC9F,YAAA,cAAc,EAAE,CAAC,QAAgC,KAAK,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC;AACtF,YAAA,mBAAmB,EAAE,CAAC,QAAgC,KAAK,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC;AAChG,YAAA,oBAAoB,EAAE,CAAC,WAA6B,KAAK,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,WAAW,CAAC;AAClG,YAAA,QAAQ,EAAE,CAAC,CAAU,KAAK,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;YAC7C,qBAAqB,EAAE,IAAI,CAAC;kBACxB,CAAC,MAAM,KAAK,IAAI,CAAC,qBAAsB,CAAC,MAAM;AAChD,kBAAE,SAAS;AACd,SAAA,CAAC;IACJ;+GAhKW,uBAAuB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAAvB,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,uBAAuB,o6BAJxB,mBAAmB,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,oDAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA,CAAA;;4FAIlB,uBAAuB,EAAA,UAAA,EAAA,CAAA;kBAPnC,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,iBAAiB,cACf,IAAI,EAAA,QAAA,EACN,mBAAmB,EAAA,eAAA,EAEZ,uBAAuB,CAAC,MAAM,EAAA,MAAA,EAAA,CAAA,oDAAA,CAAA,EAAA;;sBAG9C;;sBACA;;sBACA;;sBACA;;sBACA;;sBACA;;sBACA;;sBACA;;sBACA;;sBACA;;sBAMA;;sBACA;;sBACA;;sBACA;;sBACA;;sBACA;;sBACA;;sBACA;;sBACA;;sBACA;;sBACA;;sBACA;;sBACA;;sBAEA,SAAS;uBAAC,MAAM;;;ACvEnB;;AAEG;;;;"}
1
+ {"version":3,"file":"mdzip-editor-ng.mjs","sources":["../../src/entry-renderer.directive.ts","../../src/package-info.ts","../../src/workspace.component.ts","../../src/diff.component.ts","../../src/mdzip-editor-ng.ts"],"sourcesContent":["import { Directive, Input, TemplateRef, ViewContainerRef, inject } from '@angular/core';\nimport type { MdzipEntryRenderContext, MdzipEntryRenderer } from '@mdzip/editor';\n\n/** Template context available via `let-context` (also the `$implicit` value). */\nexport interface MdzipEntryRendererTemplateContext {\n $implicit: MdzipEntryRenderContext;\n context: MdzipEntryRenderContext;\n}\n\n/**\n * Declares an entry renderer template inside `<mdzip-workspace>`:\n *\n * ```html\n * <mdzip-workspace [bytes]=\"bytes\" mode=\"editable\">\n * <ng-template mdzipEntryRenderer=\"manifest.json\" let-context>\n * <app-internals [manifest]=\"context.manifest\" />\n * </ng-template>\n * </mdzip-workspace>\n * ```\n *\n * Match either by exact archive path(s) via `mdzipEntryRenderer`, or with a\n * predicate via `[mdzipEntryRendererMatch]`. The embedded view is created in\n * the workspace component's view container (so change detection and\n * dependency injection work normally), its DOM is moved into the editor's\n * entry pane, and the view is destroyed when the selection changes or the\n * workspace is destroyed.\n */\n@Directive({\n selector: 'ng-template[mdzipEntryRenderer], ng-template[mdzipEntryRendererMatch]',\n standalone: true\n})\nexport class MdzipEntryRendererDirective {\n readonly templateRef = inject(TemplateRef<MdzipEntryRendererTemplateContext>);\n private readonly viewContainerRef = inject(ViewContainerRef);\n\n /** Exact archive path(s) to claim, case-insensitive. */\n @Input() mdzipEntryRenderer: string | readonly string[] = '';\n /** Predicate alternative for extension/MIME/path-family matching. */\n @Input() mdzipEntryRendererMatch?: (context: MdzipEntryRenderContext) => boolean;\n /** Stable id used for renderer diffing. Defaults to the matched paths. */\n @Input() mdzipEntryRendererId?: string;\n /** Matching priority relative to the `entryRenderers` input. Default 0. */\n @Input() mdzipEntryRendererPriority?: number;\n\n /** Adapts this template onto the framework-independent renderer contract. */\n toEntryRenderer(index: number): MdzipEntryRenderer {\n const paths = (typeof this.mdzipEntryRenderer === 'string'\n ? [this.mdzipEntryRenderer]\n : this.mdzipEntryRenderer\n ).filter((path) => path.length > 0).map((path) => path.toLowerCase());\n\n return {\n id: this.mdzipEntryRendererId\n ?? (paths.length > 0 ? `mdzip-ng-template:${paths.join(',')}` : `mdzip-ng-template#${index}`),\n priority: this.mdzipEntryRendererPriority ?? 0,\n matches: (context) => this.mdzipEntryRendererMatch\n ? this.mdzipEntryRendererMatch(context)\n : paths.includes(context.path.toLowerCase()),\n mount: (container, context) => {\n const templateContext: MdzipEntryRendererTemplateContext = {\n $implicit: context,\n context\n };\n const viewRef = this.viewContainerRef.createEmbeddedView(this.templateRef, templateContext);\n viewRef.detectChanges();\n const movedNodes = [...(viewRef.rootNodes as Node[])];\n for (const node of movedNodes) {\n container.appendChild(node);\n }\n return {\n update: (next) => {\n templateContext.$implicit = next;\n templateContext.context = next;\n viewRef.markForCheck();\n viewRef.detectChanges();\n },\n destroy: () => {\n viewRef.destroy();\n // The nodes were moved out of Angular's host container; make\n // sure none linger if the renderer did not remove them.\n for (const node of movedNodes) {\n node.parentNode?.removeChild(node);\n }\n }\n };\n }\n };\n }\n}\n","// Generated from package.json. Do not edit by hand.\nexport const PACKAGE_INFO = {\n \"name\": \"@mdzip/editor-ng\",\n \"version\": \"1.3.8\",\n \"repositoryUrl\": \"https://github.com/mdzip-project/mdzip-editor/tree/main/packages/editor-ng\",\n \"description\": \"Angular UI components for the MDZip workspace engine.\"\n} as const;\n","import {\n AfterContentInit,\n AfterViewInit,\n ChangeDetectionStrategy,\n Component,\n ContentChildren,\n ElementRef,\n EventEmitter,\n Input,\n OnChanges,\n OnDestroy,\n Output,\n QueryList,\n SimpleChanges,\n ViewChild,\n} from '@angular/core';\nimport { MdzipEntryRendererDirective } from './entry-renderer.directive';\nimport { PACKAGE_INFO } from './package-info.js';\nimport { MdzipWorkspaceView } from '@mdzip/editor';\nimport type {\n MdzipControlPolicy,\n MdzipControlPreset,\n MdzipColorScheme,\n MdzipConversionAction,\n MdzipConversionContext,\n MdzipEditorCommand,\n MdzipDocumentChangeEvent,\n MdzipEditorSnapshot,\n MdzipEntryRenderer,\n MdzipMarkdownRenderExtension,\n MdzipMarkdownRenderer,\n MdzipNavigationMode,\n MdzipRemoveAssetOptions,\n MdzipSourceFormat,\n MdzWorkspace,\n MdzWorkspaceAsset,\n MdzipWorkspaceChange,\n MdzipWorkspaceLayout,\n MdzipWorkspaceMode,\n MdzipWorkspaceSave,\n MdzipWorkspaceSnapshot,\n} from '@mdzip/editor';\n\n// Identity-insensitive key for the rendering inputs: extensions and entry\n// renderers are diffed by their stable name/id (and priority), so template\n// expressions that build new arrays each change-detection cycle never\n// trigger an update.\nfunction renderingConfigKey(\n extensions: readonly MdzipMarkdownRenderExtension[],\n entryRenderers: readonly MdzipEntryRenderer[]\n): string {\n return JSON.stringify([\n extensions.map((extension) => extension.name),\n entryRenderers.map((renderer) => [renderer.id, renderer.priority ?? 0]),\n ]);\n}\n\n@Component({\n selector: 'mdzip-workspace',\n standalone: true,\n template: '<div #host></div>',\n styles: [':host { display: block; height: 100%; } div { height: 100%; }'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class MdzipWorkspaceComponent implements AfterContentInit, AfterViewInit, OnChanges, OnDestroy {\n @Input() bytes: Uint8Array | null = null;\n @Input() workspace: MdzWorkspace | null = null;\n @Input() fileName = 'document.mdz';\n @Input() mode: MdzipWorkspaceMode = 'read-only';\n @Input() sourceFormat?: MdzipSourceFormat;\n @Input() controls: MdzipControlPreset | MdzipControlPolicy = 'viewer';\n @Input() initialLayout?: MdzipWorkspaceLayout;\n @Input() initialColorScheme?: MdzipColorScheme;\n @Input() navigationMode: MdzipNavigationMode = 'editor';\n @Input() navigationButtonActive = true;\n /**\n * Host hook for the markdown→MDZ conversion flow. An input function (not an\n * output) because it must return/resolve `true` to suppress the built-in\n * conversion dialog.\n */\n @Input() onConversionRequested?: (\n action: MdzipConversionAction,\n context: MdzipConversionContext\n ) => boolean | Promise<boolean>;\n /**\n * Custom markdown renderer. Keep the reference stable: identity changes\n * apply via a cheap preview re-render, never a workspace rebuild.\n */\n @Input() markdownRenderer?: MdzipMarkdownRenderer;\n /** Markdown pipeline extensions, diffed by `name`. */\n @Input() markdownExtensions: readonly MdzipMarkdownRenderExtension[] = [];\n /** Entry renderers, diffed by `id`/`priority`. */\n @Input() entryRenderers: readonly MdzipEntryRenderer[] = [];\n @Output() readonly changed = new EventEmitter<MdzipWorkspaceChange>();\n @Output() readonly saved = new EventEmitter<MdzipWorkspaceSave>();\n @Output() readonly workspaceChanged = new EventEmitter<MdzipDocumentChangeEvent>();\n @Output() readonly documentChanged = new EventEmitter<MdzipDocumentChangeEvent>();\n @Output() readonly assetChanged = new EventEmitter<MdzipDocumentChangeEvent>();\n @Output() readonly manifestChanged = new EventEmitter<MdzipDocumentChangeEvent>();\n @Output() readonly snapshotChanged = new EventEmitter<MdzipWorkspaceSnapshot>();\n @Output() readonly selectionChanged = new EventEmitter<MdzipWorkspaceSnapshot>();\n @Output() readonly dirtyChanged = new EventEmitter<MdzipWorkspaceSnapshot>();\n @Output() readonly validationChanged = new EventEmitter<MdzipWorkspaceSnapshot>();\n @Output() readonly colorSchemeChanged = new EventEmitter<MdzipColorScheme>();\n /** Emits when the preview HTML for the current selection is mounted. */\n @Output() readonly previewRendered = new EventEmitter<MdzipWorkspaceSnapshot>();\n /** Emits once the mounted preview's images have finished loading. */\n @Output() readonly assetsHydrated = new EventEmitter<MdzipWorkspaceSnapshot>();\n @Output() readonly failed = new EventEmitter<unknown>();\n\n @ViewChild('host') private readonly hostRef!: ElementRef<HTMLDivElement>;\n /**\n * `<ng-template mdzipEntryRenderer>` declarations projected into the\n * component. Each becomes an entry renderer appended after the\n * `entryRenderers` input (stable sort keeps the input ahead at equal\n * priority).\n */\n @ContentChildren(MdzipEntryRendererDirective)\n private readonly entryTemplates!: QueryList<MdzipEntryRendererDirective>;\n private view: MdzipWorkspaceView | null = null;\n private renderingKey = '';\n private entryTemplatesSub: { unsubscribe(): void } | null = null;\n\n ngAfterContentInit(): void {\n this.entryTemplatesSub = this.entryTemplates.changes.subscribe(() => {\n this.applyRenderingOptions(false);\n });\n }\n\n ngAfterViewInit(): void {\n this.createView();\n this.syncView();\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (this.view && (changes['controls'] || changes['initialLayout']\n || changes['initialColorScheme'] || changes['navigationMode']\n || changes['navigationButtonActive'])) {\n this.createView();\n this.syncView();\n return;\n }\n if (this.view && (changes['bytes'] || changes['workspace'] || changes['mode']\n || changes['sourceFormat'] || changes['fileName'])) {\n this.syncView();\n }\n if (this.view && (changes['markdownRenderer'] || changes['markdownExtensions']\n || changes['entryRenderers'])) {\n this.applyRenderingOptions(Boolean(changes['markdownRenderer']));\n }\n }\n\n ngOnDestroy(): void {\n this.entryTemplatesSub?.unsubscribe();\n this.view?.destroy();\n }\n\n canExecuteCommand(command: MdzipEditorCommand): boolean {\n return this.view?.canExecuteCommand(command) ?? false;\n }\n\n executeCommand(command: MdzipEditorCommand, file?: File): Promise<boolean> {\n return this.view?.executeCommand(command, file) ?? Promise.resolve(false);\n }\n\n convertToMdz(): Promise<boolean> {\n return this.view?.convertToMdz() ?? Promise.resolve(false);\n }\n\n focus(): void {\n this.view?.focus();\n }\n\n flush(): Promise<MdzipEditorSnapshot | null> {\n return this.view?.flush() ?? Promise.resolve(null);\n }\n\n serialize(): Promise<Blob | null> {\n return this.view?.serialize() ?? Promise.resolve(null);\n }\n\n getCurrentSnapshot(): Promise<MdzipEditorSnapshot | null> {\n return this.view?.getCurrentSnapshot() ?? Promise.resolve(null);\n }\n\n whenRendered(): Promise<void> {\n return this.view?.whenRendered() ?? Promise.resolve();\n }\n\n markPersisted(): void {\n this.view?.markPersisted();\n }\n\n addAsset(archivePath: string, fileBytes: Uint8Array): Promise<void> {\n return this.view?.addAsset(archivePath, fileBytes) ?? Promise.resolve();\n }\n\n replaceAsset(archivePath: string, fileBytes: Uint8Array): Promise<boolean> {\n return this.view?.replaceAsset(archivePath, fileBytes) ?? Promise.resolve(false);\n }\n\n removeAsset(archivePath: string, options?: MdzipRemoveAssetOptions): Promise<boolean> {\n return this.view?.removeAsset(archivePath, options) ?? Promise.resolve(false);\n }\n\n removeFile(archivePath: string): Promise<boolean> {\n return this.view?.removeFile(archivePath) ?? Promise.resolve(false);\n }\n\n renameFile(oldPath: string, newPath: string): Promise<boolean> {\n return this.view?.renameFile(oldPath, newPath) ?? Promise.resolve(false);\n }\n\n setEntryPoint(archivePath: string): Promise<boolean> {\n return this.view?.setEntryPoint(archivePath) ?? Promise.resolve(false);\n }\n\n setCoverImage(archivePath: string | null): Promise<boolean> {\n return this.view?.setCoverImage(archivePath) ?? Promise.resolve(false);\n }\n\n listAssets(): MdzWorkspaceAsset[] {\n return this.view?.listAssets() ?? [];\n }\n\n private syncView(): void {\n if (this.view && this.workspace) {\n void this.view.openWorkspace(this.workspace, {\n mode: this.mode,\n sourceFormat: this.sourceFormat,\n fileName: this.fileName\n });\n } else if (this.view && this.bytes) {\n void this.view.open(this.bytes, {\n mode: this.mode,\n sourceFormat: this.sourceFormat,\n fileName: this.fileName\n });\n }\n }\n\n private createView(): void {\n this.view?.destroy();\n this.view = new MdzipWorkspaceView(this.hostRef.nativeElement, {\n libraries: [PACKAGE_INFO],\n controls: this.controls,\n initialLayout: this.initialLayout,\n initialColorScheme: this.initialColorScheme,\n navigationMode: this.navigationMode,\n navigationButtonActive: this.navigationButtonActive,\n onChanged: (bytes, snapshot) => this.changed.emit({ bytes, snapshot }),\n onSaved: (bytes, snapshot) => this.saved.emit({ bytes, snapshot }),\n onWorkspaceChanged: (event) => this.workspaceChanged.emit(event),\n onDocumentChanged: (event) => this.documentChanged.emit(event),\n onAssetChanged: (event) => this.assetChanged.emit(event),\n onManifestChanged: (event) => this.manifestChanged.emit(event),\n onSnapshotChanged: (snapshot) => this.snapshotChanged.emit(snapshot),\n onSelectionChanged: (snapshot: MdzipWorkspaceSnapshot) => this.selectionChanged.emit(snapshot),\n onDirtyChanged: (snapshot: MdzipWorkspaceSnapshot) => this.dirtyChanged.emit(snapshot),\n onValidationChanged: (snapshot: MdzipWorkspaceSnapshot) => this.validationChanged.emit(snapshot),\n onColorSchemeChanged: (colorScheme: MdzipColorScheme) => this.colorSchemeChanged.emit(colorScheme),\n onPreviewRendered: (snapshot: MdzipWorkspaceSnapshot) => this.previewRendered.emit(snapshot),\n onAssetsHydrated: (snapshot: MdzipWorkspaceSnapshot) => this.assetsHydrated.emit(snapshot),\n onFailed: (e: unknown) => this.failed.emit(e),\n onConversionRequested: this.onConversionRequested\n ? (action, context) => this.onConversionRequested!(action, context)\n : undefined,\n markdownRenderer: this.markdownRenderer,\n markdownExtensions: this.markdownExtensions,\n entryRenderers: this.composedEntryRenderers(),\n });\n this.renderingKey = renderingConfigKey(this.markdownExtensions, this.composedEntryRenderers());\n }\n\n private composedEntryRenderers(): readonly MdzipEntryRenderer[] {\n const templates = this.entryTemplates\n ? this.entryTemplates.map((directive, index) => directive.toEntryRenderer(index))\n : [];\n return [...this.entryRenderers, ...templates];\n }\n\n // Applies rendering input changes in place — never a view rebuild. Arrays\n // re-apply only when their name/id key changes, so template expressions\n // that produce new array identities each cycle are safe.\n private applyRenderingOptions(rendererChanged: boolean): void {\n const composed = this.composedEntryRenderers();\n const key = renderingConfigKey(this.markdownExtensions, composed);\n if (!rendererChanged && key === this.renderingKey) {\n return;\n }\n this.renderingKey = key;\n this.view?.setRenderingOptions({\n markdownRenderer: this.markdownRenderer ?? null,\n markdownExtensions: this.markdownExtensions,\n entryRenderers: composed,\n });\n }\n}\n","import {\n AfterViewInit,\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n EventEmitter,\n Input,\n OnChanges,\n OnDestroy,\n Output,\n SimpleChanges,\n ViewChild\n} from '@angular/core';\nimport type {\n MdzipDiffControlsOptions,\n MdzipDiffSelectionEvent,\n MdzipDiffSideInput,\n MdzipDiffToolbarAction,\n MdzipDiffView,\n MdzipDiffViewOptions\n} from '@mdzip/editor/diff-view';\n\n@Component({\n selector: 'mdzip-diff',\n standalone: true,\n template: '<div #host></div>',\n styles: [':host { display:block; height:100%; } div { height:100%; }'],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class MdzipDiffComponent implements AfterViewInit, OnChanges, OnDestroy {\n @Input({ required: true }) before!: MdzipDiffSideInput;\n @Input({ required: true }) after!: MdzipDiffSideInput;\n @Input() initialPath?: string;\n @Input() showUnchanged = true;\n @Input() navigationVisible = true;\n @Input() controls?: MdzipDiffControlsOptions;\n @Input() toolbarActions: readonly MdzipDiffToolbarAction[] = [];\n @Output() readonly selectionChanged = new EventEmitter<MdzipDiffSelectionEvent>();\n @Output() readonly failed = new EventEmitter<Error>();\n\n @ViewChild('host') private readonly hostRef!: ElementRef<HTMLDivElement>;\n private view: MdzipDiffView | null = null;\n private destroyed = false;\n\n ngAfterViewInit(): void {\n void this.createView();\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (!this.view) return;\n if (changes['before'] || changes['after'] || changes['initialPath']) {\n void this.view.open(this.options());\n }\n if (changes['showUnchanged']) this.view.setShowUnchanged(this.showUnchanged);\n if (changes['navigationVisible']) this.view.setNavigationVisible(this.navigationVisible);\n if (changes['toolbarActions']) this.view.setToolbarActions(this.toolbarActions);\n }\n\n ngOnDestroy(): void {\n this.destroyed = true;\n this.view?.destroy();\n this.view = null;\n }\n\n openPath(path: string): Promise<boolean> {\n return this.view?.openPath(path) ?? Promise.resolve(false);\n }\n\n openPreviousChange(): Promise<boolean> {\n return this.view?.openPreviousChange() ?? Promise.resolve(false);\n }\n\n openNextChange(): Promise<boolean> {\n return this.view?.openNextChange() ?? Promise.resolve(false);\n }\n\n setShowUnchanged(show: boolean): void {\n this.view?.setShowUnchanged(show);\n }\n\n setNavigationVisible(visible: boolean): void {\n this.view?.setNavigationVisible(visible);\n }\n\n setToolbarActions(actions: readonly MdzipDiffToolbarAction[]): void {\n this.view?.setToolbarActions(actions);\n }\n\n private async createView(): Promise<void> {\n const { MdzipDiffView } = await import('@mdzip/editor/diff-view');\n if (this.destroyed) return;\n this.view = new MdzipDiffView(this.hostRef.nativeElement, this.options());\n }\n\n private options(): MdzipDiffViewOptions {\n return {\n before: this.before,\n after: this.after,\n initialPath: this.initialPath,\n showUnchanged: this.showUnchanged,\n navigationVisible: this.navigationVisible,\n controls: this.controls,\n toolbarActions: this.toolbarActions,\n onSelectionChanged: (event) => this.selectionChanged.emit(event),\n onFailed: (error) => this.failed.emit(error)\n };\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import * as i0 from '@angular/core';
2
- import { AfterViewInit, OnChanges, OnDestroy, EventEmitter, SimpleChanges } from '@angular/core';
3
- import { MdzWorkspace, MdzipWorkspaceMode, MdzipSourceFormat, MdzipControlPreset, MdzipControlPolicy, MdzipWorkspaceLayout, MdzipColorScheme, MdzipNavigationMode, MdzipConversionAction, MdzipWorkspaceChange, MdzipWorkspaceSave, MdzipDocumentChangeEvent, MdzipWorkspaceSnapshot, MdzipEditorCommand, MdzipEditorSnapshot, MdzipRemoveAssetOptions, MdzWorkspaceAsset } from '@mdzip/editor';
2
+ import { AfterContentInit, AfterViewInit, OnChanges, OnDestroy, EventEmitter, SimpleChanges, TemplateRef } from '@angular/core';
3
+ import { MdzWorkspace, MdzipWorkspaceMode, MdzipSourceFormat, MdzipControlPreset, MdzipControlPolicy, MdzipWorkspaceLayout, MdzipColorScheme, MdzipNavigationMode, MdzipConversionAction, MdzipConversionContext, MdzipMarkdownRenderer, MdzipMarkdownRenderExtension, MdzipEntryRenderer, MdzipWorkspaceChange, MdzipWorkspaceSave, MdzipDocumentChangeEvent, MdzipWorkspaceSnapshot, MdzipEditorCommand, MdzipEditorSnapshot, MdzipRemoveAssetOptions, MdzWorkspaceAsset, MdzipEntryRenderContext } from '@mdzip/editor';
4
+ import { MdzipDiffSideInput, MdzipDiffControlsOptions, MdzipDiffToolbarAction, MdzipDiffSelectionEvent } from '@mdzip/editor/diff-view';
4
5
 
5
- declare class MdzipWorkspaceComponent implements AfterViewInit, OnChanges, OnDestroy {
6
+ declare class MdzipWorkspaceComponent implements AfterContentInit, AfterViewInit, OnChanges, OnDestroy {
6
7
  bytes: Uint8Array | null;
7
8
  workspace: MdzWorkspace | null;
8
9
  fileName: string;
@@ -18,7 +19,16 @@ declare class MdzipWorkspaceComponent implements AfterViewInit, OnChanges, OnDes
18
19
  * output) because it must return/resolve `true` to suppress the built-in
19
20
  * conversion dialog.
20
21
  */
21
- onConversionRequested?: (action: MdzipConversionAction) => boolean | Promise<boolean>;
22
+ onConversionRequested?: (action: MdzipConversionAction, context: MdzipConversionContext) => boolean | Promise<boolean>;
23
+ /**
24
+ * Custom markdown renderer. Keep the reference stable: identity changes
25
+ * apply via a cheap preview re-render, never a workspace rebuild.
26
+ */
27
+ markdownRenderer?: MdzipMarkdownRenderer;
28
+ /** Markdown pipeline extensions, diffed by `name`. */
29
+ markdownExtensions: readonly MdzipMarkdownRenderExtension[];
30
+ /** Entry renderers, diffed by `id`/`priority`. */
31
+ entryRenderers: readonly MdzipEntryRenderer[];
22
32
  readonly changed: EventEmitter<MdzipWorkspaceChange>;
23
33
  readonly saved: EventEmitter<MdzipWorkspaceSave>;
24
34
  readonly workspaceChanged: EventEmitter<MdzipDocumentChangeEvent>;
@@ -30,9 +40,23 @@ declare class MdzipWorkspaceComponent implements AfterViewInit, OnChanges, OnDes
30
40
  readonly dirtyChanged: EventEmitter<MdzipWorkspaceSnapshot>;
31
41
  readonly validationChanged: EventEmitter<MdzipWorkspaceSnapshot>;
32
42
  readonly colorSchemeChanged: EventEmitter<MdzipColorScheme>;
43
+ /** Emits when the preview HTML for the current selection is mounted. */
44
+ readonly previewRendered: EventEmitter<MdzipWorkspaceSnapshot>;
45
+ /** Emits once the mounted preview's images have finished loading. */
46
+ readonly assetsHydrated: EventEmitter<MdzipWorkspaceSnapshot>;
33
47
  readonly failed: EventEmitter<unknown>;
34
48
  private readonly hostRef;
49
+ /**
50
+ * `<ng-template mdzipEntryRenderer>` declarations projected into the
51
+ * component. Each becomes an entry renderer appended after the
52
+ * `entryRenderers` input (stable sort keeps the input ahead at equal
53
+ * priority).
54
+ */
55
+ private readonly entryTemplates;
35
56
  private view;
57
+ private renderingKey;
58
+ private entryTemplatesSub;
59
+ ngAfterContentInit(): void;
36
60
  ngAfterViewInit(): void;
37
61
  ngOnChanges(changes: SimpleChanges): void;
38
62
  ngOnDestroy(): void;
@@ -43,6 +67,7 @@ declare class MdzipWorkspaceComponent implements AfterViewInit, OnChanges, OnDes
43
67
  flush(): Promise<MdzipEditorSnapshot | null>;
44
68
  serialize(): Promise<Blob | null>;
45
69
  getCurrentSnapshot(): Promise<MdzipEditorSnapshot | null>;
70
+ whenRendered(): Promise<void>;
46
71
  markPersisted(): void;
47
72
  addAsset(archivePath: string, fileBytes: Uint8Array): Promise<void>;
48
73
  replaceAsset(archivePath: string, fileBytes: Uint8Array): Promise<boolean>;
@@ -54,9 +79,80 @@ declare class MdzipWorkspaceComponent implements AfterViewInit, OnChanges, OnDes
54
79
  listAssets(): MdzWorkspaceAsset[];
55
80
  private syncView;
56
81
  private createView;
82
+ private composedEntryRenderers;
83
+ private applyRenderingOptions;
57
84
  static ɵfac: i0.ɵɵFactoryDeclaration<MdzipWorkspaceComponent, never>;
58
- static ɵcmp: i0.ɵɵComponentDeclaration<MdzipWorkspaceComponent, "mdzip-workspace", never, { "bytes": { "alias": "bytes"; "required": false; }; "workspace": { "alias": "workspace"; "required": false; }; "fileName": { "alias": "fileName"; "required": false; }; "mode": { "alias": "mode"; "required": false; }; "sourceFormat": { "alias": "sourceFormat"; "required": false; }; "controls": { "alias": "controls"; "required": false; }; "initialLayout": { "alias": "initialLayout"; "required": false; }; "initialColorScheme": { "alias": "initialColorScheme"; "required": false; }; "navigationMode": { "alias": "navigationMode"; "required": false; }; "navigationButtonActive": { "alias": "navigationButtonActive"; "required": false; }; "onConversionRequested": { "alias": "onConversionRequested"; "required": false; }; }, { "changed": "changed"; "saved": "saved"; "workspaceChanged": "workspaceChanged"; "documentChanged": "documentChanged"; "assetChanged": "assetChanged"; "manifestChanged": "manifestChanged"; "snapshotChanged": "snapshotChanged"; "selectionChanged": "selectionChanged"; "dirtyChanged": "dirtyChanged"; "validationChanged": "validationChanged"; "colorSchemeChanged": "colorSchemeChanged"; "failed": "failed"; }, never, never, true, never>;
85
+ static ɵcmp: i0.ɵɵComponentDeclaration<MdzipWorkspaceComponent, "mdzip-workspace", never, { "bytes": { "alias": "bytes"; "required": false; }; "workspace": { "alias": "workspace"; "required": false; }; "fileName": { "alias": "fileName"; "required": false; }; "mode": { "alias": "mode"; "required": false; }; "sourceFormat": { "alias": "sourceFormat"; "required": false; }; "controls": { "alias": "controls"; "required": false; }; "initialLayout": { "alias": "initialLayout"; "required": false; }; "initialColorScheme": { "alias": "initialColorScheme"; "required": false; }; "navigationMode": { "alias": "navigationMode"; "required": false; }; "navigationButtonActive": { "alias": "navigationButtonActive"; "required": false; }; "onConversionRequested": { "alias": "onConversionRequested"; "required": false; }; "markdownRenderer": { "alias": "markdownRenderer"; "required": false; }; "markdownExtensions": { "alias": "markdownExtensions"; "required": false; }; "entryRenderers": { "alias": "entryRenderers"; "required": false; }; }, { "changed": "changed"; "saved": "saved"; "workspaceChanged": "workspaceChanged"; "documentChanged": "documentChanged"; "assetChanged": "assetChanged"; "manifestChanged": "manifestChanged"; "snapshotChanged": "snapshotChanged"; "selectionChanged": "selectionChanged"; "dirtyChanged": "dirtyChanged"; "validationChanged": "validationChanged"; "colorSchemeChanged": "colorSchemeChanged"; "previewRendered": "previewRendered"; "assetsHydrated": "assetsHydrated"; "failed": "failed"; }, ["entryTemplates"], never, true, never>;
86
+ }
87
+
88
+ /** Template context available via `let-context` (also the `$implicit` value). */
89
+ interface MdzipEntryRendererTemplateContext {
90
+ $implicit: MdzipEntryRenderContext;
91
+ context: MdzipEntryRenderContext;
92
+ }
93
+ /**
94
+ * Declares an entry renderer template inside `<mdzip-workspace>`:
95
+ *
96
+ * ```html
97
+ * <mdzip-workspace [bytes]="bytes" mode="editable">
98
+ * <ng-template mdzipEntryRenderer="manifest.json" let-context>
99
+ * <app-internals [manifest]="context.manifest" />
100
+ * </ng-template>
101
+ * </mdzip-workspace>
102
+ * ```
103
+ *
104
+ * Match either by exact archive path(s) via `mdzipEntryRenderer`, or with a
105
+ * predicate via `[mdzipEntryRendererMatch]`. The embedded view is created in
106
+ * the workspace component's view container (so change detection and
107
+ * dependency injection work normally), its DOM is moved into the editor's
108
+ * entry pane, and the view is destroyed when the selection changes or the
109
+ * workspace is destroyed.
110
+ */
111
+ declare class MdzipEntryRendererDirective {
112
+ readonly templateRef: TemplateRef<any>;
113
+ private readonly viewContainerRef;
114
+ /** Exact archive path(s) to claim, case-insensitive. */
115
+ mdzipEntryRenderer: string | readonly string[];
116
+ /** Predicate alternative for extension/MIME/path-family matching. */
117
+ mdzipEntryRendererMatch?: (context: MdzipEntryRenderContext) => boolean;
118
+ /** Stable id used for renderer diffing. Defaults to the matched paths. */
119
+ mdzipEntryRendererId?: string;
120
+ /** Matching priority relative to the `entryRenderers` input. Default 0. */
121
+ mdzipEntryRendererPriority?: number;
122
+ /** Adapts this template onto the framework-independent renderer contract. */
123
+ toEntryRenderer(index: number): MdzipEntryRenderer;
124
+ static ɵfac: i0.ɵɵFactoryDeclaration<MdzipEntryRendererDirective, never>;
125
+ static ɵdir: i0.ɵɵDirectiveDeclaration<MdzipEntryRendererDirective, "ng-template[mdzipEntryRenderer], ng-template[mdzipEntryRendererMatch]", never, { "mdzipEntryRenderer": { "alias": "mdzipEntryRenderer"; "required": false; }; "mdzipEntryRendererMatch": { "alias": "mdzipEntryRendererMatch"; "required": false; }; "mdzipEntryRendererId": { "alias": "mdzipEntryRendererId"; "required": false; }; "mdzipEntryRendererPriority": { "alias": "mdzipEntryRendererPriority"; "required": false; }; }, {}, never, never, true, never>;
126
+ }
127
+
128
+ declare class MdzipDiffComponent implements AfterViewInit, OnChanges, OnDestroy {
129
+ before: MdzipDiffSideInput;
130
+ after: MdzipDiffSideInput;
131
+ initialPath?: string;
132
+ showUnchanged: boolean;
133
+ navigationVisible: boolean;
134
+ controls?: MdzipDiffControlsOptions;
135
+ toolbarActions: readonly MdzipDiffToolbarAction[];
136
+ readonly selectionChanged: EventEmitter<MdzipDiffSelectionEvent>;
137
+ readonly failed: EventEmitter<Error>;
138
+ private readonly hostRef;
139
+ private view;
140
+ private destroyed;
141
+ ngAfterViewInit(): void;
142
+ ngOnChanges(changes: SimpleChanges): void;
143
+ ngOnDestroy(): void;
144
+ openPath(path: string): Promise<boolean>;
145
+ openPreviousChange(): Promise<boolean>;
146
+ openNextChange(): Promise<boolean>;
147
+ setShowUnchanged(show: boolean): void;
148
+ setNavigationVisible(visible: boolean): void;
149
+ setToolbarActions(actions: readonly MdzipDiffToolbarAction[]): void;
150
+ private createView;
151
+ private options;
152
+ static ɵfac: i0.ɵɵFactoryDeclaration<MdzipDiffComponent, never>;
153
+ static ɵcmp: i0.ɵɵComponentDeclaration<MdzipDiffComponent, "mdzip-diff", never, { "before": { "alias": "before"; "required": true; }; "after": { "alias": "after"; "required": true; }; "initialPath": { "alias": "initialPath"; "required": false; }; "showUnchanged": { "alias": "showUnchanged"; "required": false; }; "navigationVisible": { "alias": "navigationVisible"; "required": false; }; "controls": { "alias": "controls"; "required": false; }; "toolbarActions": { "alias": "toolbarActions"; "required": false; }; }, { "selectionChanged": "selectionChanged"; "failed": "failed"; }, never, never, true, never>;
59
154
  }
60
155
 
61
- export { MdzipWorkspaceComponent };
156
+ export { MdzipDiffComponent, MdzipEntryRendererDirective, MdzipWorkspaceComponent };
157
+ export type { MdzipEntryRendererTemplateContext };
62
158
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sources":["../src/workspace.component.ts"],"mappings":";;;;AAkCA,cAAA,mCAOqC,aAAW,EAAA,SAAe,EAAA,SAAW;AAC/D,WAAO,UAAU;AACjB,eAAW,YAAY;AACvB;UACM,kBAAkB;mBACT,iBAAiB;AAChC,cAAU,kBAAkB,GAAG,kBAAkB;oBACjC,oBAAoB;yBACf,gBAAgB;oBACrB,mBAAmB;AACnC;AACT;;;;AAIG;AACM,qCAAiC,qBAAqB,eAAe,OAAO;sBAC3D,YAAA,CAAA,oBAAA;oBACF,YAAA,CAAA,kBAAA;+BACW,YAAA,CAAA,wBAAA;8BACD,YAAA,CAAA,wBAAA;2BACH,YAAA,CAAA,wBAAA;8BACG,YAAA,CAAA,wBAAA;8BACA,YAAA,CAAA,sBAAA;+BACC,YAAA,CAAA,sBAAA;2BACJ,YAAA,CAAA,sBAAA;gCACK,YAAA,CAAA,sBAAA;iCACC,YAAA,CAAA,gBAAA;qBACZ,YAAA;AAEN;;AAGnB;AAKA,yBAAqB,aAAa;AAclC;AAIA,+BAA2B,kBAAkB;AAI7C,4BAAwB,kBAAkB,SAAS,IAAI,GAAG,OAAO;AAIjE,oBAAgB,OAAO;AAIvB;AAIA,aAAS,OAAO,CAAC,mBAAmB;AAIpC,iBAAa,OAAO,CAAC,IAAI;AAIzB,0BAAsB,OAAO,CAAC,mBAAmB;AAIjD;AAIA,6CAAyC,UAAU,GAAG,OAAO;AAI7D,iDAA6C,UAAU,GAAG,OAAO;AAIjE,+CAA2C,uBAAuB,GAAG,OAAO;qCAI3C,OAAO;AAIxC,kDAA8C,OAAO;wCAIjB,OAAO;+CAIA,OAAO;kBAIpC,iBAAiB;AAI/B;AAgBA;yCAxIW,uBAAuB;2CAAvB,uBAAuB;AAiKnC;;;;","names":[]}
1
+ {"version":3,"file":"index.d.ts","sources":["../src/workspace.component.ts","../src/entry-renderer.directive.ts","../src/diff.component.ts"],"mappings":";;;;;AAyDA,cAAA,uBAOa,4BAAmC,EAAA,wBAAiC,EAAA,SAAW;AACjF,WAAO,UAAU;AACjB,eAAW,YAAY;AACvB;UACM,kBAAkB;mBACT,iBAAiB;AAChC,cAAU,kBAAkB,GAAG,kBAAkB;oBACjC,oBAAoB;yBACf,gBAAgB;oBACrB,mBAAmB;AACnC;AACT;;;;AAIG;AACM,qCACC,qBAAqB,WACpB,sBAAsB,eAClB,OAAO;AACtB;;;AAGG;uBACyB,qBAAqB;;AAExC,iCAA6B,4BAA4B;;AAEzD,6BAAyB,kBAAkB;sBAC1B,YAAA,CAAA,oBAAA;oBACF,YAAA,CAAA,kBAAA;+BACW,YAAA,CAAA,wBAAA;8BACD,YAAA,CAAA,wBAAA;2BACH,YAAA,CAAA,wBAAA;8BACG,YAAA,CAAA,wBAAA;8BACA,YAAA,CAAA,sBAAA;+BACC,YAAA,CAAA,sBAAA;2BACJ,YAAA,CAAA,sBAAA;gCACK,YAAA,CAAA,sBAAA;iCACC,YAAA,CAAA,gBAAA;;8BAEH,YAAA,CAAA,sBAAA;;6BAED,YAAA,CAAA,sBAAA;qBACR,YAAA;AAEN;AACnB;;;;;AAKG;AAEH;;;;AAKA;AAMA;AAKA,yBAAqB,aAAa;AAkBlC;AAKA,+BAA2B,kBAAkB;AAI7C,4BAAwB,kBAAkB,SAAS,IAAI,GAAG,OAAO;AAIjE,oBAAgB,OAAO;AAIvB;AAIA,aAAS,OAAO,CAAC,mBAAmB;AAIpC,iBAAa,OAAO,CAAC,IAAI;AAIzB,0BAAsB,OAAO,CAAC,mBAAmB;AAIjD,oBAAgB,OAAO;AAIvB;AAIA,6CAAyC,UAAU,GAAG,OAAO;AAI7D,iDAA6C,UAAU,GAAG,OAAO;AAIjE,+CAA2C,uBAAuB,GAAG,OAAO;qCAI3C,OAAO;AAIxC,kDAA8C,OAAO;wCAIjB,OAAO;+CAIA,OAAO;kBAIpC,iBAAiB;AAI/B;AAgBA;AAiCA;AAUA;yCA5NW,uBAAuB;2CAAvB,uBAAuB;AAyOnC;;ACtSD;AACA,2CAAiB;eACJ,uBAAuB;aACzB,uBAAuB;AACjC;AAED;;;;;;;;;;;;;;;;;AAiBG;AACH,cAAA,2BAIa;0BACS,WAAA;AACpB;;AAGS;;wCAEoC,uBAAuB;;;;;;AAOpE,oCAAgC,kBAAkB;yCAdvC,2BAA2B;2CAA3B,2BAA2B;AAyDvC;;AClED,cAAA,8BAOgC,aAAW,EAAA,SAAe,EAAA,SAAW;YAC/B,kBAAkB;WACnB,kBAAkB;;AAE5C;AACA;eACW,wBAAwB;AACnC,6BAAyB,sBAAsB;+BACrB,YAAA,CAAA,uBAAA;qBACV,YAAA,CAAA,KAAA;AAEN;;;AAInB;AAIA,yBAAqB,aAAa;AAUlC;4BAMwB,OAAO;AAI/B,0BAAsB,OAAO;AAI7B,sBAAkB,OAAO;AAIzB;AAIA;AAIA,wCAAoC,sBAAsB;;AAU1D;yCAjEW,kBAAkB;2CAAlB,kBAAkB;AA8E9B;;;;","names":[]}
package/package.json CHANGED
@@ -1,8 +1,17 @@
1
1
  {
2
2
  "name": "@mdzip/editor-ng",
3
- "version": "1.3.0",
3
+ "version": "1.3.8",
4
4
  "description": "Angular UI components for the MDZip workspace engine.",
5
5
  "license": "Apache-2.0",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/mdzip-project/mdzip-editor.git",
9
+ "directory": "packages/editor-ng"
10
+ },
11
+ "homepage": "https://mdzip.org",
12
+ "bugs": {
13
+ "url": "https://github.com/mdzip-project/mdzip-editor/issues"
14
+ },
6
15
  "type": "module",
7
16
  "module": "dist/fesm2022/mdzip-editor-ng.mjs",
8
17
  "types": "dist/index.d.ts",
@@ -19,13 +28,16 @@
19
28
  "peerDependencies": {
20
29
  "@angular/common": ">=20.0.0",
21
30
  "@angular/core": ">=20.0.0",
22
- "@mdzip/editor": "^1.3.0"
31
+ "@mdzip/editor": "^1.3.8"
23
32
  },
24
33
  "dependencies": {
25
34
  "tslib": "^2.8.1"
26
35
  },
27
36
  "scripts": {
28
- "build": "ng build @mdzip/editor-ng"
37
+ "generate:package-info": "node ../../scripts/generate-package-info.mjs",
38
+ "prebuild": "npm run generate:package-info",
39
+ "build": "ng build @mdzip/editor-ng",
40
+ "test": "vitest run"
29
41
  },
30
42
  "files": [
31
43
  "dist"