@saltcorn/markup 0.6.2-beta.2 → 0.6.2
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/dist/builder.d.ts +18 -0
- package/dist/builder.d.ts.map +1 -0
- package/dist/builder.js +57 -0
- package/dist/builder.js.map +1 -0
- package/dist/emergency_layout.d.ts +6 -0
- package/dist/emergency_layout.d.ts.map +1 -0
- package/dist/emergency_layout.js +38 -0
- package/dist/emergency_layout.js.map +1 -0
- package/dist/form.d.ts +12 -0
- package/dist/form.d.ts.map +1 -0
- package/dist/form.js +372 -0
- package/dist/form.js.map +1 -0
- package/dist/helpers.d.ts +58 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/helpers.js +169 -0
- package/dist/helpers.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +158 -0
- package/dist/index.js.map +1 -0
- package/dist/layout.d.ts +22 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +338 -0
- package/dist/layout.js.map +1 -0
- package/dist/layout_utils.d.ts +21 -0
- package/dist/layout_utils.d.ts.map +1 -0
- package/dist/layout_utils.js +272 -0
- package/dist/layout_utils.js.map +1 -0
- package/dist/mktag.d.ts +12 -0
- package/dist/mktag.d.ts.map +1 -0
- package/dist/mktag.js +100 -0
- package/dist/mktag.js.map +1 -0
- package/dist/table.d.ts +22 -0
- package/dist/table.d.ts.map +1 -0
- package/dist/table.js +51 -0
- package/dist/table.js.map +1 -0
- package/dist/tabs.d.ts +7 -0
- package/dist/tabs.d.ts.map +1 -0
- package/dist/tabs.js +34 -0
- package/dist/tabs.js.map +1 -0
- package/dist/tags.d.ts +17 -0
- package/dist/tags.d.ts.map +1 -0
- package/dist/tags.js +71 -0
- package/dist/tags.js.map +1 -0
- package/dist/tsconfig.ref.tsbuildinfo +1 -0
- package/package.json +25 -6
- package/builder.js +0 -101
- package/emergency_layout.js +0 -54
- package/form.js +0 -603
- package/form.test.js +0 -98
- package/helpers.js +0 -268
- package/index.js +0 -226
- package/layout.js +0 -590
- package/layout.test.js +0 -39
- package/layout_utils.js +0 -394
- package/markup.test.js +0 -104
- package/mktag.js +0 -105
- package/table.js +0 -115
- package/tabs.js +0 -54
- package/tags.js +0 -56
package/layout_utils.js
DELETED
|
@@ -1,394 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @category saltcorn-markup
|
|
3
|
-
* @module layout_utils
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const {
|
|
7
|
-
ul,
|
|
8
|
-
li,
|
|
9
|
-
ol,
|
|
10
|
-
a,
|
|
11
|
-
span,
|
|
12
|
-
hr,
|
|
13
|
-
div,
|
|
14
|
-
text,
|
|
15
|
-
img,
|
|
16
|
-
button,
|
|
17
|
-
nav,
|
|
18
|
-
script,
|
|
19
|
-
domReady,
|
|
20
|
-
footer,
|
|
21
|
-
i,
|
|
22
|
-
small,
|
|
23
|
-
br,
|
|
24
|
-
} = require("./tags");
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* @param {string} item
|
|
28
|
-
* @returns {string}
|
|
29
|
-
*/
|
|
30
|
-
const labelToId = (item) => text(item.replace(" ", ""));
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* @param {string} currentUrl
|
|
34
|
-
* @param {object} item
|
|
35
|
-
* @returns {boolean}
|
|
36
|
-
*/
|
|
37
|
-
const active = (currentUrl, item) =>
|
|
38
|
-
(item.link && currentUrl.startsWith(item.link)) ||
|
|
39
|
-
(item.subitems &&
|
|
40
|
-
item.subitems.some((si) => si.link && currentUrl.startsWith(si.link)));
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* @param {object[]} sections
|
|
44
|
-
* @returns {object[]}
|
|
45
|
-
*/
|
|
46
|
-
const innerSections = (sections) => {
|
|
47
|
-
var items = [];
|
|
48
|
-
(sections || []).forEach((section) => {
|
|
49
|
-
(section.items || []).forEach((item) => {
|
|
50
|
-
items.push(item);
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
return items;
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* @param {object} opts
|
|
58
|
-
* @param {string} opts.label
|
|
59
|
-
* @param {object[]} opts.subitems
|
|
60
|
-
* @param {string} [opts.icon]
|
|
61
|
-
* @param {boolean} opts.isUser
|
|
62
|
-
* @returns {li}
|
|
63
|
-
*/
|
|
64
|
-
const navSubitems = ({ label, subitems, icon, isUser }) =>
|
|
65
|
-
li(
|
|
66
|
-
{ class: "nav-item dropdown" },
|
|
67
|
-
a(
|
|
68
|
-
{
|
|
69
|
-
class: "nav-link dropdown-toggle",
|
|
70
|
-
href: "#",
|
|
71
|
-
id: `dropdown${labelToId(label)}`,
|
|
72
|
-
role: "button",
|
|
73
|
-
"data-toggle": "dropdown",
|
|
74
|
-
"aria-haspopup": "true",
|
|
75
|
-
"aria-expanded": "false",
|
|
76
|
-
},
|
|
77
|
-
icon ? i({ class: `fa-fw mr-05 ${icon}` }) : "",
|
|
78
|
-
label
|
|
79
|
-
),
|
|
80
|
-
div(
|
|
81
|
-
{
|
|
82
|
-
class: ["dropdown-menu", isUser && "dropdown-menu-right"],
|
|
83
|
-
"aria-labelledby": `dropdown${labelToId(label)}`,
|
|
84
|
-
},
|
|
85
|
-
subitems.map((si) =>
|
|
86
|
-
a(
|
|
87
|
-
{ class: ["dropdown-item", si.style || ""], href: si.link },
|
|
88
|
-
si.icon ? i({ class: `fa-fw mr-05 ${si.icon}` }) : "",
|
|
89
|
-
si.label
|
|
90
|
-
)
|
|
91
|
-
)
|
|
92
|
-
)
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* @param {string} currentUrl
|
|
97
|
-
* @param {object[]} sections
|
|
98
|
-
* @returns {div}
|
|
99
|
-
*/
|
|
100
|
-
const rightNavBar = (currentUrl, sections) =>
|
|
101
|
-
div(
|
|
102
|
-
{ class: "collapse navbar-collapse", id: "navbarResponsive" },
|
|
103
|
-
ul(
|
|
104
|
-
{ class: "navbar-nav ml-auto my-2 my-lg-0" },
|
|
105
|
-
|
|
106
|
-
innerSections(sections).map((s) =>
|
|
107
|
-
s.location === "Mobile Bottom"
|
|
108
|
-
? ""
|
|
109
|
-
: s.subitems
|
|
110
|
-
? navSubitems(s)
|
|
111
|
-
: s.link
|
|
112
|
-
? li(
|
|
113
|
-
{
|
|
114
|
-
class: ["nav-item", active(currentUrl, s) && "active"],
|
|
115
|
-
},
|
|
116
|
-
a(
|
|
117
|
-
{
|
|
118
|
-
class: ["nav-link js-scroll-trigger", s.style || ""],
|
|
119
|
-
href: text(s.link),
|
|
120
|
-
},
|
|
121
|
-
s.icon ? i({ class: `fa-fw mr-05 ${s.icon}` }) : "",
|
|
122
|
-
text(s.label)
|
|
123
|
-
)
|
|
124
|
-
)
|
|
125
|
-
: ""
|
|
126
|
-
)
|
|
127
|
-
)
|
|
128
|
-
);
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* @param {object[]} sections
|
|
132
|
-
* @returns {boolean}
|
|
133
|
-
*/
|
|
134
|
-
const hasMobileItems = (sections) =>
|
|
135
|
-
innerSections(sections).some((s) => s.location === "Mobile Bottom");
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* @param {string} currentUrl
|
|
139
|
-
* @param {object[]} sections
|
|
140
|
-
* @param {string} [cls = ""]
|
|
141
|
-
* @param {string} [clsLink = ""]
|
|
142
|
-
* @returns {footer|string}
|
|
143
|
-
*/
|
|
144
|
-
const mobileBottomNavBar = (currentUrl, sections, cls = "", clsLink = "") =>
|
|
145
|
-
hasMobileItems(sections)
|
|
146
|
-
? footer(
|
|
147
|
-
{
|
|
148
|
-
class:
|
|
149
|
-
"bs-mobile-nav-footer d-flex justify-content-around d-sm-flex d-md-none " +
|
|
150
|
-
cls,
|
|
151
|
-
},
|
|
152
|
-
innerSections(sections).map((s) =>
|
|
153
|
-
s.location !== "Mobile Bottom"
|
|
154
|
-
? ""
|
|
155
|
-
: //: s.subitems
|
|
156
|
-
//? navSubitems(s)
|
|
157
|
-
s.link
|
|
158
|
-
? div(
|
|
159
|
-
{
|
|
160
|
-
class: [
|
|
161
|
-
"mt-2 text-center",
|
|
162
|
-
active(currentUrl, s) ? "active" : "opacity-50",
|
|
163
|
-
],
|
|
164
|
-
},
|
|
165
|
-
a(
|
|
166
|
-
{
|
|
167
|
-
class: [s.style || "", clsLink],
|
|
168
|
-
href: text(s.link),
|
|
169
|
-
},
|
|
170
|
-
s.icon ? i({ class: `fa-lg ${s.icon}` }) : "",
|
|
171
|
-
br(),
|
|
172
|
-
small(text(s.label))
|
|
173
|
-
)
|
|
174
|
-
)
|
|
175
|
-
: ""
|
|
176
|
-
)
|
|
177
|
-
)
|
|
178
|
-
: "";
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* @param {object} opts
|
|
182
|
-
* @param {string} opts.name
|
|
183
|
-
* @param {string} opts.logo
|
|
184
|
-
* @returns {string[]}
|
|
185
|
-
*/
|
|
186
|
-
const leftNavBar = ({ name, logo }) => [
|
|
187
|
-
a(
|
|
188
|
-
{ class: "navbar-brand js-scroll-trigger", href: "/" },
|
|
189
|
-
logo &&
|
|
190
|
-
img({
|
|
191
|
-
src: logo,
|
|
192
|
-
width: "30",
|
|
193
|
-
height: "30",
|
|
194
|
-
class: "mx-1 d-inline-block align-top",
|
|
195
|
-
alt: "Logo",
|
|
196
|
-
loading: "lazy",
|
|
197
|
-
}),
|
|
198
|
-
name
|
|
199
|
-
),
|
|
200
|
-
button(
|
|
201
|
-
{
|
|
202
|
-
class: "navbar-toggler navbar-toggler-right",
|
|
203
|
-
type: "button",
|
|
204
|
-
"data-toggle": "collapse",
|
|
205
|
-
"data-target": "#navbarResponsive",
|
|
206
|
-
"aria-controls": "navbarResponsive",
|
|
207
|
-
"aria-expanded": "false",
|
|
208
|
-
"aria-label": "Toggle navigation",
|
|
209
|
-
},
|
|
210
|
-
span({ class: "navbar-toggler-icon" })
|
|
211
|
-
),
|
|
212
|
-
];
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* @param {object} brand
|
|
216
|
-
* @param {object[]} sections
|
|
217
|
-
* @param {string} currentUrl
|
|
218
|
-
* @param {object} opts
|
|
219
|
-
* @param {boolean} [opts.fixedTop = true]
|
|
220
|
-
* @returns {string}
|
|
221
|
-
*/
|
|
222
|
-
const navbar = (brand, sections, currentUrl, opts = { fixedTop: true }) =>
|
|
223
|
-
nav(
|
|
224
|
-
{
|
|
225
|
-
class: `navbar navbar-expand-md ${opts.class || ""} ${
|
|
226
|
-
opts.colorscheme ? opts.colorscheme.toLowerCase() : "navbar-light"
|
|
227
|
-
} ${opts.fixedTop ? "fixed-top" : ""}`,
|
|
228
|
-
id: "mainNav",
|
|
229
|
-
},
|
|
230
|
-
div(
|
|
231
|
-
{ class: opts.fluid ? "container-fluid" : "container" },
|
|
232
|
-
leftNavBar(brand),
|
|
233
|
-
rightNavBar(currentUrl, sections)
|
|
234
|
-
)
|
|
235
|
-
);
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* @param {string} type
|
|
239
|
-
* @param {string} s
|
|
240
|
-
* @returns {string}
|
|
241
|
-
*/
|
|
242
|
-
const alert = (type, s) => {
|
|
243
|
-
//console.log("alert", type, s,s.length)
|
|
244
|
-
const realtype = type === "error" ? "danger" : type;
|
|
245
|
-
return s && s.length > 0
|
|
246
|
-
? `<div class="alert alert-${realtype} alert-dismissible fade show" role="alert">
|
|
247
|
-
${text(s)}
|
|
248
|
-
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
|
249
|
-
<span aria-hidden="true">×</span>
|
|
250
|
-
</button>
|
|
251
|
-
</div>`
|
|
252
|
-
: "";
|
|
253
|
-
};
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* @returns {string}
|
|
257
|
-
*/
|
|
258
|
-
const navbarSolidOnScroll = script(
|
|
259
|
-
domReady(`$(window).scroll(function () {
|
|
260
|
-
if ($(window).scrollTop() >= 10) {
|
|
261
|
-
$('.navbar').css('background','white');
|
|
262
|
-
} else {
|
|
263
|
-
$('.navbar').css('background','transparent');
|
|
264
|
-
}
|
|
265
|
-
});`)
|
|
266
|
-
);
|
|
267
|
-
|
|
268
|
-
/**
|
|
269
|
-
* @param {object} x
|
|
270
|
-
* @param {object} s
|
|
271
|
-
* @returns {object}
|
|
272
|
-
*/
|
|
273
|
-
const logit = (x, s) => {
|
|
274
|
-
if (s) console.log(s, x);
|
|
275
|
-
else console.log(x);
|
|
276
|
-
return x;
|
|
277
|
-
};
|
|
278
|
-
|
|
279
|
-
/**
|
|
280
|
-
* @param {number} len
|
|
281
|
-
* @returns {function}
|
|
282
|
-
*/
|
|
283
|
-
const standardBreadcrumbItem = (len) => ({ href, text }, ix) =>
|
|
284
|
-
li(
|
|
285
|
-
{
|
|
286
|
-
class: ["breadcrumb-item", ix == len - 1 && "active"],
|
|
287
|
-
"aria-current": ix == len - 1 && "page",
|
|
288
|
-
},
|
|
289
|
-
href ? a({ href }, text) : text
|
|
290
|
-
);
|
|
291
|
-
|
|
292
|
-
/**
|
|
293
|
-
* @param {object} opts
|
|
294
|
-
* @param {Workflow} opts.workflow
|
|
295
|
-
* @param {object} opts.step
|
|
296
|
-
* @returns {string}
|
|
297
|
-
*/
|
|
298
|
-
const workflowBreadcrumbItem = ({ workflow, step }) =>
|
|
299
|
-
workflow.steps
|
|
300
|
-
.map((wfstep, ix) =>
|
|
301
|
-
li(
|
|
302
|
-
{
|
|
303
|
-
class: [
|
|
304
|
-
"breadcrumb-item breadcrumb-workflow",
|
|
305
|
-
step.currentStep - 1 === ix && "active-step font-weight-bold",
|
|
306
|
-
],
|
|
307
|
-
},
|
|
308
|
-
span(wfstep.name)
|
|
309
|
-
)
|
|
310
|
-
)
|
|
311
|
-
.join("");
|
|
312
|
-
|
|
313
|
-
/**
|
|
314
|
-
* @param {object[]} crumbs
|
|
315
|
-
* @returns {string}
|
|
316
|
-
*/
|
|
317
|
-
const breadcrumbs = (crumbs) =>
|
|
318
|
-
nav(
|
|
319
|
-
{ "aria-label": "breadcrumb" },
|
|
320
|
-
ol(
|
|
321
|
-
{ class: "breadcrumb" },
|
|
322
|
-
crumbs.map((c) =>
|
|
323
|
-
c.workflow
|
|
324
|
-
? workflowBreadcrumbItem(c)
|
|
325
|
-
: standardBreadcrumbItem(crumbs.length)(c)
|
|
326
|
-
)
|
|
327
|
-
)
|
|
328
|
-
);
|
|
329
|
-
|
|
330
|
-
/**
|
|
331
|
-
* @param {object[]} headers
|
|
332
|
-
* @returns {string}
|
|
333
|
-
*/
|
|
334
|
-
const headersInHead = (headers) =>
|
|
335
|
-
headers
|
|
336
|
-
.filter((h) => h.css)
|
|
337
|
-
.map((h) => `<link href="${h.css}" rel="stylesheet">`)
|
|
338
|
-
.join("") +
|
|
339
|
-
headers
|
|
340
|
-
.filter((h) => h.style)
|
|
341
|
-
.map((h) => `<style>${h.style}</style>`)
|
|
342
|
-
.join("") +
|
|
343
|
-
headers
|
|
344
|
-
.filter((h) => h.headerTag)
|
|
345
|
-
.map((h) => h.headerTag)
|
|
346
|
-
.join("");
|
|
347
|
-
|
|
348
|
-
/**
|
|
349
|
-
* @param {object[]} headers
|
|
350
|
-
* @returns {string}
|
|
351
|
-
*/
|
|
352
|
-
const headersInBody = (headers) =>
|
|
353
|
-
headers
|
|
354
|
-
.filter((h) => h.script)
|
|
355
|
-
.map(
|
|
356
|
-
(h) =>
|
|
357
|
-
`<script src="${h.script}" ${
|
|
358
|
-
h.integrity
|
|
359
|
-
? `integrity="${h.integrity}" crossorigin="anonymous"`
|
|
360
|
-
: ""
|
|
361
|
-
}></script>`
|
|
362
|
-
)
|
|
363
|
-
.join("") +
|
|
364
|
-
headers
|
|
365
|
-
.filter((h) => h.scriptBody)
|
|
366
|
-
.map((h) => `<script>${h.scriptBody}</script>`)
|
|
367
|
-
.join("");
|
|
368
|
-
|
|
369
|
-
/**
|
|
370
|
-
* @param {object[]} tabList
|
|
371
|
-
* @returns {ul}
|
|
372
|
-
*/
|
|
373
|
-
const cardHeaderTabs = (tabList) =>
|
|
374
|
-
ul(
|
|
375
|
-
{ class: "nav nav-tabs card-header-tabs" },
|
|
376
|
-
tabList.map(({ href, label, active }) =>
|
|
377
|
-
li(
|
|
378
|
-
{ class: "nav-item" },
|
|
379
|
-
a({ class: ["nav-link", active && "active"], href }, label)
|
|
380
|
-
)
|
|
381
|
-
)
|
|
382
|
-
);
|
|
383
|
-
|
|
384
|
-
module.exports = {
|
|
385
|
-
navbar,
|
|
386
|
-
alert,
|
|
387
|
-
logit,
|
|
388
|
-
navbarSolidOnScroll,
|
|
389
|
-
breadcrumbs,
|
|
390
|
-
headersInHead,
|
|
391
|
-
headersInBody,
|
|
392
|
-
cardHeaderTabs,
|
|
393
|
-
mobileBottomNavBar,
|
|
394
|
-
};
|
package/markup.test.js
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
const {
|
|
2
|
-
a,
|
|
3
|
-
input,
|
|
4
|
-
div,
|
|
5
|
-
ul,
|
|
6
|
-
text,
|
|
7
|
-
text_attr,
|
|
8
|
-
i,
|
|
9
|
-
hr,
|
|
10
|
-
genericElement,
|
|
11
|
-
} = require("./tags");
|
|
12
|
-
|
|
13
|
-
describe("tags", () => {
|
|
14
|
-
it("renders", () => {
|
|
15
|
-
expect(a({ href: "/" }, "Home")).toBe('<a href="/">Home</a>');
|
|
16
|
-
expect(a({ href: "/" }, ["Home", " Sweet", " Home"])).toBe(
|
|
17
|
-
'<a href="/">Home Sweet Home</a>'
|
|
18
|
-
);
|
|
19
|
-
expect(a({ href: "/", class: "centre" }, "Home")).toBe(
|
|
20
|
-
'<a href="/" class="centre">Home</a>'
|
|
21
|
-
);
|
|
22
|
-
expect(input({ type: "text" })).toBe('<input type="text">');
|
|
23
|
-
expect(div(5)).toBe("<div>5</div>");
|
|
24
|
-
expect(div()).toBe("<div></div>");
|
|
25
|
-
expect(i()).toBe("<i></i>");
|
|
26
|
-
expect(hr()).toBe("<hr>");
|
|
27
|
-
expect(div(["hello ", "world"])).toBe("<div>hello world</div>");
|
|
28
|
-
expect(ul({ class: "foo" }, [false, "hello ", "world"])).toBe(
|
|
29
|
-
`<ul class="foo">hello world</ul>`
|
|
30
|
-
);
|
|
31
|
-
expect(ul({ class: "foo" }, [["hello ", "world"]])).toBe(
|
|
32
|
-
`<ul class="foo">hello world</ul>`
|
|
33
|
-
);
|
|
34
|
-
expect(Array.isArray(["hello ", "world"])).toBe(true);
|
|
35
|
-
expect(Array.isArray({})).toBe(false);
|
|
36
|
-
expect(i({ class: "fas fa-plus-square" })).toBe(
|
|
37
|
-
'<i class="fas fa-plus-square"></i>'
|
|
38
|
-
);
|
|
39
|
-
expect(genericElement("div", { class: "foo" }, "Hello")).toBe(
|
|
40
|
-
'<div class="foo">Hello</div>'
|
|
41
|
-
);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it("class", () => {
|
|
45
|
-
expect(div({ class: "foo" }, 5)).toBe('<div class="foo">5</div>');
|
|
46
|
-
expect(div({ class: false }, 5)).toBe("<div>5</div>");
|
|
47
|
-
expect(div({ class: "foo bar" }, 5)).toBe('<div class="foo bar">5</div>');
|
|
48
|
-
expect(div({ class: ["foo", "bar"] }, 5)).toBe(
|
|
49
|
-
'<div class="foo bar">5</div>'
|
|
50
|
-
);
|
|
51
|
-
expect(div({ class: ["foo", " "] }, 5)).toBe('<div class="foo ">5</div>');
|
|
52
|
-
expect(input({ class: ["foo", " "] })).toBe('<input class="foo ">');
|
|
53
|
-
|
|
54
|
-
expect(
|
|
55
|
-
div({ class: ["foo bar", "", undefined, null, false, "baz"] }, 5)
|
|
56
|
-
).toBe('<div class="foo bar baz">5</div>');
|
|
57
|
-
|
|
58
|
-
expect(div({ class: [undefined, null, false] }, 5)).toBe("<div>5</div>");
|
|
59
|
-
expect(hr({ class: "foo" })).toBe('<hr class="foo">');
|
|
60
|
-
});
|
|
61
|
-
it("style", () => {
|
|
62
|
-
expect(div({ style: "color:red;border:1px solid black" }, 5)).toBe(
|
|
63
|
-
'<div style="color:red;border:1px solid black">5</div>'
|
|
64
|
-
);
|
|
65
|
-
expect(div({ style: ["color:red", "border:1px solid black"] }, 5)).toBe(
|
|
66
|
-
'<div style="color:red;border:1px solid black">5</div>'
|
|
67
|
-
);
|
|
68
|
-
expect(
|
|
69
|
-
div(
|
|
70
|
-
{ style: ["color:red", false, undefined, "border:1px solid black"] },
|
|
71
|
-
5
|
|
72
|
-
)
|
|
73
|
-
).toBe('<div style="color:red;border:1px solid black">5</div>');
|
|
74
|
-
expect(div({ style: { color: "red", border: "1px solid black" } }, 5)).toBe(
|
|
75
|
-
'<div style="color:red;border:1px solid black">5</div>'
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
expect(
|
|
79
|
-
div({ style: { marginRight: "1px", border: "1px solid black" } }, 5)
|
|
80
|
-
).toBe('<div style="margin-right:1px;border:1px solid black">5</div>');
|
|
81
|
-
//border-top-left-radius
|
|
82
|
-
expect(
|
|
83
|
-
div({ style: { marginRight: "1px", borderTopLeftRadius: "3px" } }, 5)
|
|
84
|
-
).toBe('<div style="margin-right:1px;border-top-left-radius:3px">5</div>');
|
|
85
|
-
expect(hr({ style: { color: "red" } }, 5)).toBe('<hr style="color:red">');
|
|
86
|
-
expect(hr({ style: {} })).toBe("<hr>");
|
|
87
|
-
expect(hr({ style: null })).toBe("<hr>");
|
|
88
|
-
expect(div({ class: "foo", style: null })).toBe('<div class="foo"></div>');
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it("escaping", () => {
|
|
92
|
-
expect(text("foo")).toBe("foo");
|
|
93
|
-
expect(text_attr('" onMouseOver="alert(1);')).toBe(
|
|
94
|
-
"" onMouseOver="alert(1);"
|
|
95
|
-
);
|
|
96
|
-
expect(text(1)).toBe("1");
|
|
97
|
-
expect(text(0)).toBe("0");
|
|
98
|
-
expect(text("<script>alert(1);<script>")).toBe(
|
|
99
|
-
"<script>alert(1);<script>"
|
|
100
|
-
);
|
|
101
|
-
expect(text("<p>alert<p>")).toBe("<p>alert<p>");
|
|
102
|
-
expect(text("<kbd>ctrl<kbd>")).toBe("<kbd>ctrl<kbd>");
|
|
103
|
-
});
|
|
104
|
-
});
|
package/mktag.js
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @category saltcorn-markup
|
|
3
|
-
* @module mktag
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
//https://stackoverflow.com/a/54246501
|
|
7
|
-
/**
|
|
8
|
-
* @param {string} str
|
|
9
|
-
* @returns {string}
|
|
10
|
-
*/
|
|
11
|
-
const camelToCssCase = (str) =>
|
|
12
|
-
str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* @param {string|object} cs
|
|
16
|
-
* @returns {string}
|
|
17
|
-
*/
|
|
18
|
-
const ppClasses = (cs) =>
|
|
19
|
-
typeof cs === "string" ? cs : !cs ? "" : cs.filter((c) => c).join(" ");
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @param {string|object} c
|
|
23
|
-
* @returns {string}
|
|
24
|
-
*/
|
|
25
|
-
const ppClass = (c) => {
|
|
26
|
-
const clss = ppClasses(c);
|
|
27
|
-
return clss ? `class="${clss}"` : "";
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* @param {string|string[]|object} [cs]
|
|
32
|
-
* @returns {string}
|
|
33
|
-
*/
|
|
34
|
-
const ppStyles = (cs) =>
|
|
35
|
-
typeof cs === "string"
|
|
36
|
-
? cs
|
|
37
|
-
: !cs
|
|
38
|
-
? ""
|
|
39
|
-
: Array.isArray(cs)
|
|
40
|
-
? cs.filter((c) => c).join(";")
|
|
41
|
-
: typeof cs === "object"
|
|
42
|
-
? Object.entries(cs)
|
|
43
|
-
.map(([k, v]) => `${camelToCssCase(k)}:${v}`)
|
|
44
|
-
.join(";")
|
|
45
|
-
: "";
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* @param {string|string[]|object} [cs]
|
|
49
|
-
* @returns {string}
|
|
50
|
-
*/
|
|
51
|
-
const ppStyle = (c) => {
|
|
52
|
-
const clss = ppStyles(c);
|
|
53
|
-
return clss ? `style="${clss}"` : "";
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* @param {object[]} opts
|
|
58
|
-
* @param {string} opts.k
|
|
59
|
-
* @param {boolean} [opts.v]
|
|
60
|
-
* @returns {string}
|
|
61
|
-
*/
|
|
62
|
-
const ppAttrib = ([k, v]) =>
|
|
63
|
-
typeof v === "boolean"
|
|
64
|
-
? v
|
|
65
|
-
? k
|
|
66
|
-
: ""
|
|
67
|
-
: typeof v === "undefined"
|
|
68
|
-
? ""
|
|
69
|
-
: k === "class"
|
|
70
|
-
? ppClass(v)
|
|
71
|
-
: k === "style"
|
|
72
|
-
? ppStyle(v)
|
|
73
|
-
: `${k}="${v}"`;
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* @param {string} tnm
|
|
77
|
-
* @param {boolean} voidTag
|
|
78
|
-
* @returns {function}
|
|
79
|
-
*/
|
|
80
|
-
const mkTag = (tnm, voidTag) => (...args) => {
|
|
81
|
-
var body = "";
|
|
82
|
-
var attribs = " ";
|
|
83
|
-
|
|
84
|
-
const argIter = (arg) => {
|
|
85
|
-
if (typeof arg === "undefined" || arg === null || arg === false) {
|
|
86
|
-
//do nothing
|
|
87
|
-
} else if (typeof arg === "string") {
|
|
88
|
-
body += arg;
|
|
89
|
-
} else if (typeof arg === "object") {
|
|
90
|
-
if (Array.isArray(arg)) {
|
|
91
|
-
arg.forEach(argIter);
|
|
92
|
-
} else {
|
|
93
|
-
attribs += Object.entries(arg)
|
|
94
|
-
.map(ppAttrib)
|
|
95
|
-
.filter((s) => s)
|
|
96
|
-
.join(" ");
|
|
97
|
-
}
|
|
98
|
-
} else body += arg;
|
|
99
|
-
};
|
|
100
|
-
args.forEach(argIter);
|
|
101
|
-
if (attribs === " ") attribs = "";
|
|
102
|
-
return voidTag ? `<${tnm}${attribs}>` : `<${tnm}${attribs}>${body}</${tnm}>`;
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
module.exports = mkTag;
|
package/table.js
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @category saltcorn-markup
|
|
3
|
-
* @module table
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const { contract, is } = require("contractis");
|
|
7
|
-
|
|
8
|
-
const {
|
|
9
|
-
a,
|
|
10
|
-
td,
|
|
11
|
-
tr,
|
|
12
|
-
th,
|
|
13
|
-
text,
|
|
14
|
-
div,
|
|
15
|
-
table,
|
|
16
|
-
thead,
|
|
17
|
-
tbody,
|
|
18
|
-
ul,
|
|
19
|
-
li,
|
|
20
|
-
span,
|
|
21
|
-
} = require("./tags");
|
|
22
|
-
const { pagination } = require("./helpers");
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* @param {object} hdr
|
|
26
|
-
* @returns {th}
|
|
27
|
-
*/
|
|
28
|
-
const headerCell = (hdr) =>
|
|
29
|
-
th(
|
|
30
|
-
(hdr.align || hdr.width) && {
|
|
31
|
-
style:
|
|
32
|
-
(hdr.align ? `text-align: ` + hdr.align : "") +
|
|
33
|
-
(hdr.width ? `width: ` + hdr.width : ""),
|
|
34
|
-
},
|
|
35
|
-
hdr.sortlink ? a({ href: hdr.sortlink }, hdr.label) : hdr.label
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* @function
|
|
40
|
-
* @param {object[]} hdrs
|
|
41
|
-
* @param {object[]} vs
|
|
42
|
-
* @param {object} [opts]
|
|
43
|
-
* @returns {string}
|
|
44
|
-
*/
|
|
45
|
-
const mkTable = contract(
|
|
46
|
-
is.fun(
|
|
47
|
-
[
|
|
48
|
-
is.array(is.obj({ label: is.str, key: is.or(is.str, is.fun()) })),
|
|
49
|
-
is.array(is.obj()),
|
|
50
|
-
is.maybe(
|
|
51
|
-
is.obj({
|
|
52
|
-
pagination: is.maybe(
|
|
53
|
-
is.obj({
|
|
54
|
-
current_page: is.posint,
|
|
55
|
-
pages: is.posint,
|
|
56
|
-
get_page_link: is.fun(),
|
|
57
|
-
})
|
|
58
|
-
),
|
|
59
|
-
noHeader: is.maybe(is.bool),
|
|
60
|
-
hover: is.maybe(is.bool),
|
|
61
|
-
})
|
|
62
|
-
),
|
|
63
|
-
],
|
|
64
|
-
is.str
|
|
65
|
-
),
|
|
66
|
-
(hdrs, vs, opts = {}) =>
|
|
67
|
-
div(
|
|
68
|
-
{ class: "table-responsive" },
|
|
69
|
-
table(
|
|
70
|
-
{
|
|
71
|
-
class: [
|
|
72
|
-
"table table-sm",
|
|
73
|
-
opts.class,
|
|
74
|
-
hdrs.some((h) => h.width) && "table-layout-fixed",
|
|
75
|
-
(opts.onRowSelect || (opts.hover && vs && vs.length > 1)) &&
|
|
76
|
-
"table-hover",
|
|
77
|
-
],
|
|
78
|
-
style: opts.style,
|
|
79
|
-
},
|
|
80
|
-
!opts.noHeader && thead(tr(hdrs.map((hdr) => headerCell(hdr)))),
|
|
81
|
-
tbody(
|
|
82
|
-
(vs || []).map((v) =>
|
|
83
|
-
tr(
|
|
84
|
-
mkClickHandler(opts, v),
|
|
85
|
-
hdrs.map((hdr) =>
|
|
86
|
-
td(
|
|
87
|
-
!!hdr.align && { style: "text-align:" + hdr.align },
|
|
88
|
-
typeof hdr.key === "string" ? text(v[hdr.key]) : hdr.key(v)
|
|
89
|
-
)
|
|
90
|
-
)
|
|
91
|
-
)
|
|
92
|
-
)
|
|
93
|
-
)
|
|
94
|
-
),
|
|
95
|
-
opts.pagination && pagination(opts.pagination)
|
|
96
|
-
)
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* @param {object} opts
|
|
101
|
-
* @param {object} v
|
|
102
|
-
* @returns {object}
|
|
103
|
-
*/
|
|
104
|
-
const mkClickHandler = (opts, v) => {
|
|
105
|
-
var attrs = {};
|
|
106
|
-
if (opts.onRowSelect)
|
|
107
|
-
attrs.onclick =
|
|
108
|
-
typeof opts.onRowSelect === "function"
|
|
109
|
-
? opts.onRowSelect(v)
|
|
110
|
-
: opts.onRowSelect;
|
|
111
|
-
if (opts.selectedId && v.id && +v.id === +opts.selectedId)
|
|
112
|
-
attrs.class = "table-active";
|
|
113
|
-
return attrs;
|
|
114
|
-
};
|
|
115
|
-
module.exports = mkTable;
|