@qarakash/blockwriteai 1.0.8 → 1.0.10

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,392 +1,201 @@
1
- # BlockWriteAI
2
-
3
- BlockWriteAI is a drop-in block writing editor for the web. It is built to feel familiar to Editor.js users, but ships as plain CSS and JavaScript files that can be used in PHP, Laravel, CodeIgniter, static HTML, dashboards, or any project that can load a script tag.
4
-
5
- The editor stores and saves content as JSON first. Projects can render that JSON on any page by adding a BlockWriteAI preview container, while advanced document blocks such as tables, media galleries, attachments, diagrams, charts, signatures, and code editing remain available as plugins.
6
-
7
- All public assets, package entry points, and browser globals use the `BlockWriteAI` name.
8
-
9
- ## Highlights
10
-
11
- - Editor.js-style block JSON output.
12
- - Plain script tag integration with no build step required.
13
- - Paragraphs, headings, quotes, callouts, dividers, buttons, toggle blocks, raw HTML, links, embeds, tables, lists, and nested checklists.
14
- - Floating inline toolbar with typography, colors, highlight, alignment, comments, links, and formatting controls.
15
- - Multi-image upload, drag and drop, resize, crop, rotate, and gallery layout.
16
- - Attachment blocks for documents and videos.
17
- - Code block with formatting, syntax help, language detection, and suggestions.
18
- - Charts, LaTeX, audio, layout columns, code assistance, and optional history plugins in the free plugin set.
19
- - Premium plugins for Drawing, Mermaid, Signature, Signature Flow, and AI writing, delivered after server-side license verification.
20
- - Undo, redo, autosave, block actions, drag reordering, and optional JSON save/export buttons.
21
- - JSON-powered preview mounting for public document pages.
22
- - JSON save API examples for future database storage.
23
-
24
- ## Project Structure
25
-
26
- ```text
27
- BlockWriteAI/
28
- package.json
29
- composer.json
30
- pyproject.toml
31
- dist/
32
- blockwriteai.css
33
- blockwriteai.js
34
- blockwriteai-logo.svg
35
- blockwriteai-favicon.svg
36
- plugins/
37
- blockwriteai-advanced-blocks.js
38
- blockwriteai-drawing.js
39
- blockwriteai-mermaid.js
40
- blockwriteai-ai.js
41
- blockwriteai-code-assist.js
42
- blockwriteai-history.js
43
- blockwriteai-signature.js
44
- blockwriteai-signature-flow.js
45
- examples/
46
- index.html
47
- preview.html
48
- upload.php
49
- api/
50
- document.php
51
- preview.php
52
- uploads/
53
- .gitkeep
54
- blockwriteai_editor/
55
- static/blockwriteai/
56
- src/
57
- BlockWriteAIAssets.php
58
- types/
59
- index.d.ts
60
- ```
61
-
62
- ## Installation
63
-
64
- BlockWriteAI can be consumed as a CDN/script-link package, an npm package, a Python static-assets package, or a Composer package.
65
-
66
- ### Script Link
67
-
68
- Use the npm CDN for a locked release build:
1
+ # BlockWriteAI
69
2
 
70
- ```html
71
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@qarakash/blockwriteai@1.0.8/dist/blockwriteai.css">
3
+ BlockWriteAI is a JSON-first block editor for web apps. It works with a script tag, npm, PHP/Composer, and Python static-file workflows.
72
4
 
73
- <script src="https://cdn.jsdelivr.net/npm/@qarakash/blockwriteai@1.0.8/dist/blockwriteai.js"></script>
74
- <script src="https://cdn.jsdelivr.net/npm/@qarakash/blockwriteai@1.0.8/dist/plugins/blockwriteai-code-assist.js"></script>
75
- <script src="https://cdn.jsdelivr.net/npm/@qarakash/blockwriteai@1.0.8/dist/plugins/blockwriteai-advanced-blocks.js"></script>
76
- ```
5
+ Use the free core editor for normal documents. Serve premium tools such as AI, Mermaid, Drawing, Signature, and Signature Flow only through your licensed server endpoint.
77
6
 
