@innovastudio/contentbuilder 1.1.7 → 1.1.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
@@ -80,6 +80,8 @@ React and Vue project examples are provided in separate downloads in the user ar
80
80
  - scss/ (Only provided in Source Code package)
81
81
  - docs/
82
82
  - README.md (Documentation)
83
+ - readme.txt (Readme file)
84
+ - readme-sourcecode.txt (Readme file for Source Code package)
83
85
  - ...
84
86
 
85
87
  ## Snippets
@@ -396,8 +398,6 @@ To try a working example, please open example2.php.
396
398
 
397
399
  #### 2. Using AJAX Post Method
398
400
 
399
- Example (using axios):
400
-
401
401
  ```javascript
402
402
  builder.saveImages('', ()=>{
403
403
 
@@ -408,15 +408,21 @@ builder.saveImages('', ()=>{
408
408
 
409
409
  }, (img, base64, filename)=>{
410
410
 
411
- // Upload image process
412
- axios.post('/upload', { image: base64, filename: filename }).then((response)=>{
413
-
414
- const uploadedImageUrl = response.data.url; // get saved image url
415
-
416
- img.setAttribute('src', uploadedImageUrl); // automatically replace base64 src with image url
417
-
418
- }).catch((err)=>{
419
- console.log(err)
411
+ // Upload base64 images
412
+ const reqBody = { image: base64, filename: filename };
413
+ fetch('/uploadbase64', {
414
+ method:'POST',
415
+ body: JSON.stringify(reqBody),
416
+ headers: {
417
+ 'Content-Type': 'application/json',
418
+ }
419
+ })
420
+ .then(response=>response.json())
421
+ .then(response=>{
422
+ if(!response.error) {
423
+ const uploadedImageUrl = response.url;
424
+ img.setAttribute('src', uploadedImageUrl); // Update image src
425
+ }
420
426
  });
421
427
 
422
428
  });
@@ -427,24 +433,65 @@ In this example, each image will be sent to an endpoint: /upload
427
433
  If you're using Node.js, you can implement the endpoint to save the images using:
428
434
 
429
435
  ```javascript
436
+ const express = require('express');
437
+ const fs = require('fs');
438
+ const app = express();
439
+ const path = require('path');
440
+ const cors = require('cors');
441
+ const serveStatic = require('serve-static');
442
+ const formidable = require('formidable-serverless');
443
+ const sharp = require('sharp');
444
+
430
445
  var $path = __dirname + '/public/uploads/'; // Physical path
431
446
  var $urlpath = 'uploads/'; // URL path
432
447
 
