jsgui3-server 0.0.143 → 0.0.145

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.
Files changed (67) hide show
  1. package/docs/comprehensive-documentation.md +25 -6
  2. package/docs/configuration-reference.md +46 -11
  3. package/docs/controls-development.md +54 -26
  4. package/docs/jsgui3-html-improvement-ideas.md +162 -0
  5. package/docs/jsgui3-html-improvement-ideas.svg +151 -0
  6. package/docs/troubleshooting.md +9 -8
  7. package/examples/controls/14d) window, canvas globe/EarthGlobeRenderer.js +19 -14
  8. package/examples/controls/14d) window, canvas globe/pipeline/TransformStage.js +5 -5
  9. package/examples/jsgui3-html/01) mvvm-counter/client.js +648 -0
  10. package/examples/jsgui3-html/01) mvvm-counter/server.js +21 -0
  11. package/examples/jsgui3-html/02) date-transform/client.js +764 -0
  12. package/examples/jsgui3-html/02) date-transform/server.js +21 -0
  13. package/examples/jsgui3-html/03) form-validation/client.js +1045 -0
  14. package/examples/jsgui3-html/03) form-validation/server.js +21 -0
  15. package/examples/jsgui3-html/04) data-grid/client.js +738 -0
  16. package/examples/jsgui3-html/04) data-grid/server.js +21 -0
  17. package/examples/jsgui3-html/05) master-detail/client.js +649 -0
  18. package/examples/jsgui3-html/05) master-detail/server.js +21 -0
  19. package/examples/jsgui3-html/06) theming/client.js +514 -0
  20. package/examples/jsgui3-html/06) theming/server.js +21 -0
  21. package/examples/jsgui3-html/07) mixins/client.js +465 -0
  22. package/examples/jsgui3-html/07) mixins/server.js +21 -0
  23. package/examples/jsgui3-html/08) router/client.js +372 -0
  24. package/examples/jsgui3-html/08) router/server.js +21 -0
  25. package/examples/jsgui3-html/09) resource-transform/client.js +692 -0
  26. package/examples/jsgui3-html/09) resource-transform/server.js +21 -0
  27. package/examples/jsgui3-html/10) binding-debugger/client.js +810 -0
  28. package/examples/jsgui3-html/10) binding-debugger/server.js +21 -0
  29. package/examples/jsgui3-html/README.md +48 -0
  30. package/http/responders/static/Static_Route_HTTP_Responder.js +25 -20
  31. package/lab/README.md +19 -0
  32. package/lab/experiments/window_examples_dom_audit.js +241 -0
  33. package/lab/results/window_examples_dom_audit.json +131 -0
  34. package/lab/results/window_examples_dom_audit.md +46 -0
  35. package/package.json +8 -3
  36. package/publishers/http-webpageorsite-publisher.js +8 -4
  37. package/resources/processors/bundlers/css-bundler.js +28 -173
  38. package/resources/processors/bundlers/js/esbuild/Advanced_JS_Bundler_Using_ESBuild.js +32 -20
  39. package/resources/processors/bundlers/style-bundler.js +288 -0
  40. package/resources/processors/compilers/SASS_Compiler.js +88 -0
  41. package/resources/processors/extractors/js/css_and_js/AST_Node/CSS_And_JS_From_JS_String_Using_AST_Node_Extractor.js +64 -68
  42. package/resources/website-css-resource.js +24 -20
  43. package/resources/website-javascript-resource-processor.js +17 -57
  44. package/resources/website-javascript-resource.js +17 -57
  45. package/serve-factory.js +38 -24
  46. package/server.js +116 -92
  47. package/tests/README.md +38 -3
  48. package/tests/bundlers.test.js +41 -32
  49. package/tests/content-analysis.test.js +19 -18
  50. package/tests/end-to-end.test.js +336 -365
  51. package/tests/error-handling.test.js +13 -11
  52. package/tests/examples-controls.e2e.test.js +13 -1
  53. package/tests/fixtures/end-to-end-client.js +54 -0
  54. package/tests/fixtures/jsgui3-html/binding_debugger_expectations.json +15 -0
  55. package/tests/fixtures/jsgui3-html/counter_expectations.json +31 -0
  56. package/tests/fixtures/jsgui3-html/data_grid_expectations.json +26 -0
  57. package/tests/fixtures/jsgui3-html/date_transform_expectations.json +26 -0
  58. package/tests/fixtures/jsgui3-html/form_validation_expectations.json +27 -0
  59. package/tests/fixtures/jsgui3-html/master_detail_expectations.json +15 -0
  60. package/tests/fixtures/jsgui3-html/mixins_expectations.json +10 -0
  61. package/tests/fixtures/jsgui3-html/resource_transform_expectations.json +11 -0
  62. package/tests/fixtures/jsgui3-html/router_expectations.json +10 -0
  63. package/tests/fixtures/jsgui3-html/theming_expectations.json +10 -0
  64. package/tests/jsgui3-html-examples.puppeteer.test.js +537 -0
  65. package/tests/sass-controls.e2e.test.js +327 -0
  66. package/tests/test-runner.js +4 -1
  67. package/tests/window-examples.puppeteer.test.js +455 -0
