@saltcorn/bootstrap-prompt-theme 0.1.3 → 0.1.4

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 (3) hide show
  1. package/agent-skill.js +61 -89
  2. package/index.js +61 -0
  3. package/package.json +1 -1
package/agent-skill.js CHANGED
@@ -67,78 +67,9 @@ LAYOUT CONFIG: Besides CSS, you can control structural layout options via set_la
67
67
  - top_pad: 0–5 — Bootstrap spacing scale for top padding on page sections
68
68
  - in_card: true | false — wrap page body in a Bootstrap card
69
69
  Only call set_layout_config when you want to change structural layout, separate from CSS. Call both tools when a request requires both structural and CSS changes.
70
+ When you change menu_style, the tool response will include a page_structure field with rendered HTML of the new layout. Read it to understand the actual element hierarchy and CSS selectors before writing any CSS for that layout.
70
71
 
71
- PAGE STRUCTURE: A typical rendered Saltcorn page looks like this (abridged). Use it to understand element hierarchy, class names, and selectors when writing CSS:
72
- \`\`\`html
73
- <html lang="en" data-bs-theme="light">
74
- <head>
75
- <meta charset="utf-8">
76
- <meta name="viewport" content="width=device-width, initial-scale=1">
77
- <link href="/plugins/public/bootstrap-prompt-theme/bootstrap.min.css" rel="stylesheet">
78
- <link rel="stylesheet" href="/plugins/public/bootstrap-prompt-theme/sidebar-3.css">
79
- <link rel="stylesheet" href="/plugins/public/bootstrap-prompt-theme/overlay.css">
80
- <link href="/static_assets/.../saltcorn.css" rel="stylesheet">
81
- <script>var _sc_globalCsrf = "<csrf-token>", _sc_version_tag = "...", _sc_lightmode = "light";</script>
82
- </head>
83
- <body id="page-top" class="page_<pagename>">
84
- <div id="wrapper">
85
- <nav class="navbar d-print-none navbar-expand-md navbar-light bg-light" id="mainNav">
86
- <div class="container">
87
- <a class="navbar-brand" href="/">Saltcorn</a>
88
- <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarResponsive">
89
- <span class="navbar-toggler-icon"></span>
90
- </button>
91
- <div class="collapse navbar-collapse" id="navbarResponsive">
92
- <ul class="navbar-nav ms-auto my-2 my-lg-0">
93
- <li class="nav-item"><a class="nav-link" href="/table">Tables</a></li>
94
- <li class="nav-item dropdown">
95
- <a class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown">Settings</a>
96
- <div class="dropdown-menu">
97
- <a class="dropdown-item" href="/admin">About application</a>
98
- <a class="dropdown-item" href="/plugins">Modules</a>
99
- </div>
100
- </li>
101
- <li class="nav-item dropdown">
102
- <a class="nav-link dropdown-toggle user-nav-section" href="#" data-bs-toggle="dropdown">User</a>
103
- <div class="dropdown-menu dropdown-menu-end">
104
- <a class="dropdown-item" href="/auth/settings">User settings</a>
105
- <a class="dropdown-item" href="/auth/logout">Logout</a>
106
- </div>
107
- </li>
108
- </ul>
109
- </div>
110
- </div>
111
- </nav>
112
- <div id="page-inner-content">
113
- <section class="page-section pt-2">
114
- <div class="container">
115
- <!-- admin edit bar (admin only) -->
116
- <div class="card p-1 mt-1 mb-3 d-print-none admin-edit-bar">
117
- <div class="card-body p-1">...</div>
118
- </div>
119
- </div>
120
- </section>
121
- <section class="page-section">
122
- <div class="container">
123
- <!-- page content, e.g. a table view -->
124
- <div class="table-responsive">
125
- <table class="table table-sm table-valign-middle">
126
- <thead><tr><th>Email</th><th>Role</th></tr></thead>
127
- <tbody><tr><td>admin@foo.com</td><td>1</td></tr></tbody>
128
- </table>
129
- </div>
130
- </div>
131
- </section>
132
- <section class="page-section">
133
- <div class="container">
134
- <div id="toasts-area" class="toast-container position-fixed top-0 end-0 p-2" style="z-index: 9999;"></div>
135
- </div>
136
- </section>
137
- </div>
138
- </div>
139
- </body>
140
- </html>
141
- \`\`\`
72
+ {{PAGE_STRUCTURE}}
142
73
 
143
74
  WORKFLOW:
144
75
  1. Call apply_css_overlay with the complete CSS — this is the only way to deliver CSS.
@@ -203,6 +134,18 @@ const savePluginConfig = async (plugin, patch) => {
203
134
  });
204
135
  };
205
136
 
137
+ const renderStructureSkeleton = (config) => {
138
+ try {
139
+ return require(join(__dirname, "index.js")).renderStructureSkeleton(config);
140
+ } catch (e) {
141
+ getState().log(
142
+ 4,
143
+ `bootstrap-prompt-theme: renderStructureSkeleton failed: ${e.message}`
144
+ );
145
+ return null;
146
+ }
147
+ };
148
+
206
149
  class GenerateBootstrapThemeSkill {
207
150
  static skill_name = "Generate Bootstrap Theme";
208
151
 
@@ -218,8 +161,26 @@ class GenerateBootstrapThemeSkill {
218
161
  return [];
219
162
  }
220
163
 
221
- systemPrompt() {
222
- return SYSTEM_PROMPT;
164
+ async systemPrompt() {
165
+ const plugin = await findPlugin();
166
+ const config = plugin?.configuration || {};
167
+ let pageStructure =
168
+ "PAGE STRUCTURE: (unavailable — could not render current layout)";
169
+ try {
170
+ const { renderPageSkeleton } = require(join(__dirname, "index.js"));
171
+ const html = renderPageSkeleton(config);
172
+ if (html)
173
+ pageStructure =
174
+ "PAGE STRUCTURE: The current page renders like this (with a sample list view, based on the active layout config). Use it to understand element hierarchy, class names, and selectors when writing CSS:\n```html\n" +
175
+ html +
176
+ "\n```";
177
+ } catch (e) {
178
+ getState().log(
179
+ 4,
180
+ `bootstrap-prompt-theme: systemPrompt renderPageSkeleton failed: ${e.message}`
181
+ );
182
+ }
183
+ return SYSTEM_PROMPT.replace("{{PAGE_STRUCTURE}}", pageStructure);
223
184
  }