78
- `blockwriteai-advanced-blocks.js` is the free advanced bundle. It includes Chart,
79
- LaTeX, Audio, and Columns/Layout. Drawing, Mermaid, Signature, Signature Flow,
80
- and AI are premium plugins and should not be loaded directly in production.
7
+ ## Quick Start With CDN
81
8
 
82
- Load History only when a project needs the history dropdown:
9
+ Add the stylesheet, editor script, and free plugin bundle:
83
10
 
84
11
  ```html
85
- <script src="https://cdn.jsdelivr.net/npm/@qarakash/blockwriteai@1.0.8/dist/plugins/blockwriteai-history.js"></script>
12
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@qarakash/blockwriteai@1.0.10/dist/blockwriteai.min.css">
13
+
14
+ <div id="editor"></div>
15
+
16
+ <script src="https://cdn.jsdelivr.net/npm/@qarakash/blockwriteai@1.0.10/dist/blockwriteai.min.js"></script>
17
+ <script src="https://cdn.jsdelivr.net/npm/@qarakash/blockwriteai@1.0.10/dist/plugins/blockwriteai-code-assist.min.js"></script>
18
+ <script src="https://cdn.jsdelivr.net/npm/@qarakash/blockwriteai@1.0.10/dist/plugins/blockwriteai-advanced-blocks.min.js"></script>
19
+ <script>
20
+ const editor = new BlockWriteAI({
21
+ holder: "#editor",
22
+ placeholder: "Write something, or press / for blocks",
23
+ async onSave(data) {
24
+ await fetch("/api/documents", {
25
+ method: "POST",
26
+ headers: { "Content-Type": "application/json" },
27
+ body: JSON.stringify(data)
28
+ });
29
+ }
30
+ });
31
+ </script>
86
32
  ```
87
33
 
88
- For development against the current GitHub branch, replace the npm URLs with the
89
- GitHub CDN form:
34
+ Use these CDN URLs for production:
35
+
36
+ ```text
37
+ https://cdn.jsdelivr.net/npm/@qarakash/blockwriteai@1.0.10/dist/blockwriteai.min.css
38
+ https://cdn.jsdelivr.net/npm/@qarakash/blockwriteai@1.0.10/dist/blockwriteai.min.js
39
+ https://cdn.jsdelivr.net/npm/@qarakash/blockwriteai@1.0.10/dist/plugins/blockwriteai-code-assist.min.js
40
+ https://cdn.jsdelivr.net/npm/@qarakash/blockwriteai@1.0.10/dist/plugins/blockwriteai-advanced-blocks.min.js
41
+ ```
42
+
43
+ Optional history plugin:
90
44
 
91
45
  ```html
92
- https://cdn.jsdelivr.net/gh/qarAkash/BlockWriteAI@main/dist/...
46
+ <script src="https://cdn.jsdelivr.net/npm/@qarakash/blockwriteai@1.0.10/dist/plugins/blockwriteai-history.min.js"></script>
93
47
  ```
94
48
 
95
- ### Premium License Gating
49
+ ## Install With Node
96
50
 
97
- Drawing, Mermaid drawing, Signature, Signature Flow, and AI can be licensed through
98
- the BlockWriteAI Platform. Normal editor blocks continue to work without a license.
99
- Premium plugin scripts are delivered only after the license endpoint returns an
100
- active trial or subscription. Without a valid license, those tools are not
101
- registered and do not appear in the insert-block menu.
51
+ ```bash
52
+ npm install @qarakash/blockwriteai
53
+ ```
102
54
 
