Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@saltcorn/markup

Package Overview
Dependencies
Maintainers
1
Versions
405
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@saltcorn/markup - npm Package Compare versions

Comparing version 0.5.6-beta.2 to 0.5.6-beta.3

50

helpers.js

@@ -41,26 +41,28 @@ const {

const radio_group = ({ name, options, value, form_name, ...rest }) =>
(options || [])
.filter((o) => (typeof o === "string" ? o : o.value))
.map((o, ix) => {
const myvalue = typeof o === "string" ? o : o.value;
const id = `input${text_attr(name)}${ix}`;
return div(
{ class: "form-check" },
input({
class: ["form-check-input", rest.class],
type: "radio",
name,
"data-fieldname": form_name,
id,
value: text_attr(myvalue),
checked: myvalue === value,
}),
label(
{ class: "form-check-label", for: id },
typeof o === "string" ? o : o.label
)
);
})
.join("");
const radio_group = ({ name, options, value, inline, form_name, ...rest }) =>
div(
(options || [])
.filter((o) => (typeof o === "string" ? o : o.value))
.map((o, ix) => {
const myvalue = typeof o === "string" ? o : o.value;
const id = `input${text_attr(name)}${ix}`;
return div(
{ class: ["form-check", inline && "form-check-inline"] },
input({
class: ["form-check-input", rest.class],
type: "radio",
name,
"data-fieldname": form_name,
id,
value: text_attr(myvalue),
checked: myvalue === value,
}),
label(
{ class: "form-check-label", for: id },
typeof o === "string" ? o : o.label
)
);
})
.join("")
);

@@ -67,0 +69,0 @@ const pagination = ({

@@ -15,3 +15,6 @@ const {

domReady,
footer,
i,
small,
br,
} = require("./tags");

@@ -73,7 +76,11 @@

innerSections(sections).map((s) =>
s.subitems
s.location === "Mobile Bottom"
? ""
: s.subitems
? navSubitems(s)
: s.link
? li(
{ class: ["nav-item", active(currentUrl, s) && "active"] },
{
class: ["nav-item", active(currentUrl, s) && "active"],
},
a(

@@ -93,2 +100,41 @@ {

const hasMobileItems = (sections) =>
innerSections(sections).some((s) => s.location === "Mobile Bottom");
const mobileBottomNavBar = (currentUrl, sections, cls = "", clsLink = "") =>
hasMobileItems(sections)
? footer(
{
class:
"bs-mobile-nav-footer d-flex justify-content-around d-sm-flex d-md-none " +
cls,
},
innerSections(sections).map((s) =>
s.location !== "Mobile Bottom"
? ""
: //: s.subitems
//? navSubitems(s)
s.link
? div(
{
class: [
"mt-2 text-center",
active(currentUrl, s) ? "active" : "opacity-50",
],
},
a(
{
class: [s.style || "", clsLink],
href: text(s.link),
},
s.icon ? i({ class: `fa-lg ${s.icon}` }) : "",
br(),
small(text(s.label))
)
)
: ""
)
)
: "";
const leftNavBar = ({ name, logo }) => [

@@ -122,8 +168,3 @@ a(

const navbar = (
brand,
sections,
currentUrl,
opts = { fixedTop: true}
) =>
const navbar = (brand, sections, currentUrl, opts = { fixedTop: true }) =>
nav(

@@ -259,2 +300,3 @@ {

cardHeaderTabs,
mobileBottomNavBar,
};

@@ -1,2 +0,2 @@

const { a, input, div, ul, text, text_attr } = require("./tags");
const { a, input, div, ul, text, text_attr, i, hr } = require("./tags");

@@ -15,2 +15,4 @@ describe("tags", () => {

expect(div()).toBe("<div></div>");
expect(i()).toBe("<i></i>");
expect(hr()).toBe("<hr>");
expect(div(["hello ", "world"])).toBe("<div>hello world</div>");

@@ -25,2 +27,8 @@ expect(ul({ class: "foo" }, [false, "hello ", "world"])).toBe(

expect(Array.isArray({})).toBe(false);
expect(i({ class: "fas fa-plus-square" })).toBe(
'<i class="fas fa-plus-square"></i>'
);
});
it("class", () => {
expect(div({ class: "foo" }, 5)).toBe('<div class="foo">5</div>');

@@ -32,3 +40,2 @@ expect(div({ class: false }, 5)).toBe("<div>5</div>");

);
expect(div({ class: ["foo", " "] }, 5)).toBe('<div class="foo ">5</div>');

@@ -41,5 +48,25 @@ expect(input({ class: ["foo", " "] })).toBe('<input class="foo ">');

expect(div({ class: [undefined, null, false] }, 5)).toBe("<div>5</div>");
expect(hr({ class: "foo" })).toBe('<hr class="foo">');
});
it("style", () => {
expect(div({ style: "color:red;border:1px solid black" }, 5)).toBe(
'<div style="color:red;border:1px solid black">5</div>'
);
expect(div({ style: ["color:red", "border:1px solid black"] }, 5)).toBe(
'<div style="color:red;border:1px solid black">5</div>'
);
expect(
div({ class: [undefined, null, false] }, 5)
).toBe('<div>5</div>');
div(
{ style: ["color:red", false, undefined, "border:1px solid black"] },
5
)
).toBe('<div style="color:red;border:1px solid black">5</div>');
expect(div({ style: { color: "red", border: "1px solid black" } }, 5)).toBe(
'<div style="color:red;border:1px solid black">5</div>'
);
expect(hr({ style: { color: "red" } }, 5)).toBe('<hr style="color:red">');
});
it("escaping", () => {
expect(text("foo")).toBe("foo");

@@ -51,3 +78,5 @@ expect(text_attr('" onMouseOver="alert(1);')).toBe(

expect(text(0)).toBe("0");
expect(text("<script>alert(1);<script>")).toBe("&lt;script&gt;alert(1);&lt;script&gt;");
expect(text("<script>alert(1);<script>")).toBe(
"&lt;script&gt;alert(1);&lt;script&gt;"
);
expect(text("<p>alert<p>")).toBe("<p>alert<p>");

@@ -54,0 +83,0 @@ expect(text("<kbd>ctrl<kbd>")).toBe("<kbd>ctrl<kbd>");

{
"name": "@saltcorn/markup",
"version": "0.5.6-beta.2",
"version": "0.5.6-beta.3",
"description": "Markup for Saltcorn, open-source no-code platform",

@@ -15,2 +15,3 @@ "homepage": "https://saltcorn.com",

"escape-html": "^1.0.3",
"html-tags": "3.1.0",
"xss": "^1.0.8"

@@ -17,0 +18,0 @@ },

const xss = require("xss");
const escape = require("escape-html");
const htmlTags = require("html-tags");
const voidHtmlTags = new Set(require("html-tags/void"));

@@ -10,2 +12,18 @@ const ppClasses = (cs) =>

};
const ppStyles = (cs) =>
typeof cs === "string"
? cs
: !cs
? ""
: Array.isArray(cs)
? cs.filter((c) => c).join(";")
: typeof cs === "object"
? Object.entries(cs)
.map(([k, v]) => `${k}:${v}`)
.join(";")
: "";
const ppStyle = (c) => {
const clss = ppStyles(c);
return clss ? `style="${clss}"` : "";
};
const ppAttrib = ([k, v]) =>

@@ -20,4 +38,6 @@ typeof v === "boolean"

? ppClass(v)
: k === "style"
? ppStyle(v)
: `${k}="${v}"`;
const mkTag = (tnm, forceStandAloneClosingTag) => (...args) => {
const mkTag = (tnm, voidTag) => (...args) => {
var body = "";

@@ -41,10 +61,4 @@ var attribs = " ";

if (attribs === " ") attribs = "";
return body.length > 0 || forceStandAloneClosingTag
? `<${tnm}${attribs}>${body}</${tnm}>`
: `<${tnm}${attribs} />`;
return voidTag ? `<${tnm}${attribs}>` : `<${tnm}${attribs}>${body}</${tnm}>`;
};
const input = (kvs) => {
const attribs = Object.entries(kvs).map(ppAttrib).join(" ");
return `<input ${attribs}>`;
};

@@ -60,53 +74,13 @@ //https://stackoverflow.com/a/59220393

const nbsp = "&nbsp;";
const allTags = Object.fromEntries(
htmlTags.map((tag) => [tag, mkTag(tag, voidHtmlTags.has(tag))])
);
module.exports = {
a: mkTag("a"),
div: mkTag("div", true),
span: mkTag("span"),
label: mkTag("label"),
option: mkTag("option"),
select: mkTag("select"),
button: mkTag("button"),
textarea: mkTag("textarea", true),
form: mkTag("form"),
script: mkTag("script", true),
style: mkTag("style"),
p: mkTag("p"),
colgroup: mkTag("colgroup"),
col: mkTag("col", true),
table: mkTag("table"),
img: mkTag("img"),
thead: mkTag("thead"),
tbody: mkTag("tbody"),
small: mkTag("small", true),
pre: mkTag("pre"),
code: mkTag("code"),
time: mkTag("time"),
header: mkTag("header"),
footer: mkTag("footer"),
section: mkTag("section"),
strong: mkTag("strong"),
tr: mkTag("tr"),
th: mkTag("th"),
td: mkTag("td"),
ul: mkTag("ul"),
ol: mkTag("ol"),
li: mkTag("li"),
h1: mkTag("h1"),
h2: mkTag("h2"),
h3: mkTag("h3"),
h4: mkTag("h4"),
h5: mkTag("h5"),
h6: mkTag("h6"),
b: mkTag("b"),
nav: mkTag("nav"),
i: mkTag("i", true),
hr: mkTag("hr"),
link: mkTag("link"),
...allTags,
domReady,
input,
text,
text_attr,
nbsp,
nbsp: "&nbsp;",
mkTag,
};
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc