Skip to content

Commit 47d1183

Browse files
authored
Allow to update content dynamically and to render the content inside the template (#1)
* feat(*): allow to change content inside template dynamically and to render the content * refactor(js): disconnect nodesObserver in disconnectedCallback * fix(styles): CSS var name * refactor(js): use arrow function instead of bind * update docs, demo and remove failing test * test(): with render attribute the code inside the template is rendered
1 parent 3400796 commit 47d1183

File tree

7 files changed

+326
-100
lines changed

7 files changed

+326
-100
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
.DS_Store
12
bower_components/
2-
coverage-reports/
3+
coverage-reports/

README.md

+15-3
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,25 @@ Forget to worry about spaces, indentation, HTML entities, etc.
5959
## Usage
6060

6161
The code to highlight must be provided inside a `<template>` tag.
62-
The `type` attribute is **optional** and it corresponds to the `class` applied to `<code>` in [highlight.js](https://highlightjs.org/).
6362

6463
```html
65-
<code-sample type="html">
64+
<code-sample>
6665
<template>
6766
<p>your code here...</p>
6867
</template>
6968
</code-sample>
7069
```
7170

71+
To render the code inside the template, use the boolean attribute `render`.
72+
73+
```html
74+
<code-sample render>
75+
<template>
76+
<my-custom-element></my-custom-element>
77+
</template>
78+
</code-sample>
79+
```
80+
7281
## Themes
7382

7483
The component includes 6 themes that must be imported explicitly.
@@ -112,8 +121,11 @@ The following custom CSS properties are available for styling:
112121
| Custom property | Description | Default |
113122
|:-------------------------------|:-------------------------------------------------------------|:-------------|
114123
| --code-sample-font-family | font-family applied to `<pre>` and `<code>` elements | Operator Mono, Inconsolata, Roboto Mono, monaco, consolas, monospace |
115-
| --code-sample-font-size | font-size applied to `<pre>` and `<code>` elements | 14px |
124+
| --code-sample-font-size | font-size applied to `<pre>` and `<code>` elements | 14px |
125+
| --code-sample-demo-padding | padding applied to the container of the rendered code | 0 0 20px |
126+
| --code-sample-demo | empty mixin applied to the container of the rendered code | {} |
116127

128+
_Note:_ The [CSS mixin shim](https://www.polymer-project.org/2.0/docs/upgrade#css-custom-property-shim) is required to use mixins.
117129

118130
Included themes contain custom CSS properties to set the background and text color.
119131
You may need to add these CSS properties to your own themes.

bower.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
},
2020
"devDependencies": {
2121
"web-component-tester": "^6.0.0",
22-
"iron-test-helpers": "PolymerElements/iron-test-helpers#^2.0.0"
22+
"iron-test-helpers": "PolymerElements/iron-test-helpers#^2.0.0",
23+
"transburger-icon": "^3.0.1"
2324
},
2425
"license": "https://github.com/kcmr/code-sample/LICENSE.md",
2526
"homepage": "https://github.com/kcmr/code-sample/",

code-sample.html

+42-23
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<link rel="import" href="../polymer/polymer-element.html">
2+
<link rel="import" href="../polymer/lib/utils/flattened-nodes-observer.html">
23
<link rel="import" href="highlight-import.html">
34

45
<dom-module id="code-sample">
@@ -17,9 +18,18 @@
1718
padding: 0 20px;
1819
line-height: 1.3;
1920
}
21+
22+
.demo:not(:empty) {
23+
padding: var(--code-sample-demo-padding, 0 0 20px);
24+
}
25+
26+
.demo {
27+
@apply --code-sample-demo;
28+
}
2029
</style>
2130

22-
<slot></slot>
31+
<div id="demo" class="demo"></div>
32+
<slot id="content"></slot>
2333
<pre id="code"></pre>
2434
</template>
2535
<script>
@@ -37,47 +47,56 @@
3747
*/
3848
class CodeSample extends Polymer.Element {
3949
static get is() { return 'code-sample' }
50+
4051
static get properties() {
4152
return {
42-
_content: {
43-
type: String,
44-
observer: '_contentChanged'
45-
},
46-
4753
/**
48-
* Code type. (eg.: html, js, css)
49-
* Options are the same as the available classes for `<code>` tag using highlight.js
54+
* Set to true to render the code inside the template.
5055
*/
51-
type: {
52-
type: String
56+
render: {
57+
type: Boolean,
58+
value: false
5359
}
5460
}
5561
}
5662

57-
constructor() {
58-
super();
59-
}
60-
6163
connectedCallback() {
6264
super.connectedCallback();
6365
setTimeout(() => {
6466
if (this.querySelector('template')) {
65-
this._content = this.querySelector('template').innerHTML;
67+
this._observer = new Polymer.FlattenedNodesObserver(this.$.content, () => this._updateContent());
6668
} else if (this.childNodes.length) {
6769
console.error('<code-sample>:', 'content must be provided inside a <template> tag');
6870
}
6971
}, 1);
7072
}
7173

72-
_contentChanged(content) {
73-
let code = document.createElement('code');
74-
if (this.type) {
75-
code.classList.add(this.type);
74+
disconnectedCallback() {
75+
if (this._observer) {
76+
this._observer.disconnect();
77+
this._observer = null;
7678
}
77-
code.innerHTML = this._entitize(this._cleanIndentation(content));
78-
this.$.code.appendChild(code);
79-
hljs.highlightBlock(code);
80-
this.innerHTML = '';
79+
}
80+
81+
_updateContent() {
82+
if (this._code) { this._code.parentNode.removeChild(this._code); }
83+
if (this._demo) { this.$.demo.innerHTML = ''; }
84+
85+
let nodes = Polymer.FlattenedNodesObserver.getFlattenedNodes(this.$.content);
86+
let template = [].filter.call(nodes, (node) => node.nodeType === Node.ELEMENT_NODE)[0];
87+
88+
if (this.render) {
89+
this._demo = this.$.demo.appendChild(document.importNode(template.content, true));
90+
}
91+
92+
this._highlight(template.innerHTML);
93+
}
94+
95+
_highlight(str) {
96+
this._code = document.createElement('code');
97+
this._code.innerHTML = this._entitize(this._cleanIndentation(str));
98+
this.$.code.appendChild(this._code);
99+
hljs.highlightBlock(this._code);
81100
}
82101

83102
_cleanIndentation(str) {

demo/css/demo.css

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
body {
2+
font-family: Roboto, sans-serif;
3+
background: #E6E8E8;
4+
-webkit-tap-highlight-color: transparent;
5+
}
6+
7+
h1 {
8+
font-size: 18px;
9+
font-weight: 500;
10+
margin: 0 0 1em;
11+
}
12+
13+
p { font-weight: 300; }
14+
15+
code {
16+
font-family: Roboto Mono, monospace;
17+
}
18+
19+
code-sample {
20+
--code-sample-font-family: Roboto Mono, monospace;
21+
}
22+
23+
.wrapper {
24+
max-width: 800px;
25+
margin: 40px auto 0;
26+
}
27+
28+
.wrapper > .demo {
29+
margin-bottom: 40px;
30+
padding: 40px;
31+
background-color: #fff;
32+
}
33+
.demo-text {
34+
text-align: left;
35+
margin: 0 0 20px;
36+
padding: 0;
37+
border-bottom: 1px solid #e0e0e0;
38+
}
39+
40+
.demo-btn {
41+
font: inherit;
42+
background-color: #EAEDED;
43+
border: 0;
44+
box-shadow: 0 1px 2px rgba(0,0,0,0.25);
45+
height: 40px;
46+
padding: 0 20px;
47+
border-radius: 3px;
48+
}
49+
50+
.demo-btn:active {
51+
background-color: #D7DBDD;
52+
}
53+
54+
.title-button {
55+
display: flex;
56+
justify-content: space-between;
57+
align-items: flex-end;
58+
margin-bottom: 20px;
59+
}
60+
61+
.title-button h1 { margin-bottom: 0; }
62+
63+
.center { text-align: center; }
64+
65+
.toast-text { line-height: 1.5; font-family: Roboto Mono, monaco, monospace; font-size: 13px; }
66+
.toast-text > span { color: #E9D80E; }
67+

0 commit comments

Comments
 (0)