103
55
  ```js
56
+ import BlockWriteAI from "@qarakash/blockwriteai";
57
+ import "@qarakash/blockwriteai/css";
58
+ import "@qarakash/blockwriteai/plugins/code-assist/min";
59
+ import "@qarakash/blockwriteai/plugins/advanced/min";
60
+
104
61
  const editor = new BlockWriteAI({
105
62
  holder: "#editor",
106
- premium: {
107
- licenseKey: "bwai_live_xxxxx",
108
- verifyEndpoint: "http://localhost/blockwriteai-platform/api/license_verify.php",
109
- pluginEndpoint: "http://localhost/blockwriteai-platform/api/premium_plugins.php",
110
- usageEndpoint: "http://localhost/blockwriteai-platform/api/ai_usage.php",
111
- autoLoadPlugins: true,
112
- features: ["drawing", "mermaid", "signature", "signature_flow", "ai"]
113
- },
114
- ai: {
115
- endpoint: "/api/ai.php"
63
+ async onSave(data) {
64
+ await fetch("/api/documents", {
65
+ method: "POST",
66
+ headers: { "Content-Type": "application/json" },
67
+ body: JSON.stringify(data)
68
+ });
116
69
  }
117
70
  });
118
71
  ```
119
72
 
120
- The verify endpoint must return a `features` object with these keys when enabled:
73
+ ## Install With PHP
121
74
 
122
- ```json
123
- {
124
- "drawing": true,
125
- "mermaid": true,
126
- "signature": true,
127
- "signature_flow": true,
128
- "ai": true
129
- }
75
+ ```bash
76
+ composer require qarakash/blockwriteai
130
77
  ```
131
78
 
132
- The AI plugin calls `premium.usageEndpoint` before each AI request so the
133
- platform can enforce the 7-day trial and daily prompt limits.
79
+ Publish the package `dist` assets into a public asset directory in your app, then print the tags:
80
+
81
+ ```php
82
+ <?php
83
+
84
+ use QarAkash\BlockWriteAI\BlockWriteAIAssets;
134
85
 
135
- For stronger production security, do not load premium plugin files directly from
136
- a public CDN. Load the free core first, request the premium plugins from your
137
- BlockWriteAI Platform, and create the editor only after the server has verified
138
- the license. The platform serves Drawing, Mermaid, Signature, Signature Flow,
139
- and AI as a verified bundle after checking the requested feature flags:
86
+ echo BlockWriteAIAssets::stylesheetTag('/assets/blockwriteai');
87
+ echo BlockWriteAIAssets::scriptTags('/assets/blockwriteai');
88
+ ```
89
+
90
+ Create the editor:
140
91
 
141
92
  ```html
142
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@qarakash/blockwriteai@1.0.8/dist/blockwriteai.css">
143
- <script src="https://cdn.jsdelivr.net/npm/@qarakash/blockwriteai@1.0.8/dist/blockwriteai.js"></script>
144
- <script src="https://cdn.jsdelivr.net/npm/@qarakash/blockwriteai@1.0.8/dist/plugins/blockwriteai-code-assist.js"></script>
145
- <script src="https://cdn.jsdelivr.net/npm/@qarakash/blockwriteai@1.0.8/dist/plugins/blockwriteai-advanced-blocks.js"></script>
93
+ <div id="editor"></div>
146
94
  <script>
147
- async function boot() {
148
- await BlockWriteAI.loadPremiumPlugins({
149
- licenseKey: "bwai_live_xxxxx",
150
- endpoint: "http://localhost/blockwriteai-platform/api/premium_plugins.php",
151
- features: ["drawing", "mermaid", "signature", "signature_flow", "ai"]
152
- });
153
-
154
- window.editor = new BlockWriteAI({
155
- holder: "#editor",
156
- premium: {
157
- licenseKey: "bwai_live_xxxxx",
158
- verifyEndpoint: "http://localhost/blockwriteai-platform/api/license_verify.php",
159
- usageEndpoint: "http://localhost/blockwriteai-platform/api/ai_usage.php"
160
- }
161
- });
162
- }
163
- boot();
95
+ const editor = new BlockWriteAI({
96
+ holder: "#editor",
97
+ async onSave(data) {
98
+ await fetch("/api/documents/save.php", {
99
+ method: "POST",
100
+ headers: { "Content-Type": "application/json" },
101
+ body: JSON.stringify(data)
102
+ });
103
+ }
104
+ });
164
105
  </script>
