Skip to content

Commit

Permalink
feat(html): add style helper
Browse files Browse the repository at this point in the history
  • Loading branch information
smalluban committed Jan 1, 2019
1 parent c015089 commit a3c552a
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 28 deletions.
18 changes: 9 additions & 9 deletions src/template/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import resolveProperty from './resolvers/property';

const TIMESTAMP = Date.now();

const getPlaceholder = (id = 0) => `{{h-${TIMESTAMP}-${id}}}`;
export const getPlaceholder = (id = 0) => `{{h-${TIMESTAMP}-${id}}}`;

const PLACEHOLDER_REGEXP_TEXT = getPlaceholder('(\\d+)');
const PLACEHOLDER_REGEXP_EQUAL = new RegExp(`^${PLACEHOLDER_REGEXP_TEXT}$`);
Expand Down Expand Up @@ -51,12 +51,8 @@ function applyShadyCSS(template, tagName) {
}, template);
}

export function createId(parts, isSVG) {
return `${isSVG ? 'svg:' : ''}${parts.join(getPlaceholder())}`;
}

function createSignature(parts) {
const signature = parts.reduce((acc, part, index) => {
function createSignature(parts, styles) {
let signature = parts.reduce((acc, part, index) => {
if (index === 0) {
return part;
}
Expand All @@ -66,6 +62,10 @@ function createSignature(parts) {
return acc + getPlaceholder(index - 1) + part;
}, '');

if (styles) {
signature += `<style>${styles.join('\n')}</style>`;
}

/* istanbul ignore if */
if (IS_IE) {
return signature.replace(
Expand Down Expand Up @@ -128,11 +128,11 @@ function createExternalWalker(context) {
const createWalker = typeof window.ShadyDOM === 'object' && window.ShadyDOM.inUse ? createInternalWalker : createExternalWalker;

const container = document.createElement('div');
export function compile(rawParts, isSVG) {
export function compile(rawParts, isSVG, styles) {
const template = document.createElement('template');
const parts = [];

let signature = createSignature(rawParts);
let signature = createSignature(rawParts, styles);
if (isSVG) signature = `<svg>${signature}</svg>`;

/* istanbul ignore if */
Expand Down
47 changes: 28 additions & 19 deletions src/template/index.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,43 @@
import define from '../define';
import defineElements from '../define';

import { compile, createId } from './core';
import { compile, getPlaceholder } from './core';
import resolve from './resolve';

function defineElements(elements) {
define(elements);
return this;
}

function key(id) {
this.id = id;
return this;
}

const updates = new Map();
const PLACEHOLDER = getPlaceholder();

const templatesMap = new Map();
const stylesMap = new WeakMap();

const helpers = {
define(elements) {
defineElements(elements);
return this;
},
key(id) {
this.id = id;
return this;
},
style(...styles) {
stylesMap.set(this, styles);
return this;
},
};

function create(parts, args, isSVG) {
const update = (host, target = host) => {
const id = createId(parts, isSVG);
let render = updates.get(id);
const fn = (host, target = host) => {
const styles = stylesMap.get(fn);
const id = `${parts.join(PLACEHOLDER)}${styles ? styles.join(PLACEHOLDER) : ''}${isSVG ? 'svg' : ''}`;

let render = templatesMap.get(id);
if (!render) {
render = compile(parts, isSVG);
updates.set(id, render);
render = compile(parts, isSVG, styles);
templatesMap.set(id, render);
}

render(host, target, args);
};

return Object.assign(update, { define: defineElements, key });
return Object.assign(fn, helpers);
}

export function html(parts, ...args) {
Expand Down
30 changes: 30 additions & 0 deletions test/spec/html.js
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,36 @@ describe('html:', () => {
});
});

describe('style helper', () => {
const render = html`<div>content</div>`;

it('adds single style with text content', () => {
const container = fragment.attachShadow({ mode: 'open' });

render.style('div { color: red }')(fragment, container);

expect(getComputedStyle(container.children[0]).color).toBe('rgb(255, 0, 0)');
});

it('adds multiple styles with text content', () => {
const container = fragment.attachShadow({ mode: 'open' });

render.style('div { color: red }', 'div { padding-top: 20px }')(fragment, container);

expect(getComputedStyle(container.children[0]).color).toBe('rgb(255, 0, 0)');
expect(getComputedStyle(container.children[0]).paddingTop).toBe('20px');
});

it('creates unique template id for styled version', () => {
const container = fragment.attachShadow({ mode: 'open' });
render.style('div { color: red }')({}, container);
expect(container.children.length).toBe(2);

html`<div>content</div>`({}, container);
expect(container.children.length).toBe(1);
});
});

describe('shadyCSS polyfill', () => {
const render = text => html`
<div>${text}</div>
Expand Down

0 comments on commit a3c552a

Please sign in to comment.