224
185
 
225
186
  provideTools() {
@@ -281,30 +242,41 @@ class GenerateBootstrapThemeSkill {
281
242
  return pre(code(entries));
282
243
  },
283
244
  process: async (params) => {
245
+ const allowed = [
246
+ "mode",
247
+ "menu_style",
248
+ "colorscheme",
249
+ "fixed_top",
250
+ "fluid",
251
+ "top_pad",
252
+ "in_card",
253
+ ];
254
+ const patch = Object.fromEntries(
255
+ Object.entries(params).filter(([k]) => allowed.includes(k))
256
+ );
284
257
  const plugin = await findPlugin();
285
258
  if (plugin) {
286
- const allowed = [
287
- "mode",
288
- "menu_style",
289
- "colorscheme",
290
- "fixed_top",
291
- "fluid",
292
- "top_pad",
293
- "in_card",
294
- ];
295
- const patch = Object.fromEntries(
296
- Object.entries(params).filter(([k]) => allowed.includes(k))
297
- );
298
259
  await savePluginConfig(plugin, patch);
299
260
  }
300
- return { success: true };
261
+ const result = { success: true };
262
+ if (params.menu_style) {
263
+ const mergedConfig = { ...(plugin?.configuration || {}), ...patch };
264
+ result.page_structure = renderStructureSkeleton(mergedConfig);
265
+ }
266
+ return result;
301
267
  },
302
- renderToolResponse: async () =>
303
- div({ class: "text-success" }, "Layout configuration updated."),
268
+ renderToolResponse: async ({ page_structure }) =>
269
+ div(
270
+ { class: "text-success" },
271
+ "Layout configuration updated.",
272
+ page_structure
273
+ ? pre({ class: "mt-2 small" }, code(page_structure))
274
+ : ""
275
+ ),
304
276
  function: {
305
277
  name: "set_layout_config",
306
278
  description:
307
- "Set structural layout configuration for the Saltcorn UI. Only pass the parameters you want to change.",
279
+ "Set structural layout configuration for the Saltcorn UI. Only pass the parameters you want to change. When menu_style is set, the tool response includes a page_structure field containing rendered HTML of the new layout — use it to understand the correct selectors before writing CSS.",
308
280
  parameters: {
309
281
  type: "object",
310
282
  properties: {
package/index.js CHANGED
@@ -928,6 +928,65 @@ document.addEventListener('DOMContentLoaded', () => {
928
928
  ],
929
929
  });
930
930
 
931
+ const FAKE_MENU = [
932
+ {
933
+ section: "Main",
934
+ items: [
935
+ { label: "Tables", link: "/table" },
936
+ { label: "Views", link: "/viewedit" },
937
+ { label: "Pages", link: "/pageedit" },
938
+ {
939
+ label: "Settings",
940
+ subitems: [
941
+ { label: "About application", link: "/admin" },
942
+ { label: "Modules", link: "/plugins" },
943
+ { label: "Users and security", link: "/useradmin" },
944
+ ],
945
+ },
946
+ {
947
+ label: "User",
948
+ subitems: [
949
+ { label: "User settings", link: "/auth/settings" },
950
+ { label: "Logout", link: "/auth/logout" },
951
+ ],
952
+ },
953
+ ],
954
+ },
955
+ ];
956
+
957
+ const FAKE_LIST_BODY =
958
+ '<section class="page-section pt-2"><div class="container">' +
959
+ '<div class="table-responsive"><table class="table table-sm table-valign-middle">' +
960
+ "<thead><tr>" +
961
+ '<th><span class="link-style">Email</span></th>' +
962
+ '<th class="text-align-right"><span class="link-style">Role</span></th>' +
963
+ "</tr></thead>" +
964
+ '<tbody><tr data-row-id="1"><td>admin@foo.com</td><td class="text-align-right">1</td></tr></tbody>' +
965
+ "</table></div>" +
966
+ "</div></section>";
967
+
968
+ const renderStructureSkeleton = (config) =>
969
+ menuWrap({
970
+ brand: { name: "Brand" },
971
+ menu: FAKE_MENU,
972
+ config,
973
+ currentUrl: "/",
974
+ originalUrl: "/",
975
+ body: '<section class="page-section pt-2"><div class="container"><p><!-- page content --></p></div></section>',
976
+ req: null,
977
+ });
978
+
979
+ const renderPageSkeleton = (config) =>
980
+ menuWrap({
981
+ brand: { name: "Brand" },
982
+ menu: FAKE_MENU,
983
+ config,
984
+ currentUrl: "/",
985
+ originalUrl: "/",
986
+ body: FAKE_LIST_BODY,
987
+ req: null,
988
+ });
989
+
931
990
  module.exports = {
932
991
  sc_plugin_api_version: 1,
933
992
  plugin_name: "bootstrap-prompt-theme",
@@ -980,4 +1039,6 @@ module.exports = {
980
1039
  }
981
1040
  },
982
1041
  ready_for_mobile: true,
1042
+ renderStructureSkeleton,
1043
+ renderPageSkeleton,
983
1044
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saltcorn/bootstrap-prompt-theme",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Bootstrap 5 layout plugin with LLM-generated CSS overlay",
5
5
  "main": "index.js",
6
6
  "scripts": {