165
106
  ```
166
107
 
167
- This matters because browser-only locks can be edited in DevTools. Server-side
168
- license verification, usage metering, signature event storage, and verified
169
- premium bundle delivery are the enforceable parts.
170
-
171
- ### npm
172
-
173
- Package name:
174
-
175
- ```text
176
- @qarakash/blockwriteai
177
- ```
178
-
179
- Install:
180
-
181
- ```bash
182
- npm install @qarakash/blockwriteai
183
- ```
184
-
185
- Bundler entry points:
186
-
187
- ```js
188
- import BlockWriteAI from "@qarakash/blockwriteai";
189
- import "@qarakash/blockwriteai/css";
190
- import "@qarakash/blockwriteai/plugins/code-assist";
191
- import "@qarakash/blockwriteai/plugins/advanced";
192
- import "@qarakash/blockwriteai/plugins/history";
108
+ ## Install With Python
109
+
110
+ ```bash
111
+ pip install blockwriteai-editor
193
112
  ```
194
113
 
195
- After npm publishing, the same package is also available through npm CDNs:
114
+ Copy the packaged assets into your app static directory:
196
115
 
197
- ```html
198
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@qarakash/blockwriteai@1.0.8/dist/blockwriteai.css">
199
- <script src="https://cdn.jsdelivr.net/npm/@qarakash/blockwriteai@1.0.8/dist/blockwriteai.js"></script>
116
+ ```python
117
+ from blockwriteai_editor import copy_static
118
+
119
+ copy_static("static/blockwriteai")
200
120
  ```
201
-
202
- ### Python
203
-
204
- Package name:
205
-
206
- ```text
207
- blockwriteai-editor
208
- ```
209
-
210
- Install:
211
-
212
- ```bash
213
- pip install blockwriteai-editor
214
- ```
215
-
216
- Copy packaged static files into your Flask, Django, or any Python web app static directory:
217
-
218
- ```python
219
- from blockwriteai_editor import copy_static
220
-
221
- copy_static("static/blockwriteai")
222
- ```
223
-
224
- Python helpers are also available for generating asset tags. `script_tags()` loads
225
- only core/free plugins by default. Pass `history=True` only on pages where you want
226
- the optional History dropdown:
121
+
122
+ Generate tags in Flask, Django, or any Python web app:
227
123
 
228
124
  ```python
229
- from blockwriteai_editor import premium_script_tags, stylesheet_tag, script_tags
125
+ from blockwriteai_editor import stylesheet_tag, script_tags
230
126
 
231
127
  print(stylesheet_tag("/static/blockwriteai"))
232
128
  print(script_tags("/static/blockwriteai"))
233
- print(script_tags("/static/blockwriteai", history=True))
129
+ ```
234
130
 
235
- # Only for private/licensed deployments. Public apps should prefer the platform
236
- # premium bundle endpoint shown in the Premium License Gating section.
237
- print(premium_script_tags("/static/blockwriteai", ["signature", "ai"]))
131
+ Then mount the editor in your template:
132
+
133
+ ```html
134
+ <div id="editor"></div>
135
+ <script>
136
+ const editor = new BlockWriteAI({
137
+ holder: "#editor",
138
+ async onSave(data) {
139
+ await fetch("/api/documents", {
140
+ method: "POST",
141
+ headers: { "Content-Type": "application/json" },
142
+ body: JSON.stringify(data)
143
+ });
144
+ }
145
+ });
146
+ </script>
238
147
  ```
239
-
240
- ### PHP / Composer
241
-
242
- Package name:
243
-
244
- ```text
245
- qarakash/blockwriteai
246
- ```
247
-
248
- Install:
249
-
250
- ```bash
251
- composer require qarakash/blockwriteai
252
- ```
253
-
254
- Publish assets into your public folder:
255
-
256
- ```bash
257
- cp -R vendor/qarakash/blockwriteai/dist public/blockwriteai
258
- ```
259
-
260
- PHP helper. `scriptTags()` loads only core/free plugins by default. Pass
261
- `history: true` only on pages where you want the optional History dropdown:
262
148
 
263
- ```php
264
- use QarAkash\BlockWriteAI\BlockWriteAIAssets;
149
+ ## Read Saved Documents
265
150
 
