Scenario generator for vore roleplay and story ideas.
https://scenario-generator.deliciousreya.net/responses
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
131 lines
4.3 KiB
131 lines
4.3 KiB
import {
|
|
type ButtonFeatures,
|
|
ButtonType,
|
|
type CheckboxFeatures,
|
|
type ElementFeatures, extendClasses,
|
|
type FormFeatures,
|
|
HyperlinkDestination,
|
|
type HyperlinkFeatures,
|
|
type LabelFeatures,
|
|
type TemplateBuilder
|
|
} from '../../common/template';
|
|
import escapeHTML from 'escape-html';
|
|
import { kebabCase } from 'change-case';
|
|
|
|
function tag(tagName: string, features: ElementFeatures, attributes: string[], contents: string[]): string {
|
|
if (typeof features.id !== "undefined") {
|
|
attributes.push(`id="${escapeHTML(features.id)}"`)
|
|
}
|
|
if (typeof features.classes !== "undefined") {
|
|
attributes.push(`class="${typeof features.classes === "string"
|
|
? escapeHTML(features.classes)
|
|
: Array.from(features.classes).map(escapeHTML).join(" ")}"`)
|
|
}
|
|
if (typeof features.data !== "undefined") {
|
|
for (const [key, value] of features.data) {
|
|
attributes.push(`data-${escapeHTML(kebabCase(key))}="${escapeHTML(value)}"`)
|
|
}
|
|
}
|
|
return `<${tagName}${attributes.length === 0 ? "" : " " + attributes.join(" ")}>${contents.join("")}</${tagName}>`
|
|
}
|
|
|
|
class StringTemplateBuilderImpl implements TemplateBuilder<string> {
|
|
|
|
makeButton(features: ButtonFeatures, ...contents: string[]): string {
|
|
const attributes = [
|
|
`type="${escapeHTML(features.type ?? ButtonType.Button)}"`,
|
|
]
|
|
if (typeof features.name === "string") {
|
|
attributes.push(`name="${escapeHTML(features.name)}"`)
|
|
}
|
|
if (typeof features.value === "string") {
|
|
attributes.push(`value="${escapeHTML(features.value)}"`)
|
|
}
|
|
return tag('button', {...features, classes: extendClasses(features.classes, "button")}, attributes, contents)
|
|
}
|
|
|
|
makeCheckbox(features: CheckboxFeatures, ...contents: string[]): string {
|
|
const attributes = [`type="checkbox"`, `name="${escapeHTML(features.name)}"`]
|
|
if (features.checked) {
|
|
attributes.push("checked")
|
|
}
|
|
if (typeof features.value === "string") {
|
|
attributes.push(`value="${escapeHTML(features.value)}"`)
|
|
}
|
|
return tag('input', features, attributes, contents);
|
|
}
|
|
|
|
makeDiv(features: ElementFeatures, ...contents: string[]): string {
|
|
return tag('div', features, [], contents);
|
|
}
|
|
|
|
makeFooter(features: ElementFeatures, ...contents: string[]): string {
|
|
return tag('footer', features, [], contents);
|
|
}
|
|
|
|
makeForm(features: FormFeatures, ...contents: string[]): string {
|
|
const attributes = [`action="${escapeHTML(features.action)}"`, `method="${escapeHTML(features.method)}"`]
|
|
return tag('form', features, attributes, contents);
|
|
}
|
|
|
|
makeHeader(features: ElementFeatures, ...contents: string[]): string {
|
|
return tag('header', features, [], contents)
|
|
}
|
|
|
|
makeHeading1(features: ElementFeatures, ...contents: string[]): string {
|
|
return tag('h1', features, [], contents);
|
|
}
|
|
|
|
makeHeading2(features: ElementFeatures, ...contents: string[]): string {
|
|
return tag('h2', features, [], contents);
|
|
}
|
|
|
|
makeHyperlink(features: HyperlinkFeatures, ...contents: string[]): string {
|
|
const attributes = [`href="${escapeHTML(features.url)}"`]
|
|
if (features.destination === HyperlinkDestination.External) {
|
|
attributes.push(`rel="external nofollow noreferrer"`)
|
|
}
|
|
if (features.asButton) {
|
|
attributes.push(`draggable="false"`)
|
|
}
|
|
return tag('a', {...features, classes: extendClasses(features.classes, features.asButton ? ["button"] : [])}, attributes, contents);
|
|
}
|
|
|
|
makeLabel(features: LabelFeatures, ...contents: string[]): string {
|
|
const attributes = []
|
|
if (typeof features.forId === "string") {
|
|
attributes.push(`for="${escapeHTML(features.forId)}"`)
|
|
}
|
|
return tag('label', features, attributes, contents);
|
|
}
|
|
|
|
makeListItem(features: ElementFeatures, ...contents: string[]): string {
|
|
return tag('li', features, [], contents)
|
|
}
|
|
|
|
makeNav(features: ElementFeatures, ...contents: string[]): string {
|
|
return tag('nav', features, [], contents)
|
|
}
|
|
|
|
makeNoscript(features: ElementFeatures, ...contents: string[]): string {
|
|
return tag('noscript', features, [], contents);
|
|
}
|
|
|
|
makeParagraph(features: ElementFeatures, ...contents: string[]): string {
|
|
return tag('p', features, [], contents);
|
|
}
|
|
|
|
makeSpan(features: ElementFeatures, ...contents: string[]): string {
|
|
return tag('span', features, [], contents);
|
|
}
|
|
|
|
makeText(text: string): string {
|
|
return escapeHTML(text);
|
|
}
|
|
|
|
makeUnorderedList(features: ElementFeatures, ...contents: string[]): string {
|
|
return tag('ul', features, [], contents);
|
|
}
|
|
}
|
|
|
|
export const StringTemplateBuilder = new StringTemplateBuilderImpl()
|
|
|