@@ -0,0 +1,88 @@
1
+ let sass_module;
2
+
3
+ const get_sass_module = () => {
4
+ if (!sass_module) {
5
+ try {
6
+ sass_module = require('sass');
7
+ } catch (err) {
8
+ const error = new Error('SASS compiler not available. Install "sass" to compile SCSS/SASS.');
9
+ error.cause = err;
10
+ throw error;
11
+ }
12
+ }
13
+ return sass_module;
14
+ };
15
+
16
+ const normalize_array = (value) => {
17
+ if (!value) return [];
18
+ return Array.isArray(value) ? value : [value];
19
+ };
20
+
21
+ const compile_string_with_sass = (source_string, options = {}) => {
22
+ if (!source_string || !source_string.trim()) {
23
+ return options.return_source_map ? {css: '', source_map: null} : '';
24
+ }
25
+
26
+ const sass = get_sass_module();
27
+ const load_paths = normalize_array(options.load_paths);
28
+ const output_style = options.output_style || 'expanded';
29
+ const quiet_dependencies = options.quiet_dependencies === true;
30
+
31
+ const compile_options = {
32
+ syntax: options.syntax,
33
+ loadPaths: load_paths,
34
+ style: output_style,
35
+ quietDeps: quiet_dependencies
36
+ };
37
+
38
+ if (options.source_map === true) {
39
+ compile_options.sourceMap = true;
40
+ compile_options.sourceMapIncludeSources = options.source_map_include_sources === true;
41
+ }
42
+
43
+ const compile_result = sass.compileString(source_string, compile_options);
44
+ const css_output = compile_result.css || '';
45
+
46
+ if (options.return_source_map) {
47
+ return {
48
+ css: css_output,
49
+ source_map: compile_result.sourceMap || null
50
+ };
51
+ }
52
+
53
+ return css_output;
54
+ };
55
+
56
+ class SASS_Compiler {
57
+ constructor(spec = {}) {
58
+ this.load_paths = normalize_array(spec.load_paths);
59
+ this.output_style = spec.output_style || 'expanded';
60
+ this.quiet_dependencies = spec.quiet_dependencies === true;
61
+ }
62
+
63
+ compile_scss_string(scss_string, options = {}) {
64
+ return compile_string_with_sass(scss_string, {
65
+ syntax: 'scss',
66
+ load_paths: options.load_paths || this.load_paths,
67
+ output_style: options.output_style || this.output_style,
68
+ quiet_dependencies: options.quiet_dependencies !== undefined ? options.quiet_dependencies : this.quiet_dependencies,
69
+ source_map: options.source_map,
70
+ source_map_include_sources: options.source_map_include_sources,
71
+ return_source_map: options.return_source_map === true
72
+ });
73
+ }
74
+
75
+ compile_sass_string(sass_string, options = {}) {
76
+ return compile_string_with_sass(sass_string, {
77
+ syntax: 'indented',
78
+ load_paths: options.load_paths || this.load_paths,
79
+ output_style: options.output_style || this.output_style,
80
+ quiet_dependencies: options.quiet_dependencies !== undefined ? options.quiet_dependencies : this.quiet_dependencies,
81
+ source_map: options.source_map,
82
+ source_map_include_sources: options.source_map_include_sources,
83
+ return_source_map: options.return_source_map === true
84
+ });
85
+ }
86
+ }
87
+
88
+ module.exports = SASS_Compiler;
@@ -3,8 +3,7 @@
3
3
  // Extract the CSS and JS from JS, using AST_Node.