266
- echo BlockWriteAIAssets::stylesheetTag('/blockwriteai');
267
- echo BlockWriteAIAssets::scriptTags('/blockwriteai');
268
- echo BlockWriteAIAssets::scriptTags('/blockwriteai', plugins: true, history: true);
151
+ BlockWriteAI saves JSON. Store that JSON in your database, then render it later with a preview container:
269
152
 
270
- // Only for private/licensed deployments. Public apps should prefer the platform
271
- // premium bundle endpoint shown in the Premium License Gating section.
272
- echo BlockWriteAIAssets::premiumScriptTags('/blockwriteai', ['signature', 'ai']);
273
- ```
274
-
275
- ## Local XAMPP Demo
276
-
277
- Copy the `BlockWriteAI` folder into your web root, for example:
278
-
279
- ```text
280
- C:\xampp\htdocs\BlockWriteAI
281
- ```
282
-
283
- Open:
284
-
285
- ```text
286
- http://localhost/BlockWriteAI/examples/
287
- ```
288
-
289
- ## Browser Usage
290
-
291
- ```html
292
- <link rel="stylesheet" href="/BlockWriteAI/dist/blockwriteai.css">
293
-
294
- <div id="editor"></div>
295
-
296
- <script src="/BlockWriteAI/dist/blockwriteai.js"></script>
297
- <script src="/BlockWriteAI/dist/plugins/blockwriteai-code-assist.js"></script>
298
- <script src="/BlockWriteAI/dist/plugins/blockwriteai-advanced-blocks.js"></script>
153
+ ```html
154
+ <link rel="stylesheet" href="/assets/blockwriteai/blockwriteai.min.css">
155
+
156
+ <div class="blockwriteai-preview" data-source="/api/documents/123.json"></div>
299
157
 
158
+ <script src="/assets/blockwriteai/blockwriteai.min.js"></script>
159
+ <script src="/assets/blockwriteai/plugins/blockwriteai-advanced-blocks.min.js"></script>
300
160
  <script>
301
- const editor = new BlockWriteAI({
302
- holder: "#editor",
303
- maxWidth: "960px", // optional; omit for full-width editor shell
304
- placeholder: "Write something, or press / for blocks",
305
- data: {
306
- blocks: [
307
- {
308
- type: "paragraph",
309
- data: {
310
- text: "Hello from BlockWriteAI",
311
- alignment: "left"
312
- }
313
- }
314
- ]
315
- },
316
- onChange(data) {
317
- console.log("Changed document", data);
318
- },
319
- async onSave(data) {
320
- await fetch("/save-document.php", {
321
- method: "POST",
322
- headers: {
323
- "Content-Type": "application/json"
324
- },
325
- body: JSON.stringify(data)
326
- });
327
- }
328
- });
161
+ BlockWriteAI.mountPreviews();
329
162
  </script>
330
163
  ```
331
164
 
332
- By default, BlockWriteAI mounts the full branded editor shell: logo, product subtitle,
333
- `Editor` heading, centered AI progress, and the right-aligned JSON sync status. If no
334
- `data` is provided, the editor starts with one empty paragraph block automatically. Use
335
- `shell: false` when you only want the raw editor surface, or pass `maxWidth: "960px"` /
336
- `shell: { maxWidth: "960px" }` to constrain the editor width in your project.
337
-
338
- Built-in toolbar buttons are intentionally opt-in for package consumers. `saveButton`, `exportButton`, and `exportHtmlButton` default to `false`, so applications can use their own UI and call `editor.save()` when needed.
339
-
340
- ## Saving JSON
341
-
342
- BlockWriteAI is designed to save JSON first. In production, store the JSON in your database and render it later in read-only mode or through exported HTML.
343
-
344
- ```js
345
- document.querySelector("#save").addEventListener("click", async () => {
346
- const data = await editor.save();
347
-
348
- await fetch("/save-document.php", {
349
- method: "POST",
350
- headers: {
351
- "Content-Type": "application/json"
352
- },
353
- body: JSON.stringify(data)
354
- });
355
- });
356
- ```
357
-
358
- The default toolbar includes a Save button. Use `onSave` to receive the JSON response when the user clicks it:
359
-
360
- ```js
361
- const editor = new BlockWriteAI({
362
- holder: "#editor",
363
- async onSave(data) {
364
- await fetch("/documents/123", {
365
- method: "POST",
366
- headers: {
367
- "Content-Type": "application/json"
368
- },
369
- body: JSON.stringify(data)
370
- });
371
- }
372
- });
373
- ```
374
-
375
- ## AI Plugin
376
-
377
- AI is a premium plugin. Load it through the platform premium bundle after license
378
- verification. The browser plugin never receives your OpenAI API key; it calls
379
- your own server endpoint.
165
+ The JSON endpoint can return a document directly:
380
166
 
