@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.
- package/agent-skill.js +61 -89
- package/index.js +61 -0
- 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
};
|