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
2 changes: 1 addition & 1 deletion packages/heml-parse/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions packages/heml-parse/src/closeSelfClosingNodes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import selfClosingHtmlTags from 'html-tags/void'

/**
* The HEML is parsed as XML. If the HEML contains a self closing tag without the closing slash
* all the siblings will be treated as children. This moves the children back to their place and
* forces the tag to be self closing
* @param {Cheerio} $
* @param {Array} elements
*/
export default function($, elements) {
/** collect all the self closing nodes */
const selfClosingTags = [
...selfClosingHtmlTags,
...elements.filter((element) => element.children === false).map(({ tagName }) => tagName) ]

const $selfClosingNodes = $.findNodes(selfClosingTags).reverse()

/** Move contents from self wrapping tags outside of itself */
$selfClosingNodes.forEach(($node) => {
$node.after($node.html())
$node.html('')
})
}
33 changes: 33 additions & 0 deletions packages/heml-parse/src/extractInlineStyles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import randomString from 'crypto-random-string'
import { compact, first } from 'lodash'

/**
* This extracts all inline styles on elements into a style tag to be inlined later
* so that the styles can be properly expanded and later re-inlined
* @param {Cheerio} $
* @param {Array} elements
*/
export default function($, elements) {
/** try for head, fallback to body, then heml */
const $head = first(compact([...$('head').toNodes(), ...$('body').toNodes(), ...$('heml').toNodes()]))

/** move inline styles to a style tag with unique ids so they can be hit by the css processor */
if ($head) {
const $inlineStyleNodes = $.findNodes(elements.map(({ tagName }) => tagName)).filter($node => !!$node.attr('style'))

const inlineCSS = $inlineStyleNodes.map(($node) => {
let id = $node.attr('id')
const css = $node.attr('style')
$node.removeAttr('style')

if (!id) {
id = `heml-${randomString(5)}`
$node.attr('id', id)
}

return `#${id} {${css}}`
}).join('\n')

if (inlineCSS.length > 0) $head.append(`<style>${inlineCSS}</style>`)
}
}
57 changes: 6 additions & 51 deletions packages/heml-parse/src/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { load } from 'cheerio'
import { difference, compact, first } from 'lodash'
import randomString from 'crypto-random-string'
import htmlTags from 'html-tags'
import selfClosingHtmlTags from 'html-tags/void'

const wrappingHtmlTags = difference(htmlTags, selfClosingHtmlTags)
import closeSelfClosingNodes from './closeSelfClosingNodes'
import openWrappingNodes from './openWrappingNodes'
import extractInlineStyles from './extractInlineStyles'

function parse (contents, options = {}) {
const {
Expand All @@ -31,51 +28,9 @@ function parse (contents, options = {}) {
.map((node) => $(node))
}

const selfClosingTags = [
...selfClosingHtmlTags,
...elements.filter((element) => element.children === false).map(({ tagName }) => tagName) ]
const wrappingTags = [
...wrappingHtmlTags,
...elements.filter((element) => element.children !== false).map(({ tagName }) => tagName) ]

const $selfClosingNodes = $.findNodes(selfClosingTags).reverse()
const $wrappingNodes = $.findNodes(wrappingTags).reverse()

/** Move contents from self wrapping tags outside of itself */
$selfClosingNodes.forEach(($node) => {
$node.after($node.html())
$node.html('')
})

/** ensure that all wrapping tags have at least a zero-width, non-joining character */
$wrappingNodes.forEach(($node) => {
if ($node.html().length === 0) {
$node.html(' ')
}
})

/** try for head, fallback to body, then heml */
const $head = first(compact([...$('head').toNodes(), ...$('body').toNodes(), ...$('heml').toNodes()]))

/** move inline styles to a style tag with unique ids so they can be hit by the css processor */
if ($head) {
const $inlineStyleNodes = $.findNodes(elements.map(({ tagName }) => tagName)).filter($node => !!$node.attr('style'))

const inlineCSS = $inlineStyleNodes.map(($node) => {
let id = $node.attr('id')
const css = $node.attr('style')
$node.removeAttr('style')

if (!id) {
id = `heml-${randomString(5)}`
$node.attr('id', id)
}

return `#${id} {${css}}`
}).join('\n')

$head.append(`<style>${inlineCSS}</style>`)
}
closeSelfClosingNodes($, elements)
openWrappingNodes($, elements)
extractInlineStyles($, elements)

return $
}
Expand Down
27 changes: 27 additions & 0 deletions packages/heml-parse/src/openWrappingNodes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import htmlTags from 'html-tags'
import selfClosingHtmlTags from 'html-tags/void'
import { difference } from 'lodash'

const wrappingHtmlTags = difference(htmlTags, selfClosingHtmlTags)

/**
* The HEML is parsed as XML. If the HEML contains a wrapping tag with no content it will be
* optimized to be self closing. This add a placeholder space to all empty wrapping tags
* @param {Cheerio} $
* @param {Array} elements
*/
export default function($, elements) {
/** collect all the wrapping nodes */
const wrappingTags = [
...wrappingHtmlTags,
...elements.filter((element) => element.children !== false).map(({ tagName }) => tagName) ]

const $wrappingNodes = $.findNodes(wrappingTags).reverse()

/** ensure that all wrapping tags have at least a space */
$wrappingNodes.forEach(($node) => {
if ($node.html().length === 0) {
$node.html(' ')
}
})
}
55 changes: 54 additions & 1 deletion packages/heml-styles/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/heml-styles/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
},
"dependencies": {
"css-declaration-sorter": "^2.1.0",
"css-selector-tokenizer": "^0.7.0",
"css-shorthand-expand": "^1.1.0",
"lodash": "^4.17.4",
"postcss": "^6.0.13",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,6 @@ export default postcss.plugin('postcss-element-expander', ({ elements, aliases }

return (root, result) => {
for (let element of elements) {
/**
* add the element tag to any css selectors that implicitly target an element
* .i.e. #my-button that selects <button id="my-button">click me</button>
*/
root.walkRules((rule) => {
tagAliasSelectors(element, aliases[element.tag], rule)
})

/**
* There are 3 (non-mutually exclusive) possibilities when it contains the element tag
*
Expand Down

This file was deleted.

Loading