381
- ```html
382
- <script src="/blockwriteai/blockwriteai.js"></script>
167
+ ```json
168
+ {
169
+ "time": 1779540000000,
170
+ "version": "1.0.10",
171
+ "blocks": []
172
+ }
173
+ ```
383
174
 
175
+ It can also return a wrapper:
176
+
177
+ ```json
178
+ {
179
+ "ok": true,
180
+ "data": {
181
+ "time": 1779540000000,
182
+ "version": "1.0.10",
183
+ "blocks": []
184
+ }
185
+ }
186
+ ```
187
+
188
+ ## Premium Plugins
189
+
190
+ Do not expose premium plugin files as normal public scripts. Load them after your server verifies an active license:
191
+
192
+ ```html
384
193
  <script>
385
- async function boot() {
194
+ async function bootEditor() {
386
195
  await BlockWriteAI.loadPremiumPlugins({
387
196
  licenseKey: "bwai_live_xxxxx",
388
197
  endpoint: "/blockwriteai-platform/api/premium_plugins.php",
389
- features: ["ai"]
198
+ features: ["drawing", "mermaid", "signature", "signature_flow", "ai"]
390
199
  });
391
200
 
392
201
  window.editor = new BlockWriteAI({
@@ -397,282 +206,29 @@ your own server endpoint.
397
206
  usageEndpoint: "/blockwriteai-platform/api/ai_usage.php"
398
207
  },
399
208
  ai: {
400
- endpoint: "/api/blockwriteai-ai.php"
209
+ endpoint: "/api/blockwriteai-ai"
401
210
  }
402
211
  });
403
212
  }
404
- boot();
405
- </script>
406
- ```
407
-
408
- The included demo endpoint is `examples/api/ai.php`. For local development, copy `examples/api/openai.local.example.php` to `examples/api/openai.local.php` and add a development key, or set `OPENAI_API_KEY` in the server environment. Do not expose the key in browser JavaScript.
409
-
410
- The drawer can also be opened without selecting text from the centered AI button in the editor toolbar, or programmatically with `editor.openAI()`.
411
-
412
- Available AI drawer actions:
413
-
414
- - Improve writing
415
- - Fix grammar
416
- - Summarize
417
- - Expand
418
- - Make professional
419
- - Generate BlockWriteAI blocks from a prompt
420
-
421
- ## Preview Pages
422
-
423
- Create any page in your application and add a preview container. BlockWriteAI will load saved JSON and render the document HTML inside that container.
424
-
425
- ```html
426
- <link rel="stylesheet" href="/blockwriteai/blockwriteai.css">
427
-
428
- <div class="blockwriteai-preview" data-source="/documents/123.json"></div>
429
-
430
- <script src="/blockwriteai/blockwriteai.js"></script>
431
- <script src="/blockwriteai/plugins/blockwriteai-advanced-blocks.js"></script>
432
- <script>
433
- BlockWriteAI.mountPreviews();
213
+
214
+ bootEditor();
434
215
  </script>
