-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
13f8513
commit e036840
Showing
25 changed files
with
943 additions
and
318 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K> | ||
export type Mandatory<T, K extends keyof T> = Pick<Required<T>, K> & Omit<T, K> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import { HiccoughContent, HiccoughElement, HiccoughOptions } from './hiccoughElement' | ||
import { Mandatory } from '../../util/types' | ||
|
||
export function html(input: HiccoughContent | HiccoughContent[], options: HiccoughOptions = {}): string { | ||
const fullOptions: InternalHiccoughOptions = { | ||
newLines: false, | ||
eachIndent: ' ', | ||
indentCount: -1, | ||
...options | ||
} | ||
|
||
return renderContentArray(Array.isArray(input) ? input : [input], fullOptions).rendered | ||
} | ||
|
||
type InternalHiccoughOptions = Mandatory<HiccoughOptions, 'newLines' | 'indentCount' | 'eachIndent'> | ||
|
||
function renderContentArray(content: HiccoughContent[], options: InternalHiccoughOptions) { | ||
const renderedElements = content | ||
.map((x) => renderContent(x, options)) | ||
.filter((x) => x !== undefined) as RenderedContent[] | ||
|
||
return { | ||
rendered: renderedElements.map(({ rendered }) => rendered).join(`${options.newLines ? '\n' : ''}`), | ||
containsStructure: renderedElements.length > 1 || renderedElements.some(({ hasChildren }) => hasChildren) | ||
} | ||
} | ||
|
||
type RenderedContent = { rendered: string; hasChildren: boolean } | ||
|
||
function renderContent( | ||
content: HiccoughContent, | ||
options: InternalHiccoughOptions | ||
): RenderedContent | undefined { | ||
if (typeof content === 'undefined') return undefined | ||
if (typeof content === 'string') return { rendered: content, hasChildren: false } | ||
return { | ||
rendered: `${renderElement(content, { | ||
...options, | ||
indentCount: options.indentCount + 1 | ||
})}`, | ||
hasChildren: true | ||
} | ||
} | ||
|
||
function renderElement(input: HiccoughElement, parentOptions: InternalHiccoughOptions) { | ||
const options = { ...parentOptions, ...input.options } | ||
const childOptions = { ...options, ...{ indentFromParent: parentOptions.indentFromParent } } | ||
|
||
const { name, attributes, content } = input, | ||
{ rendered, containsStructure } = renderContentArray(content ?? [], childOptions), | ||
preOpenIndentString = | ||
options.newLines || options.indentFromParent | ||
? Array.from({ length: options.indentCount }, () => options.eachIndent).join('') | ||
: '', | ||
renderedAttributes = attributes | ||
? ' ' + | ||
Object.entries(attributes) | ||
.map(([k, v]) => `${k}="${v}"`) | ||
.join(' ') | ||
: '' | ||
|
||
if (rendered.length === 0) { | ||
return `${preOpenIndentString}<${name}${renderedAttributes} />` | ||
} | ||
|
||
const newLineString = options.newLines && containsStructure ? '\n' : '', | ||
preCloseIndentString = options.newLines && containsStructure ? preOpenIndentString : '' | ||
|
||
return `${preOpenIndentString}<${name}${renderedAttributes}>${newLineString}${rendered}${newLineString}${preCloseIndentString}</${name}>` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
export type HiccoughAttributes = Record<string, string> | ||
|
||
export type HiccoughContent = string | HiccoughElement | undefined | ||
|
||
export type HiccoughOptions = { | ||
newLines?: boolean | ||
indentFromParent?: boolean | ||
eachIndent?: string | ||
indentCount?: number | ||
} | ||
|
||
export type HiccoughElement = { | ||
isElement: true | ||
name: string | ||
attributes?: HiccoughAttributes | ||
content?: HiccoughContent[] | ||
options?: HiccoughOptions | ||
} | ||
|
||
function isHiccoughElement(x: unknown): x is HiccoughElement { | ||
return typeof x === 'object' && (x as HiccoughElement).isElement | ||
} | ||
|
||
function isHiccoughContent(x: unknown): x is HiccoughContent { | ||
const xtype = typeof x | ||
return xtype === 'undefined' || xtype === 'string' || isHiccoughElement(x) | ||
} | ||
|
||
export type HiccoughElementDefinition = | ||
| HiccoughContent[] | ||
| [HiccoughAttributes | HiccoughContent, ...HiccoughContent[]] | ||
|
||
// First element of def can be either attributes or content | ||
export function element(name: string, ...def: HiccoughElementDefinition): HiccoughElement { | ||
const baseElement: HiccoughElement = { isElement: true, name } | ||
const [first, ...rest] = def | ||
|
||
return isHiccoughContent(first) | ||
? { ...baseElement, content: def as HiccoughContent[] } | ||
: { | ||
...baseElement, | ||
attributes: first, | ||
content: rest as HiccoughContent[] | ||
} | ||
} | ||
|
||
export function withAttributes(attributes: HiccoughAttributes, element: HiccoughElement): HiccoughElement { | ||
return { | ||
...element, | ||
attributes: { | ||
...element.attributes, | ||
...attributes | ||
} | ||
} | ||
} | ||
|
||
export function withOptions(options: HiccoughOptions, element: HiccoughElement): HiccoughElement { | ||
return { | ||
...element, | ||
options | ||
} | ||
} | ||
|
||
export const inlineChildren: HiccoughOptions = { | ||
indentFromParent: true, | ||
newLines: false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import { element, HiccoughAttributes, HiccoughElementDefinition, withAttributes } from './hiccoughElement' | ||
|
||
export function htmlPage(...def: HiccoughElementDefinition) { | ||
return element('html', ...def) | ||
} | ||
|
||
export function head(...def: HiccoughElementDefinition) { | ||
return element('head', ...def) | ||
} | ||
|
||
export function meta(...def: HiccoughElementDefinition) { | ||
return element('meta', ...def) | ||
} | ||
|
||
export function title(content: string) { | ||
return element('title', content) | ||
} | ||
|
||
export function link(rel: string, href: string, attributes?: HiccoughAttributes) { | ||
return element('link', { rel, href, ...attributes }) | ||
} | ||
|
||
export function body(...def: HiccoughElementDefinition) { | ||
return element('body', ...def) | ||
} | ||
|
||
export function h1(...def: HiccoughElementDefinition) { | ||
return element('h1', ...def) | ||
} | ||
|
||
export function h2(...def: HiccoughElementDefinition) { | ||
return element('h2', ...def) | ||
} | ||
|
||
export function h3(...def: HiccoughElementDefinition) { | ||
return element('h3', ...def) | ||
} | ||
|
||
export function h4(...def: HiccoughElementDefinition) { | ||
return element('h4', ...def) | ||
} | ||
|
||
export function table(...def: HiccoughElementDefinition) { | ||
return element('table', ...def) | ||
} | ||
|
||
export function thead(...def: HiccoughElementDefinition) { | ||
return element('thead', ...def) | ||
} | ||
|
||
export function tbody(...def: HiccoughElementDefinition) { | ||
return element('tbody', ...def) | ||
} | ||
|
||
export function tr(...def: HiccoughElementDefinition) { | ||
return element('tr', ...def) | ||
} | ||
|
||
export function th(...def: HiccoughElementDefinition) { | ||
return element('th', ...def) | ||
} | ||
|
||
export function td(...def: HiccoughElementDefinition) { | ||
return element('td', ...def) | ||
} | ||
|
||
export function p(...def: HiccoughElementDefinition) { | ||
return element('p', ...def) | ||
} | ||
|
||
export function a(href: string, ...def: HiccoughElementDefinition) { | ||
return withAttributes({ href }, element('a', ...def)) | ||
} | ||
|
||
export function div(...def: HiccoughElementDefinition) { | ||
return element('div', ...def) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export const DOCTYPE_HTML5 = '<!doctype html>' |
Oops, something went wrong.