Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/heml-elements/src/Base.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import HEML, { createElement } from '@heml/utils' // eslint-disable-line no-unused-vars
import HEML, { createMetaElement } from '@heml/utils' // eslint-disable-line no-unused-vars
import Meta from './Meta'
import isAbsoluteUrl from 'is-absolute-url'
import { resolve } from 'url'
import { has, first } from 'lodash'

export default createElement('base', {
export default createMetaElement('base', {
parent: [ 'head' ],
children: false,
unique: true,
Expand Down
4 changes: 2 additions & 2 deletions packages/heml-elements/src/Meta.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import HEML, { createElement } from '@heml/utils' // eslint-disable-line no-unused-vars
import HEML, { createMetaElement } from '@heml/utils' // eslint-disable-line no-unused-vars

let metaMap

export default createElement('meta', {
export default createMetaElement('meta', {
attrs: true,
parent: [ 'head' ],

Expand Down
4 changes: 2 additions & 2 deletions packages/heml-elements/src/Preview.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import HEML, { createElement } from '@heml/utils' // eslint-disable-line no-unused-vars
import HEML, { createMetaElement } from '@heml/utils' // eslint-disable-line no-unused-vars
import Meta from './Meta'

export default createElement('preview', {
export default createMetaElement('preview', {
parent: [ 'head' ],
unique: true,

Expand Down
4 changes: 2 additions & 2 deletions packages/heml-elements/src/Style.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import HEML, { createElement } from '@heml/utils' // eslint-disable-line no-unused-vars
import HEML, { createMetaElement } from '@heml/utils' // eslint-disable-line no-unused-vars
import hemlstyles from '@heml/styles'
import { castArray, isEqual, uniqWith, sortBy } from 'lodash'

Expand All @@ -8,7 +8,7 @@ const START_INLINE_CSS = `/*!***START:INLINE_CSS*****/`
let styleMap
let options

export default createElement('style', {
export default createMetaElement('style', {
parent: [ 'head' ],
attrs: [ 'for', 'heml-embed' ],
defaultAttrs: {
Expand Down
4 changes: 2 additions & 2 deletions packages/heml-elements/src/Subject.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import HEML, { createElement } from '@heml/utils' // eslint-disable-line no-unused-vars
import HEML, { createMetaElement } from '@heml/utils' // eslint-disable-line no-unused-vars
import Meta from './Meta'

export default createElement('subject', {
export default createMetaElement('subject', {
parent: [ 'head' ],
unique: true,

Expand Down
65 changes: 51 additions & 14 deletions packages/heml-render/src/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { filter, difference, keyBy, first } from 'lodash'
import { filter, keyBy, first } from 'lodash'
import renderElement from './renderElement'

export { renderElement }
Expand All @@ -18,6 +18,7 @@ export default async function render ($, options = {}) {
const Meta = first(elements.filter(({ tagName }) => tagName === 'meta'))

await preRenderElements(elements, globals)
await renderMetaElements(elements, globals)
await renderElements(elements, globals)
await postRenderElements(elements, globals)

Expand Down Expand Up @@ -49,29 +50,65 @@ async function postRenderElements (elements, globals) {
}

/**
* Renders all HEML elements
* Renders meta HEML elements
* @param {Array} elements List of element definitons
* @param {Object} globals
* @return {Promise}
*/
async function renderMetaElements (elements, globals) {
const { $ } = globals
const metaTagNames = filter(elements, ({ meta }) => !!meta).map(({ tagName }) => tagName)

/** Render the meta elements first to last */
const $nodes = $.findNodes(metaTagNames)
await renderNodes($nodes, globals)
}

/**
* Renders HEML elements
* @param {Array} elements List of element definitons
* @param {Object} globals
* @return {Promise}
*/
async function renderElements (elements, globals) {
const { $ } = globals
const elementMap = keyBy(elements, 'tagName')
const metaTagNames = filter(elements, { parent: [ 'head' ] }).map(({ tagName }) => tagName)
const nonMetaTagNames = difference(elements.map(({ tagName }) => tagName), metaTagNames)
const nonMetaTagNames = filter(elements, ({ meta }) => !meta).map(({ tagName }) => tagName)

/** Render the elements last to first/outside to inside */
const $nodes = $.findNodes(nonMetaTagNames).reverse()
await renderNodes($nodes, globals)
}

const $nodes = [
...$.findNodes(metaTagNames), /** Render the meta elements first to last */
...$.findNodes(nonMetaTagNames).reverse() /** Render the elements last to first/outside to inside */
]
/**
* renders the given array of $nodes
* @param {Array[Cheerio]} $nodes
* @param {Object} globals { $, elements }
*/
async function renderNodes ($nodes, globals) {
const { elements } = globals
const elementMap = keyBy(elements, 'tagName')

for (let $node of $nodes) {
const element = elementMap[$node.prop('tagName').toLowerCase()]
const contents = $node.html()
const attrs = $node[0].attribs
const tagName = $node.prop('tagName').toLowerCase()

if (!elementMap[tagName]) { continue }

const renderedValue = await Promise.resolve(renderElement(element, attrs, contents))
const element = elementMap[tagName]

$node.replaceWith(renderedValue.trim())
await renderNode($node, element)
}
}

/**
* renders a single $node of the given element
* @param {Cheerio} $node
* @param {Object} element
*/
async function renderNode ($node, element) {
const contents = $node.html()
const attrs = $node[0].attribs

const renderedValue = await Promise.resolve(renderElement(element, attrs, contents))

$node.replaceWith(renderedValue.trim())
}
16 changes: 16 additions & 0 deletions packages/heml-utils/src/createMetaElement.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { isFunction } from 'lodash'
import createElement from './createElement'

export default function (name, element) {
if (!name || name.trim().length === 0) {
throw new Error(`When creating an element, you must set the name. ${name.trim().length === 0 ? 'An empty string' : `"${name}"`} was given.`)
}

if (isFunction(element)) {
element = { render: element }
}

element.meta = true

return createElement(name, element)
}
3 changes: 2 additions & 1 deletion packages/heml-utils/src/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { renderElement } from '@heml/render'
import cssGroups from 'css-groups'
import createElement from './createElement'
import createMetaElement from './createMetaElement'
import HEMLError from './HEMLError'
import transforms from './transforms'
import condition from './condition'

module.exports = { createElement, renderElement, HEMLError, cssGroups, transforms, condition }
module.exports = { createElement, createMetaElement, renderElement, HEMLError, cssGroups, transforms, condition }
2 changes: 1 addition & 1 deletion packages/heml/src/bin/heml.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ cli
.option('-v, --validate [level]', 'Sets the validation level', /^(none|soft|strict)$/i, 'soft')
.action(build)

if (args.length === 0 || !commands.includes(first(args)) && !first(args).startsWith('-')) {
if (args.length === 0 || (!commands.includes(first(args)) && !first(args).startsWith('-'))) {
cli.outputHelp()
}

Expand Down