435
216
  ```
436
217
 
437
- If the preview page must render premium blocks, load the licensed premium bundle
438
- before `BlockWriteAI.mountPreviews()`:
218
+ The browser plugin must never receive private API keys. Keep OpenAI, billing, usage limits, and license checks on your server.
439
219
 
440
- ```js
441
- async function mountDocumentPreview() {
442
- await BlockWriteAI.loadPremiumPlugins({
443
- licenseKey: "bwai_live_xxxxx",
444
- endpoint: "/blockwriteai-platform/api/premium_plugins.php",
445
- features: ["drawing", "mermaid", "signature", "signature_flow", "ai"]
446
- });
447
- BlockWriteAI.mountPreviews();
448
- }
449
- mountDocumentPreview();
450
- ```
451
-
452
- The JSON endpoint can return either a BlockWriteAI document directly or an API wrapper such as:
453
-
454
- ```json
455
- {
456
- "ok": true,
457
- "data": {
458
- "time": 1779540000000,
459
- "version": "1.0.8",
460
- "blocks": []
461
- }
462
- }
463
- ```
464
-
465
- Example PHP receiver:
466
-
467
- ```php
468
- <?php
469
- header('Content-Type: application/json');
470
-
471
- $json = file_get_contents('php://input');
472
- $data = json_decode($json, true);
473
-
474
- if (!$data || !isset($data['blocks']) || !is_array($data['blocks'])) {
475
- http_response_code(422);
476
- echo json_encode(['error' => 'Invalid BlockWriteAI document']);
477
- exit;
478
- }
479
-
480
- file_put_contents(__DIR__ . '/saved-document.json', json_encode($data, JSON_PRETTY_PRINT));
481
-
482
- echo json_encode(['ok' => true]);
483
- ```
484
-
485
- ## Uploads
486
-
487
- The demo includes `examples/upload.php` and stores files under `examples/uploads/`. For production, replace this with your own storage layer.
488
-
489
- ```js
490
- const editor = new BlockWriteAI({
491
- holder: "#editor",
492
- uploadOutput: ["upload", "base64"],
493
- upload: {
494
- image: async (file) => {
495
- const form = new FormData();
496
- form.append("file", file);
497
- form.append("kind", "image");
498
-
499
- const response = await fetch("/BlockWriteAI/examples/upload.php", {
500
- method: "POST",
501
- body: form
502
- });
503
-
504
- return response.json();
505
- },
506
- file: async (file) => {
507
- const form = new FormData();
508
- form.append("file", file);
509
- form.append("kind", "file");
510
-
511
- const response = await fetch("/BlockWriteAI/examples/upload.php", {
512
- method: "POST",
513
- body: form
514
- });
515
-
516
- return response.json();
517
- }
518
- }
519
- });
520
- ```
220
+ ## Release Checklist
521
221
 
522
- `uploadOutput` controls what gets written into the saved JSON:
222
+ 1. Run `npm run build:min`.
223
+ 2. Run `npm run check`.
224
+ 3. Publish `@qarakash/blockwriteai` to npm.
225
+ 4. Publish `qarakash/blockwriteai` to Packagist.
226
+ 5. Publish `blockwriteai-editor` to PyPI.
227
+ 6. Serve only the public asset directory from your application.
523
228
 
524
- - `"base64"` or `["base64"]` stores uploaded media directly in the block JSON. This is the default.
525
- - `"upload"` or `["upload"]` stores the response from your upload handler, such as a server URL.
526
- - `["upload", "base64"]` stores both, useful when you want server files plus a portable JSON backup.
527
-
528
- Expected upload response:
529
-
530
- ```json
531
- {
532
- "url": "/BlockWriteAI/examples/uploads/example.pdf",
533
- "name": "example.pdf",
534
- "size": 12345,
535
- "type": "application/pdf"
536
- }
537
- ```
229
+ ## Notes For Production
538
230
 
539
- When both outputs are enabled, saved image and attachment items include the server response under `upload` and the inline file data under `base64`.
540
-
541
- ## API Methods
542
-
543
- ```js
544
- await editor.save(); // Get JSON document
545
- editor.getData(); // Get current data synchronously
546
- editor.render(data); // Replace editor content
547
- editor.clear(); // Reset editor
548
- editor.exportHTML(); // Export HTML
549
- editor.exportMarkdown(); // Export Markdown API, hidden from the default UI
550
- editor.importHTML(html); // Import HTML into blocks
551
- editor.setReadOnly(true); // Toggle read-only mode
552
- editor.undo(); // Undo last change
553
- editor.redo(); // Redo last undo
554
- editor.destroy(); // Remove editor instance
555
- BlockWriteAI.mountPreviews(); // Render JSON into .blockwriteai-preview containers
556
- ```
557
-
558
- ## Data Shape
559
-
560
- ```json
561
- {
562
- "time": 1779540000000,
563
- "version": "1.0.8",
564
- "blocks": [
565
- {
566
- "id": "block-title",
567
- "type": "heading",
568
- "data": {
569
- "level": 2,
570
- "text": "BlockWriteAI document",
571
- "alignment": "left"
572
- }
573
- },
574
- {
575
- "id": "block-body",
576
- "type": "paragraph",
577
- "data": {
578
- "text": "Reusable content saved as JSON."
579
- }
580
- }
581
- ]
582
- }
583
- ```
584
-
585
- ## Tool Control
586
-
587
- Limit available blocks per project:
588
-
589
- ```js
590
- const editor = new BlockWriteAI({
591
- holder: "#editor",
592
- tools: [
593
- "paragraph",
594
- "heading",
595
- "image",
596
- "list",
597
- "table"
598
- ]
599
- });
600
- ```
601
-
602
- Disable specific tools:
603
-
604
- ```js
605
- const editor = new BlockWriteAI({
606
- holder: "#editor",
607
- tools: {
608
- raw: false,
609
- attaches: false
610
- }
611
- });
612
- ```
613
-
614
- ## Autosave
615
-
616
- ```js
617
- const editor = new BlockWriteAI({
618
- holder: "#editor",
619
- autosave: {
620
- key: "blockwriteai-draft",
621
- load: true
622
- }
623
- });
624
- ```
625
-
626
- ## Security Notes
627
-
628
- BlockWriteAI sanitizes normal rich text blocks before saving and exporting. Raw HTML blocks are intentionally treated as trusted HTML, so enable the raw HTML tool only for trusted users.
629
-
630
- For production applications:
631
-
632
- - Validate JSON on the server.
633
- - Sanitize output again before public rendering.
634
- - Restrict upload types and file sizes.
635
- - Store uploaded files outside executable PHP paths when possible.
636
- - Add authentication before saving documents.
637
-
638
- ## GitHub
639
-
640
- Repository target:
641
-
642
- ```text
643
- https://github.com/qarAkash/BlockWriteAI.git
644
- ```
645
-
646
- ## Publishing Packages
647
-
648
- After a release is ready, publish each package from the repository root.
649
-
650
- Create a Git release tag for script-link/CDN users:
651
-
652
- ```bash
653
- git tag v1.0.8
654
- git push origin v1.0.8
655
- ```
656
-
657
- Publish npm:
658
-
659
- ```bash
660
- npm publish --access public
661
- ```
662
-
663
- Publish Python:
664
-
665
- ```bash
666
- python -m build
667
- python -m twine upload dist/*
668
- ```
669
-
670
- Publish Composer:
671
-
672
- ```text
673
- Submit https://github.com/qarAkash/BlockWriteAI to Packagist as qarakash/blockwriteai.
674
- ```
675
-
676
- ## Status
677
-
678
- BlockWriteAI is currently an active custom editor library and demo project. It is suitable for continued feature development, integration testing, and database-backed storage work.
231
+ - Use the `.min.css` and `.min.js` files in public pages.
232
+ - Do not publish source folders, examples, build artifacts, package caches, or private configuration files.
233
+ - Browser-delivered CSS and JavaScript can always be downloaded. Protect paid features with server-side license checks and metered premium bundle delivery.
234
+ - Keep secret keys in backend environment variables only.