4
4
  // AST_Node is part of jsgui3-server, possibly too slow though.
5
5
 
6
- const {obs, prom_or_cb} = require('fnl');
7
- const {tof, each} = require('jsgui3-html');
6
+ const {obs} = require('fnl');
8
7
 
9
8
 
10
9
  const JS_AST_Node = require('../../../../../jsbuilder/JS_AST/JS_AST_Node');
@@ -52,27 +51,21 @@ class CSS_And_JS_From_JS_String_Using_AST_Node_Extractor extends Extractor {
52
51
  // This part is kind-of slow.
53
52
 
54
53
  //console.log('pre create js ast node');
55
- console.log('Separating CSS and JS');
56
- const js_ast_node = JS_AST_Node.from_spec(spec);
57
- //console.log('post create js ast node');
58
-
59
- //const ae_nodes = [];
60
-
61
- const arr_pos_spans_css_js_nodes = []; // will remove them from the JS that's built / published.
62
-
63
-
64
-
65
-
66
- // Just assigning a template literal to .css?
67
- const css_ae_nodes = [];
68
-
69
- // How about removing those parts from the JS AST?
70
-
71
-
54
+ console.log('Separating styles and JS');
55
+ const js_ast_node = JS_AST_Node.from_spec(spec);
56
+ //console.log('post create js ast node');
57
+
58
+ //const ae_nodes = [];
59
+
60
+ const arr_pos_spans_style_js_nodes = []; // will remove them from the JS that's built / published.
61
+ const arr_css = [];
62
+ const arr_scss = [];
63
+ const arr_sass = [];
64
+ const arr_style_segments = [];
72
65
 
73
66
  js_ast_node.deep_iterate(node => {
74
67
 
75
- const {start, end} = node.babel;
68
+ const {start, end} = node.babel;
76
69
 
77
70
  // Maybe this part is slow? Don't think so though.
78
71
 
@@ -103,20 +96,29 @@ class CSS_And_JS_From_JS_String_Using_AST_Node_Extractor extends Extractor {
103
96
 
104
97
  //console.log('node_assigned_to', node_assigned_to);
105
98
 
106
- // the last ID being .css?
107
- const last_me_child = node_assigned_to.child_nodes[node_assigned_to.child_nodes.length - 1];
108
- //console.log('last_me_child', last_me_child);
109
- //console.log('last_me_child.source', last_me_child.source);
110
-
111
- if (last_me_child.source === 'css') {
112
- css_ae_nodes.push(node);
113
-
114
- //console.log('[start, end]', [start, end]);
115
- //console.log('node.source:\n' + node.source + '\n');
116
-
117
- arr_pos_spans_css_js_nodes.push([start, end]);
118
-
119
- }
99
+ // the last ID being .css / .scss / .sass?
100
+ const last_me_child = node_assigned_to.child_nodes[node_assigned_to.child_nodes.length - 1];
101
+ //console.log('last_me_child', last_me_child);
102
+ //console.log('last_me_child.source', last_me_child.source);
103
+
104
+ if (last_me_child.source === 'css' || last_me_child.source === 'scss' || last_me_child.source === 'sass') {
105
+ const tl_node = node_assigned.child_nodes[0];
106
+ const tl_source = tl_node ? tl_node.source : '';
107
+
108
+ const style_type = last_me_child.source;
109
+ if (style_type === 'css') arr_css.push(tl_source);
110
+ if (style_type === 'scss') arr_scss.push(tl_source);
111
+ if (style_type === 'sass') arr_sass.push(tl_source);
112
+
113
+ arr_style_segments.push({
114
+ type: style_type,
115
+ source: tl_source,
116
+ start,
117
+ end
118
+ });
119
+
120
+ arr_pos_spans_style_js_nodes.push([start, end]);
121
+ }
120
122
 
121
123
  // does it end '.css'?
122
124
  // break it down further?
@@ -137,39 +139,33 @@ class CSS_And_JS_From_JS_String_Using_AST_Node_Extractor extends Extractor {
137
139
  //console.log('ae_nodes', ae_nodes);
138
140
  //console.log('ae_nodes.length', ae_nodes.length);
139
141
  //console.log('css_ae_nodes.length', css_ae_nodes.length);
140
- console.log('arr_pos_spans_css_js_nodes.length', arr_pos_spans_css_js_nodes.length);
141
-
142
- const arr_css = [];
143
-
144
- if (css_ae_nodes.length > 0) {
145
- //console.log('css_ae_nodes', css_ae_nodes);
146
-
147
- each(css_ae_nodes, css_ae_node => {
148
- //console.log('css_ae_node.source', css_ae_node.source);
149
-
150
-
151
- const tl = css_ae_node.child_nodes[1].child_nodes[0];
152
-
153
-
154
- //console.log('tl', tl);
155
- //console.log('tl.source', tl.source);
156
- arr_css.push(tl.source);
157
-
158
-
159
- })
160
- }
161
-
162
- if (arr_css.length > 0) {
163
- const str_css = arr_css.join('\n');
164
- const str_js_without_css_assignments = pos_span_string_extractor.extract(js_str, arr_pos_spans_css_js_nodes, {invert: true});
165
- const res = {
166
- css: str_css,
167
- js: str_js_without_css_assignments
168
- }
169
- complete(res);
170
- } else {
171
- complete();
172
- }
142
+ console.log('arr_pos_spans_style_js_nodes.length', arr_pos_spans_style_js_nodes.length);
143
+
144
+ const str_css = arr_css.join('\n');
145
+ const str_scss = arr_scss.join('\n');
146
+ const str_sass = arr_sass.join('\n');
147
+
148
+ if (arr_pos_spans_style_js_nodes.length > 1) {
149
+ arr_pos_spans_style_js_nodes.sort((a, b) => a[0] - b[0]);
150
+ }
151
+
152
+ let style_segments = arr_style_segments;
153
+ if (style_segments.length > 1) {
154
+ style_segments.sort((a, b) => a.start - b.start);
155
+ }
156
+ style_segments = style_segments.map(({type, source}) => ({type, source}));
157
+
158
+ const str_js_without_style_assignments = arr_pos_spans_style_js_nodes.length > 0
159
+ ? pos_span_string_extractor.extract(js_str, arr_pos_spans_style_js_nodes, {invert: true})
160
+ : js_str;
161
+
162
+ complete({
163
+ css: str_css,
164
+ scss: str_scss,
165
+ sass: str_sass,
166
+ style_segments,
167
+ js: str_js_without_style_assignments
168
+ });
173
169
 
174
170
  const [stop, pause, resume] = [() => {}, () => {}, () => {}];
175
171
  return [stop, pause, resume];
@@ -188,4 +184,4 @@ class CSS_And_JS_From_JS_String_Using_AST_Node_Extractor extends Extractor {
188
184
 
189
185
  }
190
186
 
191
- module.exports = CSS_And_JS_From_JS_String_Using_AST_Node_Extractor;
187
+ module.exports = CSS_And_JS_From_JS_String_Using_AST_Node_Extractor;
@@ -27,7 +27,8 @@ var path = require('path'),
27
27
  Cookies = require('cookies'),
28
28
  fs2 = require('../fs2');
29
29
 
30
- const fnl = require('fnl');
30
+ const fnl = require('fnl');
31
+ const {compile_styles} = require('./processors/bundlers/style-bundler');
31
32
 
32
33
  var stringify = jsgui.stringify,
33
34
  each = jsgui.each,
@@ -54,24 +55,27 @@ const prom_or_cb = fnl.prom_or_cb;
54
55
 
55
56
  // and a map of all css text?
56
57
 
57
- const compile_controls_css = controls => {
58
- // go through all the controls, look for the .css property (on the class)
59
-
60
- //let res = '';
61
- const arr_css = [];
62
-
63
-
64
- each(controls, Ctrl => {
65
-
66
- const {css} = Ctrl;
67
- if (css) arr_css.push(css);
68
-
69
-
70
- });
71
- const str_css = arr_css.join('\n');
72
- return str_css;
73
-
74
- }
58
+ const compile_controls_css = controls => {
59
+ // go through all the controls, look for the .css/.scss/.sass property (on the class)
60
+
61
+ const arr_css = [];
62
+ const arr_scss = [];
63
+ const arr_sass = [];
64
+
65
+ each(controls, Ctrl => {
66
+ const {css, scss, sass} = Ctrl;
67
+ if (css) arr_css.push(css);
68
+ if (scss) arr_scss.push(scss);
69
+ if (sass) arr_sass.push(sass);
70
+ });
71
+
72
+ const style_bundle = compile_styles({
73
+ css: arr_css,
74
+ scss: arr_scss,
75
+ sass: arr_sass
76
+ });
77
+ return style_bundle.css || '';
78
+ }
75
79
 
76
80
 
77
81
 
@@ -409,4 +413,4 @@ Site_CSS.compile_controls_css = compile_controls_css;
409
413
 
410
414
 
411
415
  //});
412
- module.exports = Site_CSS;
416
+ module.exports = Site_CSS;
@@ -74,8 +74,12 @@ const babel = require('@babel/core');
74
74
  const stream_to_array = require('stream-to-array');
75
75
  const Resource_Processor = require('./website-resource-processor');
76
76
 
77
- const process_js = require('./process-js');
78
- const {analyse_js_doc_formatting, extract_client_js} = process_js;
77
+ const process_js = require('./process-js');
78
+ const {analyse_js_doc_formatting, extract_client_js} = process_js;
79
+
80
+ const CSS_And_JS_From_JS_String_Extractor = require('./processors/extractors/js/css_and_js/CSS_And_JS_From_JS_String_Extractor');
81
+ const {compile_styles} = require('./processors/bundlers/style-bundler');
82
+ const css_and_js_from_js_string_extractor = new CSS_And_JS_From_JS_String_Extractor();
79
83
 
80
84
 
81
85
 
@@ -660,60 +664,16 @@ class Site_JavaScript_Resource_Processor extends Resource_Processor {
660
664
  }
661
665
  */
662
666
 
663
- const filter_js_extract_control_css = (str_js_code) => {
664
- // res = [css, js_no_css]
665
- // Split the js lines.
666
-
667
- const s_js = str_js_code.split('\n');
668
- let within_class_css = false;
669
- const control_css_lines = [];
670
- const js_non_css_lines = [];
671
- // and the non-css lines.
672
- // And need to look for its stop.
673
- // And leave the first and last line out of the css.
674
- each(s_js, js_line => {
675
- let placed_js_line = false;
676
- const pos_class_css_begin = js_line.indexOf('.css = `');
677
- // if its 0
678
-
679
- if (pos_class_css_begin > -1) {
680
- //console.log('js_line', js_line);
681
- within_class_css = true;
682
- }
683
- // Put empty lines (back) into the js array?
684
-
685
- if (within_class_css) {
686
- //console.log('js_line', js_line);
687
-
688
- const pos_control_css_end = js_line.indexOf('`;');
689
- //console.log('pos_control_css_end', pos_control_css_end);
690
- if (pos_control_css_end > -1) {
691
- within_class_css = false;
692
- } else {
693
- if (pos_class_css_begin > -1) {
694
-
695
- } else {
696
- control_css_lines.push(js_line);
697
- }
698
-
699
- }
700
- } else {
701
- js_non_css_lines.push(js_line);
702
- placed_js_line = true;
703
- }
704
-
705
- if (!placed_js_line) {
706
- js_non_css_lines.push('');
707
- }
708
- //let is_control_css_start = js_line.indexOf()
709
-
710
- if (control_css_lines.length > 200) throw 'stop';
711
-
712
- })
713
- return [control_css_lines.join('\n'), js_non_css_lines.join('\n')];
714
- }
715
-
716
- let [str_css, str_js_no_css] = filter_js_extract_control_css(str_js_code);
667
+ const res_extract_styles = await css_and_js_from_js_string_extractor.extract(str_js_code);
668
+ let {
669
+ css = '',
670
+ scss = '',
671
+ sass = '',
672
+ style_segments = [],
673
+ js: str_js_no_css = str_js_code
674
+ } = res_extract_styles || {};
675
+ const style_bundle = compile_styles({css, scss, sass, style_segments}, options.style || {});
676
+ let str_css = style_bundle.css || '';
717
677
 
718
678
  // Add the sourcemaps back? Its working.
719
679
 
@@ -906,4 +866,4 @@ class Site_JavaScript_Resource_Processor extends Resource_Processor {
906
866
 
907
867
  }
908
868
 
909
- module.exports = Site_JavaScript_Resource_Processor;
869
+ module.exports = Site_JavaScript_Resource_Processor;
@@ -162,8 +162,12 @@ const babel = require('@babel/core');
162
162
  const stream_to_array = require('stream-to-array');
163
163
 
164
164
 
165
- const process_js = require('./process-js');
166
- const {analyse_js_doc_formatting, extract_client_js} = process_js;
165
+ const process_js = require('./process-js');
166
+ const {analyse_js_doc_formatting, extract_client_js} = process_js;
167
+
168
+ const CSS_And_JS_From_JS_String_Extractor = require('./processors/extractors/js/css_and_js/CSS_And_JS_From_JS_String_Extractor');
169
+ const {compile_styles} = require('./processors/bundlers/style-bundler');
170
+ const css_and_js_from_js_string_extractor = new CSS_And_JS_From_JS_String_Extractor();
167
171
 
168
172
 
169
173
  // A way of serving a file so that it includes custom code.
@@ -627,60 +631,16 @@ class Site_JavaScript extends Resource {
627
631
  }
628
632
  */
629
633
 
630
- const filter_js_extract_control_css = (str_js_code) => {
631
- // res = [css, js_no_css]
632
- // Split the js lines.
633
-
634
- const s_js = str_js_code.split('\n');
635
- let within_class_css = false;
636
- const control_css_lines = [];
637
- const js_non_css_lines = [];
638
- // and the non-css lines.
639
- // And need to look for its stop.
640
- // And leave the first and last line out of the css.
641
- each(s_js, js_line => {
642
- let placed_js_line = false;
643
- const pos_class_css_begin = js_line.indexOf('.css = `');
644
- // if its 0
645
-
646
- if (pos_class_css_begin > -1) {
647
- //console.log('js_line', js_line);
648
- within_class_css = true;
649
- }
650
- // Put empty lines (back) into the js array?
651
-
652
- if (within_class_css) {
653
- //console.log('js_line', js_line);
654
-
655
- const pos_control_css_end = js_line.indexOf('`;');
656
- //console.log('pos_control_css_end', pos_control_css_end);
657
- if (pos_control_css_end > -1) {
658
- within_class_css = false;
659
- } else {
660
- if (pos_class_css_begin > -1) {
661
-
662
- } else {
663
- control_css_lines.push(js_line);
664
- }
665
-
666
- }
667
- } else {
668
- js_non_css_lines.push(js_line);
669
- placed_js_line = true;
670
- }
671
-
672
- if (!placed_js_line) {
673
- js_non_css_lines.push('');
674
- }
675
- //let is_control_css_start = js_line.indexOf()
676
-
677
- if (control_css_lines.length > 200) throw 'stop';
678
-
679
- })
680
- return [control_css_lines.join('\n'), js_non_css_lines.join('\n')];
681
- }
682
-
683
- let [str_css, str_js_no_css] = filter_js_extract_control_css(str_js_code);
634
+ const res_extract_styles = await css_and_js_from_js_string_extractor.extract(str_js_code);
635
+ let {
636
+ css = '',
637
+ scss = '',
638
+ sass = '',
639
+ style_segments = [],
640
+ js: str_js_no_css = str_js_code
641
+ } = res_extract_styles || {};
642
+ const style_bundle = compile_styles({css, scss, sass, style_segments}, options.style || {});
643
+ let str_css = style_bundle.css || '';
684
644
 
685
645
  // Add the sourcemaps back? Its working.
686
646
 
@@ -872,4 +832,4 @@ class Site_JavaScript extends Resource {
872
832
 
873
833
  }
874
834
 
875
- module.exports = Site_JavaScript;
835
+ module.exports = Site_JavaScript;
package/serve-factory.js CHANGED
@@ -12,9 +12,9 @@ const Static_Route_HTTP_Responder = require('./http/responders/static/Static_Rou
12
12
  const { get_port_or_free } = require('./port-utils');
13
13
 
14
14
 
15
- const prepare_webpage_route = (server, route, page_options = {}, defaults = {}) => {
16
- return new Promise((resolve, reject) => {
17
- try {
15
+ const prepare_webpage_route = (server, route, page_options = {}, defaults = {}) => {
16
+ return new Promise((resolve, reject) => {
17
+ try {
18
18
  const {
19
19
  title,
20
20
  name,
@@ -34,11 +34,13 @@ const prepare_webpage_route = (server, route, page_options = {}, defaults = {})
34
34
  path: route
35
35
  });
36
36
 
37
- const publisher_options = {
38
- webpage
39
- };
40
- if (guessed_client_path) publisher_options.src_path_client_js = guessed_client_path;
41
- if (truthy(defaults.debug)) publisher_options.debug = true;
37
+ const publisher_options = {
38
+ webpage
39
+ };
40
+ if (guessed_client_path) publisher_options.src_path_client_js = guessed_client_path;
41
+ if (truthy(defaults.debug)) publisher_options.debug = true;
42
+ if (defaults.style !== undefined) publisher_options.style = defaults.style;
43
+ if (defaults.bundler !== undefined) publisher_options.bundler = defaults.bundler;
42
44
 
43
45
  const webpage_publisher = new HTTP_Webpage_Publisher(publisher_options);
44
46
  webpage_publisher.on('ready', (bundle) => {
@@ -138,13 +140,21 @@ module.exports = (Server) => {
138
140
  throw new Error('Invalid port specified for Server.serve');
139
141
  }
140
142
 
141
- const host = serve_options.host || process.env.HOST || null;
142
- const debug_enabled = serve_options.debug !== undefined ? truthy(serve_options.debug) : truthy(process.env.JSGUI_DEBUG);
143
+ const host = serve_options.host || process.env.HOST || null;
144
+ const debug_enabled = serve_options.debug !== undefined ? truthy(serve_options.debug) : truthy(process.env.JSGUI_DEBUG);
145
+ const style_config = serve_options.style;
146
+ const bundler_config = serve_options.bundler;
143
147
 
144
- const server_spec = {
145
- name: serve_options.name || 'jsgui3 server',
146
- debug: debug_enabled
147
- };
148
+ const server_spec = {
149
+ name: serve_options.name || 'jsgui3 server',
150
+ debug: debug_enabled
151
+ };
152
+ if (style_config !== undefined) {
153
+ server_spec.style = style_config;
154
+ }
155
+ if (bundler_config !== undefined) {
156
+ server_spec.bundler = bundler_config;
157
+ }
148
158
  if (typeof serve_options.ctrl === 'function') {
149
159
  server_spec.Ctrl = serve_options.ctrl;
150
160
  } else if (serve_options.api && typeof serve_options.api === 'object') {
@@ -173,16 +183,20 @@ module.exports = (Server) => {
173
183
 
174
184
  let has_started = false;
175
185
 
176
- const extra_page_promises = additional_pages.map(([route, cfg]) => prepare_webpage_route(server_instance, route, cfg, {
177
- caller_dir,
178
- debug: debug_enabled
179
- }));
180
- if (serve_options.page_config && serve_options.page_route && serve_options.page_route !== '/') {
181
- extra_page_promises.unshift(prepare_webpage_route(server_instance, serve_options.page_route, serve_options.page_config, {
182
- caller_dir,
183
- debug: debug_enabled
184
- }));
185
- }
186
+ const extra_page_promises = additional_pages.map(([route, cfg]) => prepare_webpage_route(server_instance, route, cfg, {
187
+ caller_dir,
188
+ debug: debug_enabled,
189
+ style: style_config,
190
+ bundler: bundler_config
191
+ }));
192
+ if (serve_options.page_config && serve_options.page_route && serve_options.page_route !== '/') {
193
+ extra_page_promises.unshift(prepare_webpage_route(server_instance, serve_options.page_route, serve_options.page_config, {
194
+ caller_dir,
195
+ debug: debug_enabled,
196
+ style: style_config,
197
+ bundler: bundler_config
198
+ }));
199
+ }
186
200
 
187
201
  if (serve_options.api && typeof serve_options.api === 'object') {
188
202
  console.log('🔍 DEBUG: Setting up API routes');