433
- app.post('/upload', (req, res) => {
448
+ app.use(cors());
449
+ app.use(express.urlencoded({
450
+ extended: true
451
+ }));
452
+ app.use(express.json({ limit: '50mb' }));
453
+ app.use(serveStatic(path.join(__dirname, '/public')));
454
+
455
+ app.post('/uploadbase64', async (req, res) => {
434
456
  const base64Data = req.body.image;
435
457
  const filename = req.body.filename;
436
- require("fs").writeFile($path + filename, base64Data, 'base64', ()=>{
437
- res.status(200).json({
438
- success: true,
439
- url: `${$urlpath}${filename}` // return saved image url
458
+
459
+ let extension = path.extname(filename).toLowerCase();
460
+
461
+ let imageFile=base64Data;
462
+ if(extension === '.jpeg' || extension === '.jpg') {
463
+ let img = new Buffer.from(base64Data, 'base64');
464
+ imageFile = await sharp(img).resize(1600, 1600, {
465
+ fit: sharp.fit.inside,
466
+ withoutEnlargement: true,
440
467
  })
468
+ .jpeg({ quality: 70, progressive: true, force: false })
469
+ .toBuffer();
470
+ }
471
+ fs.writeFile($path + filename, imageFile, 'base64', async (err)=>{
472
+ if (err) {
473
+ res.status(500).json({
474
+ ok:true, status: 500,
475
+ error: 'Something went wrong.'
476
+ });
477
+ return
478
+ }
479
+ res.status(200).json({
480
+ ok:true, status: 200,
481
+ url: $urlpath + filename
482
+ });
441
483
  });
442
484
  });
485
+
486
+ app.listen(8081, function() {
487
+ console.log('App running on port 8081');
488
+ });
443
489
  ```
444
490
 
445
491
  Example use of the AJAX post method can be seen on:
446
492
  - React Example (react-contentbuilder folder, please see src/components/contentbuilder/buildercontrol.jsx)
447
493
  - Vue Example (vue-contentbuilder folder, please see src/components/Editable.vue)
494
+ - src/index.js (in Source Code package)
448
495
 
449
496
  ### Configuration
450
497
 
@@ -548,38 +595,41 @@ Example:
548
595
 
549
596
  ```javascript
550
597
  const builder = new ContentBuilder({
551
- container: '.container',
552
- onMediaUpload: (e)=>{
553
-
554
- const selectedFile = e.target.files[0];
555
- const filename = selectedFile.name;
556
- const reader = new FileReader();
557
- reader.onload = (e) => {
558
- let base64 = e.target.result;
559
- base64 = base64.replace(/^data:(.*?);base64,/, "");
560
- base64 = base64.replace(/ /g, '+');
561
-
562
- // Upload process using axios (https://github.com/axios/axios)
563
- axios.post('upload/', { image: base64, filename: filename }).then((response)=>{
564
-
565
- const uploadedFileUrl = response.data.url; // get saved file url
566
- builder.returnUrl(uploadedFileUrl); // return the url
567
-
568
- }).catch((err)=>{
569
- console.log(err)
570
- });
571
- }
572
- reader.readAsDataURL(selectedFile);
573
-
574
- }
575
- });
598
+ container: '.container',
599
+ onMediaUpload: (e)=>{
600
+ uploadFile(e, (response)=>{
601
+ if(!response.error) {
602
+ const uploadedImageUrl = response.url;
603
+ if(uploadedImageUrl) obj.returnUrl(uploadedImageUrl);
604
+ }
605
+ });
606
+ }
607
+ });
608
+
609
+ function uploadFile(e, callback) {
610
+
611
+ const selectedFile = e.target.files[0];
612
+
613
+ const formData = new FormData();
614
+ formData.append('file', selectedFile);
615
+ fetch('/upload', {
616
+ method: 'POST',
617
+ body: formData,
618
+ })
619
+ .then(response=>response.json())
620
+ .then(response=>{
621
+ console.log(response)
622
+ if(callback) callback(response);
623
+ });
624
+ }
576
625
  ```
577
-
578
626
  The example above uses the **returnUrl(url)** method to apply the uploaded image url back to the image dialog. You can also use the **applyLargerImage** parameter (previous version) which is the same and still works.
627
+ In the example, file will be sent to an endpoint: /upload
579
628
 
580
629
  Working examples can be seen on the React & Vue examples:
581
630
  - React Example (react-contentbuilder folder, please see src/components/contentbuilder/buildercontrol.jsx)
582
631
  - Vue Example (vue-contentbuilder folder, please see src/components/Editable.vue)
632
+ - src/index.js (in Source Code package)
583
633
 
584
634
  ## Video Upload from the Video Dialog
585
635
 
@@ -622,31 +672,34 @@ Example:
622
672
 
623
673
  ```javascript
624
674
  const builder = new ContentBuilder({
625
- container: '.container',
626
- onVideoUpload: (e)=>{
627
-
628
- const selectedFile = e.target.files[0];
629
- const filename = selectedFile.name;
630
- const reader = new FileReader();
631
- reader.onload = (e) => {
632
- let base64 = e.target.result;
633
- base64 = base64.replace(/^data:(.*?);base64,/, "");
634
- base64 = base64.replace(/ /g, '+');
635
-
636
- // Upload process using axios (https://github.com/axios/axios)
637
- axios.post('upload/', { image: base64, filename: filename }).then((response)=>{
638
-
639
- const uploadedFileUrl = response.data.url; // get saved file url
640
- builder.returnUrl(uploadedFileUrl); // return the url
641
-
642
- }).catch((err)=>{
643
- console.log(err)
644
- });
645
- }
646
- reader.readAsDataURL(selectedFile);
647
-
648
- }
649
- });
675
+ container: '.container',
676
+ ...
677
+ onVideoUpload: (e)=>{
678
+ uploadFile(e, (response)=>{
679
+ if(!response.error) {
680
+ const uploadedFileUrl = response.url;
681
+ if(uploadedFileUrl) obj.returnUrl(uploadedFileUrl);
682
+ }
683
+ });
684
+ },
685
+ });
686
+
687
+ function uploadFile(e, callback) {
688
+
689
+ const selectedFile = e.target.files[0];
690
+
691
+ const formData = new FormData();
692
+ formData.append('file', selectedFile);
693
+ fetch('/upload', {
694
+ method: 'POST',
695
+ body: formData,
696
+ })
697
+ .then(response=>response.json())
698
+ .then(response=>{
699
+ console.log(response)
700
+ if(callback) callback(response);
701
+ });
702
+ }
650
703
  ```
651
704
 
652
705
  ## Plugins
@@ -658,7 +711,6 @@ With plugins, you can extend the ContentBuilder.js features. A plugin can add an
658
711
  Plugin scripts are located in the **plugins/** folder inside **contentbuilder/**.
659
712
 
660
713
  You will see the folder containing some prebuilt plugins:
661
- - contentbuilder/plugins/buttoneditor
662
714
  - contentbuilder/plugins/helloworld
663
715
  - contentbuilder/plugins/preview
664
716
  - contentbuilder/plugins/searchreplace
@@ -675,7 +727,6 @@ const builder = new ContentBuilder({
675
727
  { name: 'preview', showInMainToolbar: true, showInElementToolbar: true },
676
728
  { name: 'wordcount', showInMainToolbar: true, showInElementToolbar: true },
677
729
  { name: 'symbols', showInMainToolbar: true, showInElementToolbar: false },
678
- { name: 'buttoneditor', showInMainToolbar: false, showInElementToolbar: false },
679
730
  ],
680
731
  pluginPath: 'contentbuilder/',
681
732
  });
@@ -703,7 +754,9 @@ As seen in the example configuration above:
703
754
  ![Button Editor Plugin](docs/plugin-symbols1.png)
704
755
  Here the Symbol button is not displayed on the element editing toolbar:
705
756
  ![Button Editor Plugin](docs/plugin-symbols2.png)
706
- - The 'buttoneditor' plugin doesn't add a button on both the main editing toolbar and the alternate editing toolbar, so the **showInMainToolbar** is set to false, and the **showInElementToolbar** is set to false. This is because the plugin is only activated when the link button is clicked. There is no button on the toolbar. Instead, an edit (pencil) icon shows on top of the button.
757
+
758
+ In the previous version, there is a ‘buttoneditor’ plugin which shows an edit (pencil) icon when a link button is clicked. This plugin is now integrated with the builder, so no configuration is needed.
759
+
707
760
  ![Button Editor Plugin](docs/plugin-buttoneditor.png)
708
761
 
709
762
  An alternative way to load the plugins is by using a configuration file:
@@ -718,7 +771,6 @@ _cb.settings.plugins = [
718
771
  { name: 'preview', showInMainToolbar: true, showInElementToolbar: true },
719
772
  { name: 'wordcount', showInMainToolbar: true, showInElementToolbar: true },
720
773
  { name: 'symbols', showInMainToolbar: true, showInElementToolbar: false },
721
- { name: 'buttoneditor', showInMainToolbar: false, showInElementToolbar: false },
722
774
  ];
723
775
  ```
724
776
 
@@ -735,7 +787,7 @@ Note that using an external configuration file is an approach that comes from th
735
787
  In the previous version, the plugins parameter is configured like this:
736
788
 
737
789
  ```javascript
738
- ['preview','wordcount', 'buttoneditor']
790
+ ['preview','wordcount']
739
791
  ```
740
792
  This still works, however we recommend using the new approach (explained above) for future flexibility.
741
793
 
@@ -1028,7 +1080,7 @@ Specify the framework classes using the **row** & **cols** parameters.
1028
1080
 
1029
1081
  Example:
1030
1082
 
1031
- Bootstrap Framework:
1083
+ Bootstrap:
1032
1084
 
1033
1085
  ```javascript
1034
1086
  const builder = new ContentBuilder({
@@ -1038,7 +1090,7 @@ const builder = new ContentBuilder({
1038
1090
  });
1039
1091
  ```
1040
1092
 
1041
- Foundation Framework:
1093
+ Foundation:
1042
1094
 
1043
1095
  ```javascript
1044
1096
  const builder = new ContentBuilder({
@@ -1048,6 +1100,27 @@ const builder = new ContentBuilder({
1048
1100
  });
1049
1101
  ```
1050
1102
 
1103
+ Tailwind:
1104
+ ```javascript
1105
+ const builder = new ContentBuilder({
1106
+ container: '.container',
1107
+ row: 'flex flex-col md:flex-row',
1108
+ cols: [
1109
+ 'w-full md:w-1/12 px-4',
1110
+ 'w-full md:w-2/12 px-4',
1111
+ 'w-full md:w-3/12 px-4',
1112
+ 'w-full md:w-4/12 px-4',
1113
+ 'w-full md:w-5/12 px-4',
1114
+ 'w-full md:w-6/12 px-4',
1115
+ 'w-full md:w-7/12 px-4',
1116
+ 'w-full md:w-8/12 px-4',
1117
+ 'w-full md:w-9/12 px-4',
1118
+ 'w-full md:w-10/12 px-4',
1119
+ 'w-full md:w-11/12 px-4',
1120
+ 'w-full px-4'],
1121
+ });
1122
+ ```
1123
+
1051
1124
  #### 2. If the framework has grid system in which the column size increment is not constant
1052
1125
 
1053
1126
  Specify two additional parameters: **colequal** & **colsizes**
@@ -1114,6 +1187,7 @@ Note:
1114
1187
  - example1-purecss.html (Pure Css Example)
1115
1188
  - example1-skeleton.html (Skeleton Example)
1116
1189
  - example1-spectre.html (Spectre.css Example)
1190
+ - example1-tailwind (Tailwind Example)
1117
1191
  - example1-uikit.html (UIKit Example)
1118
1192
  - example1-w3css.html (W3.CSS Example)
1119
1193
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@innovastudio/contentbuilder",
3
- "version": "1.1.7",
3
+ "version": "1.1.8",
4
4
  "description": "",
5
5
  "main": "public/contentbuilder/contentbuilder.esm.js",
6
6
  "files": [
@@ -66271,6 +66271,34 @@ class ContentBuilder {
66271
66271
  leading_29: 'leading-29',
66272
66272
  leading_30: 'leading-30'
66273
66273
  },
66274
+ opacity: {
66275
+ opacity_0: 'opacity-0',
66276
+ opacity_2: 'opacity-2',
66277
+ opacity_4: 'opacity-4',
66278
+ opacity_5: 'opacity-5',
66279
+ opacity_6: 'opacity-6',
66280
+ opacity_8: 'opacity-8',
66281
+ opacity_10: 'opacity-10',
66282
+ opacity_12: 'opacity-12',
66283
+ opacity_15: 'opacity-15',
66284
+ opacity_20: 'opacity-20',
66285
+ opacity_25: 'opacity-25',
66286
+ opacity_30: 'opacity-30',
66287
+ opacity_35: 'opacity-35',
66288
+ opacity_40: 'opacity-40',
66289
+ opacity_45: 'opacity-45',
66290
+ opacity_50: 'opacity-50',
66291
+ opacity_55: 'opacity-55',
66292
+ opacity_60: 'opacity-60',
66293
+ opacity_65: 'opacity-65',
66294
+ opacity_70: 'opacity-70',
66295
+ opacity_75: 'opacity-75',
66296
+ opacity_80: 'opacity-80',
66297
+ opacity_85: 'opacity-85',
66298
+ opacity_90: 'opacity-90',
66299
+ opacity_95: 'opacity-95',
66300
+ opacity_100: 'opacity-100'
66301
+ },
66274
66302
  padding: {
66275
66303
  all: {
66276
66304
  p_0: 'p-0',