prosemirror-rs 0.3.4 → 0.3.6

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/Cargo.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "prosemirror-rs-node"
3
- version = "0.3.4"
3
+ version = "0.3.6"
4
4
  authors = [
5
5
  "Johannes Wilm <johannes@fiduswriter.org>",
6
6
  "Daniel Seiler <me@dseiler.eu>",
package/index.d.ts CHANGED
@@ -100,9 +100,13 @@ export declare class Editor {
100
100
  * passed to JavaScript. Suitable for saving directly to a database without
101
101
  * creating any intermediate JS objects.
102
102
  *
103
+ * When `skipDefaults` is `true`, attributes whose value matches the
104
+ * schema-defined default are omitted from the output ("mini" JSON).
105
+ *
106
+ * @param skipDefaults If true, omit attributes that have default values.
103
107
  * @returns The current document as a compact JSON string.
104
108
  */
105
- docJson(): string;
109
+ docJson(skipDefaults?: boolean): string;
106
110
 
107
111
  /**
108
112
  * Number of steps successfully applied since construction or last `reset()`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prosemirror-rs",
3
- "version": "0.3.4",
3
+ "version": "0.3.6",
4
4
  "description": "Node.js bindings for prosemirror-rs: a Rust implementation of ProseMirror's document model and transform pipeline",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
Binary file
Binary file
Binary file
package/src/lib.rs CHANGED
@@ -268,10 +268,15 @@ impl Editor {
268
268
  /// document directly to a database without creating any intermediate
269
269
  /// JS objects.
270
270
  ///
271
+ /// When `skipDefaults` is `true`, attributes whose value matches the
272
+ /// schema-defined default are omitted from the output ("mini" JSON).
273
+ ///
274
+ /// @param skipDefaults If true, omit attributes that have default values.
271
275
  /// @returns The document as a compact JSON string.
272
276
  #[napi]
273
- pub fn doc_json(&self) -> napi::Result<String> {
274
- serde_json::to_string(&self.doc)
277
+ pub fn doc_json(&self, skip_defaults: Option<bool>) -> napi::Result<String> {
278
+ let val = self.schema.with_types(|| self.doc.to_json(skip_defaults.unwrap_or(false)));
279
+ serde_json::to_string(&val)
275
280
  .map_err(|e| napi::Error::new(Status::GenericFailure, format!("Serialization error: {e}")))
276
281
  }
277
282
 
@@ -81,16 +81,96 @@ test('constructor throws when doc JSON is not a node object', () => {
81
81
  });
82
82
 
83
83
  // ---------------------------------------------------------------------------
84
- // docJson
84
+ // docJson with skipDefaults
85
85
  // ---------------------------------------------------------------------------
86
86
 
87
- test('docJson returns a valid JSON string containing the initial text', () => {
88
- const editor = new Editor(SCHEMA, DOC);
89
- const raw = editor.docJson();
90
- assert.equal(typeof raw, 'string');
91
- const doc = JSON.parse(raw);
92
- assert.equal(doc.type, 'doc');
93
- assert.ok(raw.includes('hello'), `Expected "hello" in: ${raw}`);
87
+ test('docJson() without argument includes all attributes', () => {
88
+ // Schema with attributes that have defaults
89
+ const schemaWithAttrs = JSON.stringify({
90
+ nodes: {
91
+ doc: { content: 'paragraph+' },
92
+ paragraph: {
93
+ content: 'text*',
94
+ group: 'block',
95
+ attrs: { align: { default: 'left' }, indent: { default: 0 } },
96
+ },
97
+ text: { group: 'inline' },
98
+ },
99
+ marks: { strong: { attrs: { level: { default: 1 } } }, em: {} },
100
+ });
101
+
102
+ // Document with default attributes (should be included in regular serialization)
103
+ const docDefault = JSON.stringify({
104
+ type: 'doc',
105
+ content: [{
106
+ type: 'paragraph',
107
+ attrs: { align: 'left', indent: 0 },
108
+ content: [{
109
+ type: 'text',
110
+ text: 'hello',
111
+ marks: [{ type: 'strong', attrs: { level: 1 } }],
112
+ }],
113
+ }],
114
+ });
115
+
116
+ const editorDefault = new Editor(schemaWithAttrs, docDefault);
117
+
118
+ // Regular serialization should include all attrs
119
+ const fullRaw = editorDefault.docJson();
120
+ const full = JSON.parse(fullRaw);
121
+ assert.ok(fullRaw.includes('"attrs"'), `Expected attrs in full serialization: ${fullRaw}`);
122
+ assert.equal(full.content[0].attrs.align, 'left');
123
+ assert.equal(full.content[0].attrs.indent, 0);
124
+ assert.equal(full.content[0].content[0].marks[0].attrs.level, 1);
125
+
126
+ // Mini serialization should skip all default attributes
127
+ const miniRaw = editorDefault.docJson(true);
128
+ const mini = JSON.parse(miniRaw);
129
+ assert.ok(!miniRaw.includes('"attrs"'), `Expected no attrs in mini serialization: ${miniRaw}`);
130
+ assert.ok(!('attrs' in mini.content[0]), 'paragraph should have no attrs');
131
+ assert.ok(!('attrs' in mini.content[0].content[0].marks[0]), 'mark should have no attrs');
132
+
133
+ // Document with non-default attributes
134
+ const docCustom = JSON.stringify({
135
+ type: 'doc',
136
+ content: [{
137
+ type: 'paragraph',
138
+ attrs: { align: 'right', indent: 2 },
139
+ content: [{ type: 'text', text: 'world' }],
140
+ }],
141
+ });
142
+
143
+ const editorCustom = new Editor(schemaWithAttrs, docCustom);
144
+ const miniCustomRaw = editorCustom.docJson(true);
145
+ const miniCustom = JSON.parse(miniCustomRaw);
146
+ // Non-default attrs should still appear
147
+ assert.ok(miniCustomRaw.includes('"attrs"'), `Expected attrs for non-default values: ${miniCustomRaw}`);
148
+ assert.equal(miniCustom.content[0].attrs.align, 'right');
149
+ assert.equal(miniCustom.content[0].attrs.indent, 2);
150
+
151
+ // Mix of default and non-default
152
+ const docMixed = JSON.stringify({
153
+ type: 'doc',
154
+ content: [{
155
+ type: 'paragraph',
156
+ attrs: { align: 'center', indent: 0 },
157
+ content: [{ type: 'text', text: 'mixed' }],
158
+ }],
159
+ });
160
+
161
+ const editorMixed = new Editor(schemaWithAttrs, docMixed);
162
+ const miniMixedRaw = editorMixed.docJson(true);
163
+ const miniMixed = JSON.parse(miniMixedRaw);
164
+ // Only 'align' should be present (indent is default 0)
165
+ assert.ok(miniMixedRaw.includes('"attrs"'), `Expected attrs for partial non-default: ${miniMixedRaw}`);
166
+ assert.equal(miniMixed.content[0].attrs.align, 'center');
167
+ assert.ok(!('indent' in miniMixed.content[0].attrs), 'indent should be omitted (default value)');
168
+
169
+ // Verify backwards compatibility: no argument == false
170
+ const editorBC = new Editor(SCHEMA, DOC);
171
+ const noArg = editorBC.docJson();
172
+ const falseArg = editorBC.docJson(false);
173
+ assert.equal(noArg, falseArg, 'docJson() and docJson(false) should be identical');
94
174
  });
95
175
 
96
176
  // ---------------------------------------------------------------------------