From d8b1c59d17b9106074f7ca1b43b0ea958cc54fd0 Mon Sep 17 00:00:00 2001 From: simonihmig Date: Fri, 31 May 2019 14:48:44 +0200 Subject: [PATCH 01/11] Remove highlight.js integration --- addon/components/code-snippet.js | 9 +- app/components/code-snippet.js | 7 +- ember-cli-build.js | 6 +- index.js | 33 +----- package.json | 1 + tests/dummy/app/templates/application.hbs | 31 +++++- vendor/highlight-style.css | 121 ---------------------- vendor/highlight.pack.js | 2 - yarn.lock | 70 ++++++++++++- 9 files changed, 105 insertions(+), 175 deletions(-) delete mode 100644 vendor/highlight-style.css delete mode 100644 vendor/highlight.pack.js diff --git a/addon/components/code-snippet.js b/addon/components/code-snippet.js index 592692f..f9e3def 100644 --- a/addon/components/code-snippet.js +++ b/addon/components/code-snippet.js @@ -1,8 +1,7 @@ import layout from '../templates/components/code-snippet'; import Component from '@ember/component'; import { computed } from '@ember/object'; - -const Highlight = self.require('highlight.js'); +import snippets from 'ember-code-snippet/snippets'; export default Component.extend({ layout, @@ -30,7 +29,7 @@ export default Component.extend({ source: computed('name', function(){ let snippet = this.get('name') .split('/') - .reduce((dir, name) => dir && dir[name], this.snippets); + .reduce((dir, name) => dir && dir[name], snippets); return this._unindent( (snippet || "") @@ -39,10 +38,6 @@ export default Component.extend({ ); }), - didInsertElement(){ - Highlight.highlightBlock(this.get('element')); - }, - language: computed('name', function(){ let m = /\.(\w+)$/i.exec(this.get('name')); if (m) { diff --git a/app/components/code-snippet.js b/app/components/code-snippet.js index 709a5e4..516d3c5 100644 --- a/app/components/code-snippet.js +++ b/app/components/code-snippet.js @@ -1,6 +1 @@ -import CodeSnippet from 'ember-code-snippet/components/code-snippet'; -import snippets from "../snippets"; - -export default CodeSnippet.extend({ - snippets: snippets -}); \ No newline at end of file +export { default } from 'ember-code-snippet/components/code-snippet'; diff --git a/ember-cli-build.js b/ember-cli-build.js index 879e3a3..da5a6f8 100644 --- a/ember-cli-build.js +++ b/ember-cli-build.js @@ -4,7 +4,11 @@ const EmberAddon = require('ember-cli/lib/broccoli/ember-addon'); module.exports = function(defaults) { let app = new EmberAddon(defaults, { - snippetSearchPaths: ['tests/integration'] + snippetSearchPaths: ['tests/integration', 'tests/dummy'], + 'ember-prism': { + 'components': ['markup-templating', 'handlebars', 'javascript'], + 'plugins': ['line-highlight'] + } }); /* diff --git a/index.js b/index.js index d4b11fc..50bdd67 100644 --- a/index.js +++ b/index.js @@ -37,25 +37,7 @@ module.exports = { return app.options.includeFileExtensionInSnippetNames !== false; }, - includeHighlightJS() { - let app = findHost(this); - if (typeof app.options.includeHighlightJS === 'boolean') { - return app.options.includeHighlightJS; - } else { - return true; - } - }, - - includeHighlightStyle() { - let app = findHost(this); - if (typeof app.options.includeHighlightStyle === 'boolean') { - return app.options.includeHighlightStyle; - } else { - return true; - } - }, - - treeForApp(tree) { + treeForAddon(tree) { let snippets = mergeTrees(this.snippetPaths().filter(function(path){ return fs.existsSync(path); })); @@ -74,17 +56,6 @@ module.exports = { outputFile: 'snippets.js' }); - return mergeTrees([tree, snippets]); - }, - - included(app) { - if (this.includeHighlightJS()) { - app.import('vendor/highlight.pack.js', { using: [ - { transformation: 'amd', as: 'highlight.js' } - ] } ); - } - if (this.includeHighlightStyle()) { - app.import('vendor/highlight-style.css'); - } + return this._super.treeForAddon.call(this, mergeTrees([tree, snippets])); } }; diff --git a/package.json b/package.json index 6ae794f..ca04da9 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "ember-export-application-global": "^2.0.0", "ember-load-initializers": "^2.0.0", "ember-maybe-import-regenerator": "^0.1.6", + "ember-prism": "^0.4.0", "ember-qunit": "^4.4.1", "ember-resolver": "^5.0.1", "ember-source": "~3.10.0", diff --git a/tests/dummy/app/templates/application.hbs b/tests/dummy/app/templates/application.hbs index 5230580..af80c24 100644 --- a/tests/dummy/app/templates/application.hbs +++ b/tests/dummy/app/templates/application.hbs @@ -1,3 +1,30 @@ -

Welcome to Ember

+

Welcome to ember-code-snippet

-{{outlet}} \ No newline at end of file +

Static snippet

+ + +

I am a handlebars template!

+

The value is: {{val}}

+
+ {{input value=val}} +
+ + +{{code-snippet name="static.hbs"}} + +

Dynamic snippet

+ +
+ + {{input id="type" value=type}} +
+ + +

I am a handlebars template!

+

The value is: {{val}}

+
+ {{input value=val type=type}} +
+ + +{{#code-block language="handlebars"}}{{code-snippet name="dynamic.hbs"}}{{/code-block}} \ No newline at end of file diff --git a/vendor/highlight-style.css b/vendor/highlight-style.css deleted file mode 100644 index b50e3b8..0000000 --- a/vendor/highlight-style.css +++ /dev/null @@ -1,121 +0,0 @@ -.hljs { - display: block; - overflow-x: auto; - padding: 0.5em; - color: #333; - background: #f8f8f8; -} - -.hljs-comment, -.hljs-template_comment, -.diff .hljs-header, -.hljs-javadoc { - color: #998; - font-style: italic; -} - -.hljs-keyword, -.css .rule .hljs-keyword, -.hljs-winutils, -.javascript .hljs-title, -.nginx .hljs-title, -.hljs-subst, -.hljs-request, -.hljs-status { - color: #333; - font-weight: bold; -} - -.hljs-number, -.hljs-hexcolor, -.ruby .hljs-constant { - color: #099; -} - -.hljs-string, -.hljs-tag .hljs-value, -.hljs-phpdoc, -.tex .hljs-formula { - color: #d14; -} - -.hljs-title, -.hljs-id, -.coffeescript .hljs-params, -.scss .hljs-preprocessor { - color: #900; - font-weight: bold; -} - -.javascript .hljs-title, -.lisp .hljs-title, -.clojure .hljs-title, -.hljs-subst { - font-weight: normal; -} - -.hljs-class .hljs-title, -.haskell .hljs-type, -.vhdl .hljs-literal, -.tex .hljs-command { - color: #458; - font-weight: bold; -} - -.hljs-tag, -.hljs-tag .hljs-title, -.hljs-rules .hljs-property, -.django .hljs-tag .hljs-keyword { - color: #000080; - font-weight: normal; -} - -.hljs-attribute, -.hljs-variable, -.lisp .hljs-body { - color: #008080; -} - -.hljs-regexp { - color: #009926; -} - -.hljs-symbol, -.ruby .hljs-symbol .hljs-string, -.lisp .hljs-keyword, -.tex .hljs-special, -.hljs-prompt { - color: #990073; -} - -.hljs-built_in, -.lisp .hljs-title, -.clojure .hljs-built_in { - color: #0086b3; -} - -.hljs-preprocessor, -.hljs-pragma, -.hljs-pi, -.hljs-doctype, -.hljs-shebang, -.hljs-cdata { - color: #999; - font-weight: bold; -} - -.hljs-deletion { - background: #fdd; -} - -.hljs-addition { - background: #dfd; -} - -.diff .hljs-change { - background: #0086b3; -} - -.hljs-chunk { - color: #aaa; -} \ No newline at end of file diff --git a/vendor/highlight.pack.js b/vendor/highlight.pack.js deleted file mode 100644 index 52972b9..0000000 --- a/vendor/highlight.pack.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! highlight.js v9.12.0 | BSD3 License | git.io/hljslicense */ -!function(e){var n="object"==typeof window&&window||"object"==typeof self&&self;"undefined"!=typeof exports?e(exports):n&&(n.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return n.hljs}))}(function(e){function n(e){return e.replace(/&/g,"&").replace(//g,">")}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0===t.index}function a(e){return k.test(e)}function i(e){var n,t,r,i,o=e.className+" ";if(o+=e.parentNode?e.parentNode.className:"",t=B.exec(o))return w(t[1])?t[1]:"no-highlight";for(o=o.split(/\s+/),n=0,r=o.length;r>n;n++)if(i=o[n],a(i)||w(i))return i}function o(e){var n,t={},r=Array.prototype.slice.call(arguments,1);for(n in e)t[n]=e[n];return r.forEach(function(e){for(n in e)t[n]=e[n]}),t}function u(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i=i.nextSibling)3===i.nodeType?a+=i.nodeValue.length:1===i.nodeType&&(n.push({event:"start",offset:a,node:i}),a=r(i,a),t(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:i}));return a}(e,0),n}function c(e,r,a){function i(){return e.length&&r.length?e[0].offset!==r[0].offset?e[0].offset"}function u(e){s+=""}function c(e){("start"===e.event?o:u)(e.node)}for(var l=0,s="",f=[];e.length||r.length;){var g=i();if(s+=n(a.substring(l,g[0].offset)),l=g[0].offset,g===e){f.reverse().forEach(u);do c(g.splice(0,1)[0]),g=i();while(g===e&&g.length&&g[0].offset===l);f.reverse().forEach(o)}else"start"===g[0].event?f.push(g[0].node):f.pop(),c(g.splice(0,1)[0])}return s+n(a.substr(l))}function l(e){return e.v&&!e.cached_variants&&(e.cached_variants=e.v.map(function(n){return o(e,{v:null},n)})),e.cached_variants||e.eW&&[o(e)]||[e]}function s(e){function n(e){return e&&e.source||e}function t(t,r){return new RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,i){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var o={},u=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");o[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?u("keyword",a.k):x(a.k).forEach(function(e){u(e,a.k[e])}),a.k=o}a.lR=t(a.l||/\w+/,!0),i&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||"",a.eW&&i.tE&&(a.tE+=(a.e?"|":"")+i.tE)),a.i&&(a.iR=t(a.i)),null==a.r&&(a.r=1),a.c||(a.c=[]),a.c=Array.prototype.concat.apply([],a.c.map(function(e){return l("self"===e?a:e)})),a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,i);var c=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=c.length?t(c.join("|"),!0):{exec:function(){return null}}}}r(e)}function f(e,t,a,i){function o(e,n){var t,a;for(t=0,a=n.c.length;a>t;t++)if(r(n.c[t].bR,e))return n.c[t]}function u(e,n){if(r(e.eR,n)){for(;e.endsParent&&e.parent;)e=e.parent;return e}return e.eW?u(e.parent,n):void 0}function c(e,n){return!a&&r(n.iR,e)}function l(e,n){var t=N.cI?n[0].toLowerCase():n[0];return e.k.hasOwnProperty(t)&&e.k[t]}function p(e,n,t,r){var a=r?"":I.classPrefix,i='',i+n+o}function h(){var e,t,r,a;if(!E.k)return n(k);for(a="",t=0,E.lR.lastIndex=0,r=E.lR.exec(k);r;)a+=n(k.substring(t,r.index)),e=l(E,r),e?(B+=e[1],a+=p(e[0],n(r[0]))):a+=n(r[0]),t=E.lR.lastIndex,r=E.lR.exec(k);return a+n(k.substr(t))}function d(){var e="string"==typeof E.sL;if(e&&!y[E.sL])return n(k);var t=e?f(E.sL,k,!0,x[E.sL]):g(k,E.sL.length?E.sL:void 0);return E.r>0&&(B+=t.r),e&&(x[E.sL]=t.top),p(t.language,t.value,!1,!0)}function b(){L+=null!=E.sL?d():h(),k=""}function v(e){L+=e.cN?p(e.cN,"",!0):"",E=Object.create(e,{parent:{value:E}})}function m(e,n){if(k+=e,null==n)return b(),0;var t=o(n,E);if(t)return t.skip?k+=n:(t.eB&&(k+=n),b(),t.rB||t.eB||(k=n)),v(t,n),t.rB?0:n.length;var r=u(E,n);if(r){var a=E;a.skip?k+=n:(a.rE||a.eE||(k+=n),b(),a.eE&&(k=n));do E.cN&&(L+=C),E.skip||(B+=E.r),E=E.parent;while(E!==r.parent);return r.starts&&v(r.starts,""),a.rE?0:n.length}if(c(n,E))throw new Error('Illegal lexeme "'+n+'" for mode "'+(E.cN||"")+'"');return k+=n,n.length||1}var N=w(e);if(!N)throw new Error('Unknown language: "'+e+'"');s(N);var R,E=i||N,x={},L="";for(R=E;R!==N;R=R.parent)R.cN&&(L=p(R.cN,"",!0)+L);var k="",B=0;try{for(var M,j,O=0;;){if(E.t.lastIndex=O,M=E.t.exec(t),!M)break;j=m(t.substring(O,M.index),M[0]),O=M.index+j}for(m(t.substr(O)),R=E;R.parent;R=R.parent)R.cN&&(L+=C);return{r:B,value:L,language:e,top:E}}catch(T){if(T.message&&-1!==T.message.indexOf("Illegal"))return{r:0,value:n(t)};throw T}}function g(e,t){t=t||I.languages||x(y);var r={r:0,value:n(e)},a=r;return t.filter(w).forEach(function(n){var t=f(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}),a.language&&(r.second_best=a),r}function p(e){return I.tabReplace||I.useBR?e.replace(M,function(e,n){return I.useBR&&"\n"===e?"
":I.tabReplace?n.replace(/\t/g,I.tabReplace):""}):e}function h(e,n,t){var r=n?L[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}function d(e){var n,t,r,o,l,s=i(e);a(s)||(I.useBR?(n=document.createElementNS("http://www.w3.org/1999/xhtml","div"),n.innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n")):n=e,l=n.textContent,r=s?f(s,l,!0):g(l),t=u(n),t.length&&(o=document.createElementNS("http://www.w3.org/1999/xhtml","div"),o.innerHTML=r.value,r.value=c(t,u(o),l)),r.value=p(r.value),e.innerHTML=r.value,e.className=h(e.className,s,r.language),e.result={language:r.language,re:r.r},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.r}))}function b(e){I=o(I,e)}function v(){if(!v.called){v.called=!0;var e=document.querySelectorAll("pre code");E.forEach.call(e,d)}}function m(){addEventListener("DOMContentLoaded",v,!1),addEventListener("load",v,!1)}function N(n,t){var r=y[n]=t(e);r.aliases&&r.aliases.forEach(function(e){L[e]=n})}function R(){return x(y)}function w(e){return e=(e||"").toLowerCase(),y[e]||y[L[e]]}var E=[],x=Object.keys,y={},L={},k=/^(no-?highlight|plain|text)$/i,B=/\blang(?:uage)?-([\w-]+)\b/i,M=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,C="
",I={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0};return e.highlight=f,e.highlightAuto=g,e.fixMarkup=p,e.highlightBlock=d,e.configure=b,e.initHighlighting=v,e.initHighlightingOnLoad=m,e.registerLanguage=N,e.listLanguages=R,e.getLanguage=w,e.inherit=o,e.IR="[a-zA-Z]\\w*",e.UIR="[a-zA-Z_]\\w*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},e.C=function(n,t,r){var a=e.inherit({cN:"comment",b:n,e:t,c:[]},r||{});return a.c.push(e.PWM),a.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),a},e.CLCM=e.C("//","$"),e.CBCM=e.C("/\\*","\\*/"),e.HCM=e.C("#","$"),e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e.METHOD_GUARD={b:"\\.\\s*"+e.UIR,r:0},e});hljs.registerLanguage("json",function(e){var i={literal:"true false null"},n=[e.QSM,e.CNM],r={e:",",eW:!0,eE:!0,c:n,k:i},t={b:"{",e:"}",c:[{cN:"attr",b:/"/,e:/"/,c:[e.BE],i:"\\n"},e.inherit(r,{b:/:/})],i:"\\S"},c={b:"\\[",e:"\\]",c:[e.inherit(r)],i:"\\S"};return n.splice(n.length,0,t,c),{c:n,k:i,i:"\\S"}});hljs.registerLanguage("javascript",function(e){var r="[A-Za-z$_][0-9A-Za-z$_]*",t={keyword:"in of if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const export super debugger as async await static import from as",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect Promise"},a={cN:"number",v:[{b:"\\b(0[bB][01]+)"},{b:"\\b(0[oO][0-7]+)"},{b:e.CNR}],r:0},n={cN:"subst",b:"\\$\\{",e:"\\}",k:t,c:[]},c={cN:"string",b:"`",e:"`",c:[e.BE,n]};n.c=[e.ASM,e.QSM,c,a,e.RM];var s=n.c.concat([e.CBCM,e.CLCM]);return{aliases:["js","jsx"],k:t,c:[{cN:"meta",r:10,b:/^\s*['"]use (strict|asm)['"]/},{cN:"meta",b:/^#!/,e:/$/},e.ASM,e.QSM,c,e.CLCM,e.CBCM,a,{b:/[{,]\s*/,r:0,c:[{b:r+"\\s*:",rB:!0,r:0,c:[{cN:"attr",b:r,r:0}]}]},{b:"("+e.RSR+"|\\b(case|return|throw)\\b)\\s*",k:"return throw case",c:[e.CLCM,e.CBCM,e.RM,{cN:"function",b:"(\\(.*?\\)|"+r+")\\s*=>",rB:!0,e:"\\s*=>",c:[{cN:"params",v:[{b:r},{b:/\(\s*\)/},{b:/\(/,e:/\)/,eB:!0,eE:!0,k:t,c:s}]}]},{b://,sL:"xml",c:[{b:/<\w+\s*\/>/,skip:!0},{b:/<\w+/,e:/(\/\w+|\w+\/)>/,skip:!0,c:[{b:/<\w+\s*\/>/,skip:!0},"self"]}]}],r:0},{cN:"function",bK:"function",e:/\{/,eE:!0,c:[e.inherit(e.TM,{b:r}),{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,c:s}],i:/\[|%/},{b:/\$[(.]/},e.METHOD_GUARD,{cN:"class",bK:"class",e:/[{;=]/,eE:!0,i:/[:"\[\]]/,c:[{bK:"extends"},e.UTM]},{bK:"constructor",e:/\{/,eE:!0}],i:/#(?!!)/}});hljs.registerLanguage("xml",function(s){var e="[A-Za-z0-9\\._:-]+",t={eW:!0,i:/`]+/}]}]}]};return{aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist"],cI:!0,c:[{cN:"meta",b:"",r:10,c:[{b:"\\[",e:"\\]"}]},s.C("",{r:10}),{b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{b:/<\?(php)?/,e:/\?>/,sL:"php",c:[{b:"/\\*",e:"\\*/",skip:!0}]},{cN:"tag",b:"|$)",e:">",k:{name:"style"},c:[t],starts:{e:"",rE:!0,sL:["css","xml"]}},{cN:"tag",b:"|$)",e:">",k:{name:"script"},c:[t],starts:{e:"",rE:!0,sL:["actionscript","javascript","handlebars","xml"]}},{cN:"meta",v:[{b:/<\?xml/,e:/\?>/,r:10},{b:/<\?\w+/,e:/\?>/}]},{cN:"tag",b:"",c:[{cN:"name",b:/[^\/><\s]+/,r:0},t]}]}});hljs.registerLanguage("handlebars",function(e){var a={"builtin-name":"each in with if else unless bindattr action collection debugger log outlet template unbound view yield"};return{aliases:["hbs","html.hbs","html.handlebars"],cI:!0,sL:"xml",c:[e.C("{{!(--)?","(--)?}}"),{cN:"template-tag",b:/\{\{[#\/]/,e:/\}\}/,c:[{cN:"name",b:/[a-zA-Z\.-]+/,k:a,starts:{eW:!0,r:0,c:[e.QSM]}}]},{cN:"template-variable",b:/\{\{/,e:/\}\}/,k:a}]}});hljs.registerLanguage("markdown",function(e){return{aliases:["md","mkdown","mkd"],c:[{cN:"section",v:[{b:"^#{1,6}",e:"$"},{b:"^.+?\\n[=-]{2,}$"}]},{b:"<",e:">",sL:"xml",r:0},{cN:"bullet",b:"^([*+-]|(\\d+\\.))\\s+"},{cN:"strong",b:"[*_]{2}.+?[*_]{2}"},{cN:"emphasis",v:[{b:"\\*.+?\\*"},{b:"_.+?_",r:0}]},{cN:"quote",b:"^>\\s+",e:"$"},{cN:"code",v:[{b:"^```w*s*$",e:"^```s*$"},{b:"`.+?`"},{b:"^( {4}| )",e:"$",r:0}]},{b:"^[-\\*]{3,}",e:"$"},{b:"\\[.+?\\][\\(\\[].*?[\\)\\]]",rB:!0,c:[{cN:"string",b:"\\[",e:"\\]",eB:!0,rE:!0,r:0},{cN:"link",b:"\\]\\(",e:"\\)",eB:!0,eE:!0},{cN:"symbol",b:"\\]\\[",e:"\\]",eB:!0,eE:!0}],r:10},{b:/^\[[^\n]+\]:/,rB:!0,c:[{cN:"symbol",b:/\[/,e:/\]/,eB:!0,eE:!0},{cN:"link",b:/:\s*/,e:/$/,eB:!0}]}]}});hljs.registerLanguage("htmlbars",function(e){var a="action collection component concat debugger each each-in else get hash if input link-to loc log mut outlet partial query-params render textarea unbound unless with yield view",t={i:/\}\}/,b:/[a-zA-Z0-9_]+=/,rB:!0,r:0,c:[{cN:"attr",b:/[a-zA-Z0-9_]+/}]},i=({i:/\}\}/,b:/\)/,e:/\)/,c:[{b:/[a-zA-Z\.\-]+/,k:{built_in:a},starts:{eW:!0,r:0,c:[e.QSM]}}]},{eW:!0,r:0,k:{keyword:"as",built_in:a},c:[e.QSM,t,e.NM]});return{cI:!0,sL:"xml",c:[e.C("{{!(--)?","(--)?}}"),{cN:"template-tag",b:/\{\{[#\/]/,e:/\}\}/,c:[{cN:"name",b:/[a-zA-Z\.\-]+/,k:{"builtin-name":a},starts:i}]},{cN:"template-variable",b:/\{\{[a-zA-Z][a-zA-Z\-]+/,e:/\}\}/,k:{keyword:"as",built_in:a},c:[e.QSM]}]}});hljs.registerLanguage("coffeescript",function(e){var c={keyword:"in if for while finally new do return else break catch instanceof throw try this switch continue typeof delete debugger super yield import export from as default await then unless until loop of by when and or is isnt not",literal:"true false null undefined yes no on off",built_in:"npm require console print module global window document"},n="[A-Za-z$_][0-9A-Za-z$_]*",r={cN:"subst",b:/#\{/,e:/}/,k:c},i=[e.BNM,e.inherit(e.CNM,{starts:{e:"(\\s*/)?",r:0}}),{cN:"string",v:[{b:/'''/,e:/'''/,c:[e.BE]},{b:/'/,e:/'/,c:[e.BE]},{b:/"""/,e:/"""/,c:[e.BE,r]},{b:/"/,e:/"/,c:[e.BE,r]}]},{cN:"regexp",v:[{b:"///",e:"///",c:[r,e.HCM]},{b:"//[gim]*",r:0},{b:/\/(?![ *])(\\\/|.)*?\/[gim]*(?=\W|$)/}]},{b:"@"+n},{sL:"javascript",eB:!0,eE:!0,v:[{b:"```",e:"```"},{b:"`",e:"`"}]}];r.c=i;var s=e.inherit(e.TM,{b:n}),t="(\\(.*\\))?\\s*\\B[-=]>",o={cN:"params",b:"\\([^\\(]",rB:!0,c:[{b:/\(/,e:/\)/,k:c,c:["self"].concat(i)}]};return{aliases:["coffee","cson","iced"],k:c,i:/\/\*/,c:i.concat([e.C("###","###"),e.HCM,{cN:"function",b:"^\\s*"+n+"\\s*=\\s*"+t,e:"[-=]>",rB:!0,c:[s,o]},{b:/[:\(,=]\s*/,r:0,c:[{cN:"function",b:t,e:"[-=]>",rB:!0,c:[o]}]},{cN:"class",bK:"class",e:"$",i:/[:="\[\]]/,c:[{bK:"extends",eW:!0,i:/[:="\[\]]/,c:[s]},s]},{b:n+":",e:":",rB:!0,rE:!0,r:0}])}});hljs.registerLanguage("css",function(e){var c="[a-zA-Z-][a-zA-Z0-9_-]*",t={b:/[A-Z\_\.\-]+\s*:/,rB:!0,e:";",eW:!0,c:[{cN:"attribute",b:/\S/,e:":",eE:!0,starts:{eW:!0,eE:!0,c:[{b:/[\w-]+\(/,rB:!0,c:[{cN:"built_in",b:/[\w-]+/},{b:/\(/,e:/\)/,c:[e.ASM,e.QSM]}]},e.CSSNM,e.QSM,e.ASM,e.CBCM,{cN:"number",b:"#[0-9A-Fa-f]+"},{cN:"meta",b:"!important"}]}}]};return{cI:!0,i:/[=\/|'\$]/,c:[e.CBCM,{cN:"selector-id",b:/#[A-Za-z0-9_-]+/},{cN:"selector-class",b:/\.[A-Za-z0-9_-]+/},{cN:"selector-attr",b:/\[/,e:/\]/,i:"$"},{cN:"selector-pseudo",b:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{b:"@(font-face|page)",l:"[a-z-]+",k:"font-face page"},{b:"@",e:"[{;]",i:/:/,c:[{cN:"keyword",b:/\w+/},{b:/\s/,eW:!0,eE:!0,r:0,c:[e.ASM,e.QSM,e.CSSNM]}]},{cN:"selector-tag",b:c,r:0},{b:"{",e:"}",i:/\S/,c:[e.CBCM,t]}]}}); \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 14dda6c..a5e97f9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2035,7 +2035,7 @@ broccoli-lint-eslint@^5.0.0: lodash.defaultsdeep "^4.6.0" md5-hex "^2.0.0" -broccoli-merge-trees@^1.0.0: +broccoli-merge-trees@^1.0.0, broccoli-merge-trees@^1.1.1: version "1.2.4" resolved "https://registry.yarnpkg.com/broccoli-merge-trees/-/broccoli-merge-trees-1.2.4.tgz#a001519bb5067f06589d91afa2942445a2d0fdb5" integrity sha1-oAFRm7UGfwZYnZGvopQkRaLQ/bU= @@ -2502,6 +2502,15 @@ cli-width@^2.0.0: resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= +clipboard@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.4.tgz#836dafd66cf0fea5d71ce5d5b0bf6e958009112d" + integrity sha512-Vw26VSLRpJfBofiVaFb/I8PVfdI1OxKcYShe6fm0sP/DtmiWQNCjhM/okTvdCo0G+lMMm1rMYbk4IK4x1X+kgQ== + dependencies: + good-listener "^1.2.2" + select "^1.1.2" + tiny-emitter "^2.0.0" + clone-response@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" @@ -2865,6 +2874,11 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" +delegate@^3.1.2: + version "3.2.0" + resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166" + integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw== + delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" @@ -2980,7 +2994,7 @@ ember-cli-babel@^6.0.0-beta.4, ember-cli-babel@^6.0.0-beta.7, ember-cli-babel@^6 ember-cli-version-checker "^2.1.2" semver "^5.5.0" -ember-cli-babel@^7.0.0, ember-cli-babel@^7.4.3, ember-cli-babel@^7.5.0, ember-cli-babel@^7.7.0, ember-cli-babel@^7.7.3: +ember-cli-babel@^7.0.0, ember-cli-babel@^7.1.2, ember-cli-babel@^7.4.3, ember-cli-babel@^7.5.0, ember-cli-babel@^7.7.0, ember-cli-babel@^7.7.3: version "7.7.3" resolved "https://registry.yarnpkg.com/ember-cli-babel/-/ember-cli-babel-7.7.3.tgz#f94709f6727583d18685ca6773a995877b87b8a0" integrity sha512-/LWwyKIoSlZQ7k52P+6agC7AhcOBqPJ5C2u27qXHVVxKvCtg6ahNuRk/KmfZmV4zkuw4EjTZxfJE1PzpFyHkXg== @@ -3055,7 +3069,7 @@ ember-cli-htmlbars-inline-precompile@^2.1.0: heimdalljs-logger "^0.1.9" silent-error "^1.1.0" -ember-cli-htmlbars@^3.0.1: +ember-cli-htmlbars@^3.0.0, ember-cli-htmlbars@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/ember-cli-htmlbars/-/ember-cli-htmlbars-3.0.1.tgz#01e21f0fd05e0a6489154f26614b1041769e3e58" integrity sha512-pyyB2s52vKTXDC5svU3IjU7GRLg2+5O81o9Ui0ZSiBS14US/bZl46H2dwcdSJAK+T+Za36ZkQM9eh1rNwOxfoA== @@ -3083,6 +3097,18 @@ ember-cli-lodash-subset@^2.0.1: resolved "https://registry.yarnpkg.com/ember-cli-lodash-subset/-/ember-cli-lodash-subset-2.0.1.tgz#20cb68a790fe0fde2488ddfd8efbb7df6fe766f2" integrity sha1-IMtop5D+D94kiN39jvu332/nZvI= +ember-cli-node-assets@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/ember-cli-node-assets/-/ember-cli-node-assets-0.2.2.tgz#d2d55626e7cc6619f882d7fe55751f9266022708" + integrity sha1-0tVWJufMZhn4gtf+VXUfkmYCJwg= + dependencies: + broccoli-funnel "^1.0.1" + broccoli-merge-trees "^1.1.1" + broccoli-source "^1.1.0" + debug "^2.2.0" + lodash "^4.5.1" + resolve "^1.1.7" + ember-cli-normalize-entity-name@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/ember-cli-normalize-entity-name/-/ember-cli-normalize-entity-name-1.0.0.tgz#0b14f7bcbc599aa117b5fddc81e4fd03c4bad5b7" @@ -3291,6 +3317,16 @@ ember-maybe-import-regenerator@^0.1.6: ember-cli-babel "^6.0.0-beta.4" regenerator-runtime "^0.9.5" +ember-prism@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/ember-prism/-/ember-prism-0.4.0.tgz#b1f02bed563345ead985ace900b7311a730a7149" + integrity sha512-5WfDBMs2sBAHalFnF+eZ247wBE+uYw4YW3jkRAGmAf/n7nt1yP3lPOwAEKeflxJWae5kunh77Wjk0ANhXwylxw== + dependencies: + ember-cli-babel "^7.1.2" + ember-cli-htmlbars "^3.0.0" + ember-cli-node-assets "^0.2.2" + prismjs "^1.15.0" + ember-qunit@^4.4.1: version "4.4.1" resolved "https://registry.yarnpkg.com/ember-qunit/-/ember-qunit-4.4.1.tgz#3654cadf9fa7e2287fe7b61fc7f19c3eb06222b5" @@ -4282,6 +4318,13 @@ globby@^9.0.0: pify "^4.0.1" slash "^2.0.0" +good-listener@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50" + integrity sha1-1TswzfkxPf+33JoNR3CWqm0UXFA= + dependencies: + delegate "^3.1.2" + got@^6.7.1: version "6.7.1" resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" @@ -5480,7 +5523,7 @@ lodash.values@~2.3.0: dependencies: lodash.keys "~2.3.0" -lodash@^4.17.11, lodash@^4.17.4, lodash@^4.3.0, lodash@^4.6.1: +lodash@^4.17.11, lodash@^4.17.4, lodash@^4.3.0, lodash@^4.5.1, lodash@^4.6.1: version "4.17.11" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== @@ -6257,6 +6300,13 @@ printf@^0.5.1: resolved "https://registry.yarnpkg.com/printf/-/printf-0.5.1.tgz#e0466788260859ed153006dc6867f09ddf240cf3" integrity sha512-UaE/jO0hNsrvPGQEb4LyNzcrJv9Z00tsreBduOSxMtrebvoUhxiEJ4YCHX8YHf6akwfKsC2Gyv5zv47UXhMiLg== +prismjs@^1.15.0: + version "1.16.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.16.0.tgz#406eb2c8aacb0f5f0f1167930cb83835d10a4308" + integrity sha512-OA4MKxjFZHSvZcisLGe14THYsug/nF6O1f0pAJc0KN0wTyAcLqmsbE+lTGKSpyh+9pEW57+k6pg2AfYR+coyHA== + optionalDependencies: + clipboard "^2.0.0" + private@^0.1.6, private@^0.1.8, private@~0.1.5: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" @@ -6647,7 +6697,7 @@ resolve@1.9.0: dependencies: path-parse "^1.0.6" -resolve@^1.1.3, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.3.2, resolve@^1.3.3, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.8.1: +resolve@^1.1.3, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.3.2, resolve@^1.3.3, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.8.1: version "1.11.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.0.tgz#4014870ba296176b86343d50b60f3b50609ce232" integrity sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw== @@ -6759,6 +6809,11 @@ sane@^4.0.0, sane@^4.1.0: minimist "^1.1.1" walker "~1.0.5" +select@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" + integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0= + semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: version "5.7.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" @@ -7320,6 +7375,11 @@ timed-out@^4.0.0, timed-out@^4.0.1: resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= +tiny-emitter@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" + integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== + tiny-lr@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/tiny-lr/-/tiny-lr-1.1.1.tgz#9fa547412f238fedb068ee295af8b682c98b2aab" From 3b5ec22a6a27b495d43284ccc068a2e83d08b91c Mon Sep 17 00:00:00 2001 From: simonihmig Date: Fri, 31 May 2019 15:40:56 +0200 Subject: [PATCH 02/11] Create helpers and utility functions --- addon/-private/extension.js | 4 ++ addon/-private/get-snippet.js | 24 +++++++++ addon/-private/language.js | 27 ++++++++++ addon/-private/unindent.js | 13 +++++ addon/components/code-snippet.js | 60 +-------------------- addon/helpers/get-code-snippet.js | 6 +++ addon/helpers/unindent-code-snippet.js | 6 +++ addon/index.js | 7 +++ addon/templates/components/code-snippet.hbs | 6 ++- app/helpers/get-code-snippet.js | 1 + app/helpers/unindent-code-snippet.js | 1 + tests/dummy/app/templates/application.hbs | 24 ++++++--- 12 files changed, 114 insertions(+), 65 deletions(-) create mode 100644 addon/-private/extension.js create mode 100644 addon/-private/get-snippet.js create mode 100644 addon/-private/language.js create mode 100644 addon/-private/unindent.js create mode 100644 addon/helpers/get-code-snippet.js create mode 100644 addon/helpers/unindent-code-snippet.js create mode 100644 addon/index.js create mode 100644 app/helpers/get-code-snippet.js create mode 100644 app/helpers/unindent-code-snippet.js diff --git a/addon/-private/extension.js b/addon/-private/extension.js new file mode 100644 index 0000000..e171c0a --- /dev/null +++ b/addon/-private/extension.js @@ -0,0 +1,4 @@ +export default function getExtension(name) { + let m = /\.(\w+)$/i.exec(name); + return m ? m[1].toLowerCase() : undefined; +} diff --git a/addon/-private/get-snippet.js b/addon/-private/get-snippet.js new file mode 100644 index 0000000..d7f2e1d --- /dev/null +++ b/addon/-private/get-snippet.js @@ -0,0 +1,24 @@ +import snippets from 'ember-code-snippet/snippets'; +import getLanguage from './language'; +import getExtension from './extension'; +import { assert } from '@ember/debug'; + +export default function getSnippet(name) { + let source = name + .split('/') + .reduce((dir, name) => dir && dir[name], snippets); + assert(`Code snippet with name "${name}" not found.`, source); + + source = source + .replace(/^(\s*\n)*/, '') + .replace(/\s*$/, ''); + + let language = getLanguage(name); + let extension = getExtension(name); + + return { + source, + language, + extension + }; +} \ No newline at end of file diff --git a/addon/-private/language.js b/addon/-private/language.js new file mode 100644 index 0000000..be3f9bd --- /dev/null +++ b/addon/-private/language.js @@ -0,0 +1,27 @@ +import getExtension from './extension'; + +export default function getLanguage(name) { + let ext = getExtension(name); + if (ext) { + switch (ext) { + case 'js': + return 'javascript'; + case 'coffee': + return 'coffeescript'; + case 'hbs': + return 'htmlbars'; + case 'css': + return 'css'; + case 'scss': + return 'scss'; + case 'less': + return 'less'; + case 'emblem': + return 'emblem'; + case 'ts': + return 'typescript'; + default: + return ext; + } + } +} diff --git a/addon/-private/unindent.js b/addon/-private/unindent.js new file mode 100644 index 0000000..a0d0a90 --- /dev/null +++ b/addon/-private/unindent.js @@ -0,0 +1,13 @@ +export default function unindent(src) { + let match, min, lines = src.split("\n").filter(l => l !== ''); + for (let i = 0; i < lines.length; i++) { + match = /^[ \t]*/.exec(lines[i]); + if (match && (typeof min === 'undefined' || min > match[0].length)) { + min = match[0].length; + } + } + if (typeof min !== 'undefined' && min > 0) { + src = src.replace(new RegExp("^[ \t]{" + min + "}", 'gm'), ""); + } + return src; +} diff --git a/addon/components/code-snippet.js b/addon/components/code-snippet.js index f9e3def..a805117 100644 --- a/addon/components/code-snippet.js +++ b/addon/components/code-snippet.js @@ -1,64 +1,8 @@ import layout from '../templates/components/code-snippet'; import Component from '@ember/component'; -import { computed } from '@ember/object'; -import snippets from 'ember-code-snippet/snippets'; export default Component.extend({ layout, - tagName: 'pre', - classNameBindings: ['language'], - unindent: true, - - _unindent(src) { - if (!this.get('unindent')) { - return src; - } - let match, min, lines = src.split("\n").filter(l => l !== ''); - for (let i = 0; i < lines.length; i++) { - match = /^[ \t]*/.exec(lines[i]); - if (match && (typeof min === 'undefined' || min > match[0].length)) { - min = match[0].length; - } - } - if (typeof min !== 'undefined' && min > 0) { - src = src.replace(new RegExp("^[ \t]{" + min + "}", 'gm'), ""); - } - return src; - }, - - source: computed('name', function(){ - let snippet = this.get('name') - .split('/') - .reduce((dir, name) => dir && dir[name], snippets); - - return this._unindent( - (snippet || "") - .replace(/^(\s*\n)*/, '') - .replace(/\s*$/, '') - ); - }), - - language: computed('name', function(){ - let m = /\.(\w+)$/i.exec(this.get('name')); - if (m) { - switch (m[1].toLowerCase()) { - case 'js': - return 'javascript'; - case 'coffee': - return 'coffeescript'; - case 'hbs': - return 'htmlbars'; - case 'css': - return 'css'; - case 'scss': - return 'scss'; - case 'less': - return 'less'; - case 'emblem': - return 'emblem'; - case 'ts': - return 'typescript'; - } - } - }) + tagName: '', + unindent: true }); diff --git a/addon/helpers/get-code-snippet.js b/addon/helpers/get-code-snippet.js new file mode 100644 index 0000000..fa73617 --- /dev/null +++ b/addon/helpers/get-code-snippet.js @@ -0,0 +1,6 @@ +import { helper } from '@ember/component/helper'; +import getSnippet from '../-private/get-snippet'; + +export default helper(function([name]) { + return getSnippet(name); +}); diff --git a/addon/helpers/unindent-code-snippet.js b/addon/helpers/unindent-code-snippet.js new file mode 100644 index 0000000..c234d9b --- /dev/null +++ b/addon/helpers/unindent-code-snippet.js @@ -0,0 +1,6 @@ +import { helper } from '@ember/component/helper'; +import unindent from '../-private/unindent'; + +export default helper(function([source]) { + return unindent(source); +}); diff --git a/addon/index.js b/addon/index.js new file mode 100644 index 0000000..0858186 --- /dev/null +++ b/addon/index.js @@ -0,0 +1,7 @@ +import getSnippet from './-private/get-snippet'; +import unindent from './-private/unindent'; + +export { + getSnippet, + unindent +}; diff --git a/addon/templates/components/code-snippet.hbs b/addon/templates/components/code-snippet.hbs index 3a73287..4abf2bd 100644 --- a/addon/templates/components/code-snippet.hbs +++ b/addon/templates/components/code-snippet.hbs @@ -1 +1,5 @@ -{{source}} +{{#let (get-code-snippet name) as |snippet|}} +
+{{if unindent (unindent-code-snippet snippet.source) snippet.source}}
+
+{{/let}} \ No newline at end of file diff --git a/app/helpers/get-code-snippet.js b/app/helpers/get-code-snippet.js new file mode 100644 index 0000000..cc95487 --- /dev/null +++ b/app/helpers/get-code-snippet.js @@ -0,0 +1 @@ +export { default, getCodeSnippet } from 'ember-code-snippet/helpers/get-code-snippet'; diff --git a/app/helpers/unindent-code-snippet.js b/app/helpers/unindent-code-snippet.js new file mode 100644 index 0000000..9ab8981 --- /dev/null +++ b/app/helpers/unindent-code-snippet.js @@ -0,0 +1 @@ +export { default, unindentCodeSnippet } from 'ember-code-snippet/helpers/unindent-code-snippet'; diff --git a/tests/dummy/app/templates/application.hbs b/tests/dummy/app/templates/application.hbs index af80c24..5ff194e 100644 --- a/tests/dummy/app/templates/application.hbs +++ b/tests/dummy/app/templates/application.hbs @@ -3,15 +3,21 @@

Static snippet

-

I am a handlebars template!

-

The value is: {{val}}

-
- {{input value=val}} -
+

I am a handlebars template!

+

The value is: {{val}}

+
+ {{input value=val}} +
+

Plain:

+ {{code-snippet name="static.hbs"}} +

Prism.js

+ +{{#code-block language="handlebars"}}{{code-snippet name="dynamic.hbs"}}{{/code-block}} +

Dynamic snippet

@@ -27,4 +33,10 @@
-{{#code-block language="handlebars"}}{{code-snippet name="dynamic.hbs"}}{{/code-block}} \ No newline at end of file +{{#code-block language="handlebars"}} + {{#let (get-code-snippet "dynamic.hbs") as |snippet|}} +
+{{unindent-code-snippet snippet.source}}
+
+ {{/let}} +{{/code-block}} \ No newline at end of file From 739d69972b26225f42ff01164b497d34f378a741 Mon Sep 17 00:00:00 2001 From: simonihmig Date: Fri, 31 May 2019 16:01:50 +0200 Subject: [PATCH 03/11] Add dynamic helper --- addon/helpers/dynamic-code-snippet.js | 27 +++++++++++++++++++++ addon/helpers/get-code-snippet.js | 8 ++++-- addon/helpers/unindent-code-snippet.js | 6 ----- addon/templates/components/code-snippet.hbs | 4 +-- app/helpers/dynamic-code-snippet.js | 1 + app/helpers/get-code-snippet.js | 2 +- app/helpers/unindent-code-snippet.js | 1 - tests/dummy/app/controllers/application.js | 5 ++++ tests/dummy/app/templates/application.hbs | 21 ++++++++++------ 9 files changed, 55 insertions(+), 20 deletions(-) create mode 100644 addon/helpers/dynamic-code-snippet.js delete mode 100644 addon/helpers/unindent-code-snippet.js create mode 100644 app/helpers/dynamic-code-snippet.js delete mode 100644 app/helpers/unindent-code-snippet.js create mode 100644 tests/dummy/app/controllers/application.js diff --git a/addon/helpers/dynamic-code-snippet.js b/addon/helpers/dynamic-code-snippet.js new file mode 100644 index 0000000..82fe09d --- /dev/null +++ b/addon/helpers/dynamic-code-snippet.js @@ -0,0 +1,27 @@ +import { helper } from '@ember/component/helper'; +import { get } from '@ember/object'; + +export default helper(function([source], { language, dynamic, quote = '"'}) { + Object.keys(dynamic).forEach((property) => { + let propertyValue = get(dynamic, property); + let type = typeof propertyValue; + + let quotedValue = type === 'string' ? `${quote}${propertyValue}${quote}` : propertyValue; + + switch (language) { + case 'handlebars': + case 'htmlbars': + source = source.replace( + new RegExp(`(<\\w*[^>]*\\s@[^=]+=){{${property}}}([^>]*>)`, 'g'), + type === 'string' ? `$1${quotedValue}$2` : `$1{{${propertyValue}}}$2` + ); + source = source.replace(new RegExp(`{{${property}}}`, 'g'), propertyValue); + source = source.replace(new RegExp(`=${property}`, 'g'), `=${quotedValue}`); + break; + default: + source = source.replace(new RegExp(`{{${property}}}`, 'g'), quotedValue); + } + }); + + return source; +}); diff --git a/addon/helpers/get-code-snippet.js b/addon/helpers/get-code-snippet.js index fa73617..c7c02b1 100644 --- a/addon/helpers/get-code-snippet.js +++ b/addon/helpers/get-code-snippet.js @@ -1,6 +1,10 @@ import { helper } from '@ember/component/helper'; import getSnippet from '../-private/get-snippet'; +import unindentSource from '../-private/unindent'; -export default helper(function([name]) { - return getSnippet(name); +export default helper(function([name], { unindent = true }) { + let snippet = getSnippet(name); + return unindent + ? { ...snippet, source: unindentSource(snippet.source) } + : snippet; }); diff --git a/addon/helpers/unindent-code-snippet.js b/addon/helpers/unindent-code-snippet.js deleted file mode 100644 index c234d9b..0000000 --- a/addon/helpers/unindent-code-snippet.js +++ /dev/null @@ -1,6 +0,0 @@ -import { helper } from '@ember/component/helper'; -import unindent from '../-private/unindent'; - -export default helper(function([source]) { - return unindent(source); -}); diff --git a/addon/templates/components/code-snippet.hbs b/addon/templates/components/code-snippet.hbs index 4abf2bd..be926af 100644 --- a/addon/templates/components/code-snippet.hbs +++ b/addon/templates/components/code-snippet.hbs @@ -1,5 +1,5 @@ -{{#let (get-code-snippet name) as |snippet|}} +{{#let (get-code-snippet name unindent=unindent) as |snippet|}}
-{{if unindent (unindent-code-snippet snippet.source) snippet.source}}
+{{snippet.source}}
 
{{/let}} \ No newline at end of file diff --git a/app/helpers/dynamic-code-snippet.js b/app/helpers/dynamic-code-snippet.js new file mode 100644 index 0000000..66fbdf8 --- /dev/null +++ b/app/helpers/dynamic-code-snippet.js @@ -0,0 +1 @@ +export { default } from 'ember-code-snippet/helpers/dynamic-code-snippet'; diff --git a/app/helpers/get-code-snippet.js b/app/helpers/get-code-snippet.js index cc95487..1a435df 100644 --- a/app/helpers/get-code-snippet.js +++ b/app/helpers/get-code-snippet.js @@ -1 +1 @@ -export { default, getCodeSnippet } from 'ember-code-snippet/helpers/get-code-snippet'; +export { default } from 'ember-code-snippet/helpers/get-code-snippet'; diff --git a/app/helpers/unindent-code-snippet.js b/app/helpers/unindent-code-snippet.js deleted file mode 100644 index 9ab8981..0000000 --- a/app/helpers/unindent-code-snippet.js +++ /dev/null @@ -1 +0,0 @@ -export { default, unindentCodeSnippet } from 'ember-code-snippet/helpers/unindent-code-snippet'; diff --git a/tests/dummy/app/controllers/application.js b/tests/dummy/app/controllers/application.js new file mode 100644 index 0000000..8e1b7c5 --- /dev/null +++ b/tests/dummy/app/controllers/application.js @@ -0,0 +1,5 @@ +import Controller from '@ember/controller'; + +export default Controller.extend({ + inputType: 'text' +}); diff --git a/tests/dummy/app/templates/application.hbs b/tests/dummy/app/templates/application.hbs index 5ff194e..19e480f 100644 --- a/tests/dummy/app/templates/application.hbs +++ b/tests/dummy/app/templates/application.hbs @@ -21,22 +21,27 @@

Dynamic snippet

- - {{input id="type" value=type}} + + {{input id="type" value=inputType}}
+
+

I am a handlebars template!

The value is: {{val}}

- {{input value=val type=type}} + {{input value=val type=inputType}}
-{{#code-block language="handlebars"}} - {{#let (get-code-snippet "dynamic.hbs") as |snippet|}} +{{#let (get-code-snippet "dynamic.hbs") as |snippet|}}
-{{unindent-code-snippet snippet.source}}
+{{dynamic-code-snippet snippet.source
+  language=snippet.language
+  dynamic=(hash
+    inputType=inputType
+  )
+}}
 
- {{/let}} -{{/code-block}} \ No newline at end of file +{{/let}} From 0374bcbeb9178d0925c81de231c904efb714ee88 Mon Sep 17 00:00:00 2001 From: simonihmig Date: Mon, 10 Jun 2019 20:49:42 +0200 Subject: [PATCH 04/11] Removed code-snippet component --- addon/components/code-snippet.js | 8 ------ addon/templates/components/code-snippet.hbs | 5 ---- app/components/code-snippet.js | 1 - tests/dummy/app/templates/application.hbs | 6 +++-- .../components/code-snippet-test.js | 27 ------------------- 5 files changed, 4 insertions(+), 43 deletions(-) delete mode 100644 addon/components/code-snippet.js delete mode 100644 addon/templates/components/code-snippet.hbs delete mode 100644 app/components/code-snippet.js delete mode 100644 tests/integration/components/code-snippet-test.js diff --git a/addon/components/code-snippet.js b/addon/components/code-snippet.js deleted file mode 100644 index a805117..0000000 --- a/addon/components/code-snippet.js +++ /dev/null @@ -1,8 +0,0 @@ -import layout from '../templates/components/code-snippet'; -import Component from '@ember/component'; - -export default Component.extend({ - layout, - tagName: '', - unindent: true -}); diff --git a/addon/templates/components/code-snippet.hbs b/addon/templates/components/code-snippet.hbs deleted file mode 100644 index be926af..0000000 --- a/addon/templates/components/code-snippet.hbs +++ /dev/null @@ -1,5 +0,0 @@ -{{#let (get-code-snippet name unindent=unindent) as |snippet|}} -
-{{snippet.source}}
-
-{{/let}} \ No newline at end of file diff --git a/app/components/code-snippet.js b/app/components/code-snippet.js deleted file mode 100644 index 516d3c5..0000000 --- a/app/components/code-snippet.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from 'ember-code-snippet/components/code-snippet'; diff --git a/tests/dummy/app/templates/application.hbs b/tests/dummy/app/templates/application.hbs index 19e480f..1aaedd0 100644 --- a/tests/dummy/app/templates/application.hbs +++ b/tests/dummy/app/templates/application.hbs @@ -12,11 +12,13 @@

Plain:

-{{code-snippet name="static.hbs"}} +{{#let (get-code-snippet "static.hbs") as |snippet|}} +
{{snippet.source}}
+{{/let}}

Prism.js

-{{#code-block language="handlebars"}}{{code-snippet name="dynamic.hbs"}}{{/code-block}} +{{#code-block language="handlebars"}}{{get (get-code-snippet "dynamic.hbs") "source"}}{{/code-block}}

Dynamic snippet

diff --git a/tests/integration/components/code-snippet-test.js b/tests/integration/components/code-snippet-test.js deleted file mode 100644 index 8cc1044..0000000 --- a/tests/integration/components/code-snippet-test.js +++ /dev/null @@ -1,27 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -import { render } from '@ember/test-helpers'; -import hbs from 'htmlbars-inline-precompile'; - -module('Integration | Component | code-snippet', function(hooks) { - setupRenderingTest(hooks); - - test('it renders snippet', async function(assert) { - await render(hbs` - // BEGIN-SNIPPET render-test - function sample(){ - return 42; - }; - // END-SNIPPET - - {{code-snippet id="snippet" name="render-test.js"}} - `); - - - - assert.dom('pre#snippet').exists(); - assert.dom('pre#snippet').hasText( - 'function sample(){\n return 42;\n};' - ); - }); -}); From 9ff24eabf886656a276da610c30631bc0cb542b2 Mon Sep 17 00:00:00 2001 From: simonihmig Date: Mon, 10 Jun 2019 20:53:39 +0200 Subject: [PATCH 05/11] Add helper test --- .eslintrc.js | 2 +- .template-lintrc.js | 6 ++- .../helpers/get-code-snippet-test.js | 48 +++++++++++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 tests/integration/helpers/get-code-snippet-test.js diff --git a/.eslintrc.js b/.eslintrc.js index ec62c2e..bf4fa84 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,7 +1,7 @@ module.exports = { root: true, parserOptions: { - ecmaVersion: 2017, + ecmaVersion: 2018, sourceType: 'module' }, plugins: [ diff --git a/.template-lintrc.js b/.template-lintrc.js index b45e96f..eb8c212 100644 --- a/.template-lintrc.js +++ b/.template-lintrc.js @@ -1,5 +1,9 @@ 'use strict'; module.exports = { - extends: 'recommended' + extends: 'recommended', + rules: { + 'block-indentation': false, + 'no-html-comments': false + } }; diff --git a/tests/integration/helpers/get-code-snippet-test.js b/tests/integration/helpers/get-code-snippet-test.js new file mode 100644 index 0000000..1c01a08 --- /dev/null +++ b/tests/integration/helpers/get-code-snippet-test.js @@ -0,0 +1,48 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { render } from '@ember/test-helpers'; +import hbs from 'htmlbars-inline-precompile'; + +module('Integration | Helper | get-code-snippet', function(hooks) { + setupRenderingTest(hooks); + + test('it returns snippet', async function(assert) { + await render(hbs` + // BEGIN-SNIPPET render-test + function sample(){ + return 42; + }; + // END-SNIPPET + + {{#let (get-code-snippet "render-test.js") as |snippet|}} +
{{snippet.source}}
+
{{snippet.language}}
+
{{snippet.extension}}
+ {{/let}} + `); + + assert.dom('#source').hasText('function sample(){\n return 42;\n};'); + assert.dom('#language').hasText('javascript'); // language is determined by file extension, so JS ini this case + assert.dom('#extension').hasText('js'); + }); + + test('it returns snippet w/ intented source', async function(assert) { + await render(hbs` + // BEGIN-SNIPPET render-test + function sample(){ + return 42; + }; + // END-SNIPPET + + {{#let (get-code-snippet "render-test.js" unintent=false) as |snippet|}} +
{{snippet.source}}
+
{{snippet.language}}
+
{{snippet.extension}}
+ {{/let}} + `); + + assert.dom('#source').hasText(' function sample(){\n return 42;\n };'); + assert.dom('#language').hasText('javascript'); // language is determined by file extension, so JS ini this case + assert.dom('#extension').hasText('js'); + }); +}); From c8a9c0e7a9cbbccb11c5f958354a30d7c799a267 Mon Sep 17 00:00:00 2001 From: simonihmig Date: Mon, 10 Jun 2019 21:24:55 +0200 Subject: [PATCH 06/11] Update Readme, adding helper and removing component docs --- README.md | 107 ++++++++++++++++-------------------------------------- 1 file changed, 32 insertions(+), 75 deletions(-) diff --git a/README.md b/README.md index 5957ea5..c906206 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,11 @@ -Code Snippet Ember Component +Code Snippet Ember Helper ============================ -This is an Ember component (and ember-cli addon) that lets you render +This is an Ember helper (and ember-cli addon) that lets you render code snippets within your app. The code snippets can live in their own dedicated files or you can extract blocks of code from your application itself. -- Syntax highlighting thanks to [highlight.js](http://highlightjs.org/). To see how it looks, [view the highlightjs previews](https://highlightjs.org/). -- ember-cli's auto-reload will pick up changes to any of the snippet files. -- the component uses file extensions to help highlight.js guess the - right language. See below for details on choosing the supported languages. - Compatibility ------------------------------------------------------------------------------ @@ -28,10 +23,12 @@ ember install ember-code-snippet Usage ------------------------------------------------------------------------------ +### Defining snippets + There are two ways to store your code snippets. You can use either or both together. -### With separate snippet files +#### With separate snippet files Create a new "snippets" directory at the top level of your ember-cli application or addon, and place the code snippets you'd like to render in their @@ -61,7 +58,7 @@ var app = new EmberAddon({ }); ``` -### From within your application source +#### From within your application source In any file under your `app` tree, annotate the start and end of a code snippet block by placing comments like this: @@ -78,15 +75,9 @@ The above is a Javascript example, but you can use any language's comment format. We're just looking for lines that match `/\bBEGIN-SNIPPET\s+(\S+)\b/` and `/\bEND-SNIPPET\b/`. -The opening comment must include a name. The component will identify +The opening comment must include a name. The helper will identify these snippets using the names you specified plus the file extension -of the file in which they appeared (which helps us detect languages -for better highlighting). So the above example could be included in a -template like this: - -```hbs -{{code-snippet name="my-nice-example.js"}} -``` +of the file in which they appeared. You can also define your own regex to find snippets. Just use the `snippetRegexes` option: @@ -101,15 +92,6 @@ var app = new EmberAddon({ In the regex above everything in the `element-example` component block will be a snippet! Just make sure the first regex capture group is the name of the snippet. -By default, the component will try to unindent the code block by -removing whitespace characters from the start of each line until the -code bumps up against the edge. You can disable this with: - -```hbs -{{code-snippet name="my-nice-example.js" unindent=false}} -``` - - You can choose which paths will be searched for inline snippets by settings the snippetSearchPaths option when creating your application in ember-cli-build.js: @@ -128,66 +110,41 @@ var app = new EmberApp({ }); ``` -# Syntax Highlighting Language Support - -We depend on [highlight.js](http://highlightjs.org/) for syntax highlighting. It supports 176 languages. But you probably don't want to build all of those into your app. - -Out of the box, we only enable: - - - css - - coffeescript - - html/xml - - json - - javascript - - markdown - - handlebars - - htmlbars - -If you want a different set, you can: +### get-code-snippet helper -1. Tell ember-code-snippet not to include highlight.js automatically for you. Also, include an array of file extensions corresponding to the languages you want to use. If ```snippetExtensions``` is not defined, the file extensions corresponding to the default list of supported languages will be used. +After you have defined your snippets, you can use the `get-code-snippet` helper to get the snippet data +for rendering: `{{get-code-snippet "my-nice-example.js"}}`. The returned value will be a JavaScript object with the +following properties: -```js - // in ember-cli-build.js - var app = new EmberApp(defaults, { - includeHighlightJS: false, - snippetExtensions: ['js','java','php'] - }); -``` - -2. Go to https://highlightjs.org/download/ and generate your own build of highlight.js using the languages you want. - -3. Place the resulting highlight.pack.js in your `vendor` directory. +* `source`: the source code extracted from the given snippet +* `language`: the snippets language, following the naming conventions of the popular `highlight.js` library, e.g. `htmlbars` for Ember templates +* `extension`: the file extension of the file containing the given snippet -4. Import it directly from your ember-cli-build.js file: +By default, the helper will try to unindent the code block by +removing whitespace characters from the start of each line until the +code bumps up against the edge. You can disable this with: -```js -app.import('vendor/highlight.pack.js', { - using: [ { transformation: 'amd', as: 'highlight.js' } ] -}); +```hbs +{{get-code-snippet "my-nice-example.js" unindent=false}} ``` -# Theming Support - -We include a basic syntax-highlighting theme by default, but highlight.js has 79 different themes to choose from and it's possible to make your own just by writing a stylesheet. - -To use a different theme: - -1. Tell ember-code-snippet not to include its own theme: +The following example will render a `
` tag with a given code snippet:
 
-```js
-  // in ember-cli-build.js
-  var app = new EmberApp(defaults, {
-    includeHighlightStyle: false
-  });
+```hbs
+{{#let (get-code-snippet "static.hbs") as |snippet|}}
+
{{snippet.source}}
+{{/let}} ``` -2. Place your chosen style in `vendor`. +### Syntax Highlighting -3. Import it directly from your ember-cli-build.js: +This addon does not provide any syntax highlighting capabilities itself, but instead it is designed with composability +in mind, so you can add highlighting capabilities with any highlighting library on top of the snippet extraction +primitives of this addon. The following is an example of rendering a code snippet using code highlighting provided by the +[ember-prism](https://github.com/shipshapecode/ember-prism) addon: -```js -app.import('vendor/my-highlight-style.css'); +```hbs +{{#code-block language="handlebars"}}{{get (get-code-snippet "demo.hbs") "source"}}{{/code-block}} ``` From 1f7342600044fae5fb044e04e8a79c02df500eb9 Mon Sep 17 00:00:00 2001 From: simonihmig Date: Mon, 10 Jun 2019 21:41:19 +0200 Subject: [PATCH 07/11] Add getCodeSnippet function for JS usage --- README.md | 14 +++++++++++++- addon/-private/get-snippet.js | 7 ++++++- addon/helpers/get-code-snippet.js | 8 ++------ addon/index.js | 6 ++---- tests/unit/get-code-snippet-test.js | 21 +++++++++++++++++++++ 5 files changed, 44 insertions(+), 12 deletions(-) create mode 100644 tests/unit/get-code-snippet-test.js diff --git a/README.md b/README.md index c906206..57a685e 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ var app = new EmberApp({ }); ``` -### get-code-snippet helper +### Helper usage After you have defined your snippets, you can use the `get-code-snippet` helper to get the snippet data for rendering: `{{get-code-snippet "my-nice-example.js"}}`. The returned value will be a JavaScript object with the @@ -147,6 +147,18 @@ primitives of this addon. The following is an example of rendering a code snippe {{#code-block language="handlebars"}}{{get (get-code-snippet "demo.hbs") "source"}}{{/code-block}} ``` +### JavaScript usage + +When you want to use the code snippet functionality from JavaScript, you can import the `getCodeSnippet` function like +this: + +```js +import { getCodeSnippet } from 'ember-code-snippet'; +``` + +Its call signature is similar to the helper invocation: `getCodeSnippet(name, unindent = true)`, and it returns the same +POJO as described above. + Contributing ------------------------------------------------------------------------------ diff --git a/addon/-private/get-snippet.js b/addon/-private/get-snippet.js index d7f2e1d..176b265 100644 --- a/addon/-private/get-snippet.js +++ b/addon/-private/get-snippet.js @@ -1,9 +1,10 @@ import snippets from 'ember-code-snippet/snippets'; import getLanguage from './language'; import getExtension from './extension'; +import unindentSource from '../-private/unindent'; import { assert } from '@ember/debug'; -export default function getSnippet(name) { +export default function getSnippet(name, unindent = true) { let source = name .split('/') .reduce((dir, name) => dir && dir[name], snippets); @@ -13,6 +14,10 @@ export default function getSnippet(name) { .replace(/^(\s*\n)*/, '') .replace(/\s*$/, ''); + if (unindent) { + source = unindentSource(source); + } + let language = getLanguage(name); let extension = getExtension(name); diff --git a/addon/helpers/get-code-snippet.js b/addon/helpers/get-code-snippet.js index c7c02b1..4bea6c6 100644 --- a/addon/helpers/get-code-snippet.js +++ b/addon/helpers/get-code-snippet.js @@ -1,10 +1,6 @@ import { helper } from '@ember/component/helper'; -import getSnippet from '../-private/get-snippet'; -import unindentSource from '../-private/unindent'; +import { getCodeSnippet } from 'ember-code-snippet'; export default helper(function([name], { unindent = true }) { - let snippet = getSnippet(name); - return unindent - ? { ...snippet, source: unindentSource(snippet.source) } - : snippet; + return getCodeSnippet(name, unindent); }); diff --git a/addon/index.js b/addon/index.js index 0858186..24db221 100644 --- a/addon/index.js +++ b/addon/index.js @@ -1,7 +1,5 @@ -import getSnippet from './-private/get-snippet'; -import unindent from './-private/unindent'; +import getCodeSnippet from './-private/get-snippet'; export { - getSnippet, - unindent + getCodeSnippet }; diff --git a/tests/unit/get-code-snippet-test.js b/tests/unit/get-code-snippet-test.js new file mode 100644 index 0000000..f6ea707 --- /dev/null +++ b/tests/unit/get-code-snippet-test.js @@ -0,0 +1,21 @@ +import { module, test } from 'qunit'; +import { getCodeSnippet } from 'ember-code-snippet'; + +module('Unit | getCodeSnippet', function() { + + test('it returns snippet', async function(assert) { + let snippet = getCodeSnippet('render-test.js'); + + assert.equal(snippet.source, 'function sample(){\n return 42;\n};'); + assert.equal(snippet.language, 'javascript'); + assert.equal(snippet.extension, 'js'); + }); + + test('it returns snippet w/ intented source', async function(assert) { + let snippet = getCodeSnippet('render-test.js', false); + + assert.equal(snippet.source, ' function sample(){\n return 42;\n };'); + assert.equal(snippet.language, 'javascript'); + assert.equal(snippet.extension, 'js'); + }); +}); From d52e51c850a78fc9894d92bbed40cff19774cc24 Mon Sep 17 00:00:00 2001 From: simonihmig Date: Mon, 10 Jun 2019 21:54:53 +0200 Subject: [PATCH 08/11] Replace `let` helper with `with` helper, to fix Ember 2.18 tests --- tests/integration/helpers/get-code-snippet-test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/integration/helpers/get-code-snippet-test.js b/tests/integration/helpers/get-code-snippet-test.js index 1c01a08..927047c 100644 --- a/tests/integration/helpers/get-code-snippet-test.js +++ b/tests/integration/helpers/get-code-snippet-test.js @@ -14,11 +14,11 @@ module('Integration | Helper | get-code-snippet', function(hooks) { }; // END-SNIPPET - {{#let (get-code-snippet "render-test.js") as |snippet|}} + {{#with (get-code-snippet "render-test.js") as |snippet|}}
{{snippet.source}}
{{snippet.language}}
{{snippet.extension}}
- {{/let}} + {{/with}} `); assert.dom('#source').hasText('function sample(){\n return 42;\n};'); @@ -34,11 +34,11 @@ module('Integration | Helper | get-code-snippet', function(hooks) { }; // END-SNIPPET - {{#let (get-code-snippet "render-test.js" unintent=false) as |snippet|}} + {{#with (get-code-snippet "render-test.js" unintent=false) as |snippet|}}
{{snippet.source}}
{{snippet.language}}
{{snippet.extension}}
- {{/let}} + {{/with}} `); assert.dom('#source').hasText(' function sample(){\n return 42;\n };'); From 0c3905d4171d5ef04c91720c8a9421df1ce3addc Mon Sep 17 00:00:00 2001 From: simonihmig Date: Sat, 22 Jun 2019 00:04:39 +0200 Subject: [PATCH 09/11] Cleanup dynamic-code-snippet --- addon/helpers/dynamic-code-snippet.js | 27 -------------------- app/helpers/dynamic-code-snippet.js | 1 - tests/dummy/app/templates/application.hbs | 30 +---------------------- 3 files changed, 1 insertion(+), 57 deletions(-) delete mode 100644 addon/helpers/dynamic-code-snippet.js delete mode 100644 app/helpers/dynamic-code-snippet.js diff --git a/addon/helpers/dynamic-code-snippet.js b/addon/helpers/dynamic-code-snippet.js deleted file mode 100644 index 82fe09d..0000000 --- a/addon/helpers/dynamic-code-snippet.js +++ /dev/null @@ -1,27 +0,0 @@ -import { helper } from '@ember/component/helper'; -import { get } from '@ember/object'; - -export default helper(function([source], { language, dynamic, quote = '"'}) { - Object.keys(dynamic).forEach((property) => { - let propertyValue = get(dynamic, property); - let type = typeof propertyValue; - - let quotedValue = type === 'string' ? `${quote}${propertyValue}${quote}` : propertyValue; - - switch (language) { - case 'handlebars': - case 'htmlbars': - source = source.replace( - new RegExp(`(<\\w*[^>]*\\s@[^=]+=){{${property}}}([^>]*>)`, 'g'), - type === 'string' ? `$1${quotedValue}$2` : `$1{{${propertyValue}}}$2` - ); - source = source.replace(new RegExp(`{{${property}}}`, 'g'), propertyValue); - source = source.replace(new RegExp(`=${property}`, 'g'), `=${quotedValue}`); - break; - default: - source = source.replace(new RegExp(`{{${property}}}`, 'g'), quotedValue); - } - }); - - return source; -}); diff --git a/app/helpers/dynamic-code-snippet.js b/app/helpers/dynamic-code-snippet.js deleted file mode 100644 index 66fbdf8..0000000 --- a/app/helpers/dynamic-code-snippet.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from 'ember-code-snippet/helpers/dynamic-code-snippet'; diff --git a/tests/dummy/app/templates/application.hbs b/tests/dummy/app/templates/application.hbs index 1aaedd0..a6de3cc 100644 --- a/tests/dummy/app/templates/application.hbs +++ b/tests/dummy/app/templates/application.hbs @@ -18,32 +18,4 @@

Prism.js

-{{#code-block language="handlebars"}}{{get (get-code-snippet "dynamic.hbs") "source"}}{{/code-block}} - -

Dynamic snippet

- -
- - {{input id="type" value=inputType}} -
- -
- - -

I am a handlebars template!

-

The value is: {{val}}

-
- {{input value=val type=inputType}} -
- - -{{#let (get-code-snippet "dynamic.hbs") as |snippet|}} -
-{{dynamic-code-snippet snippet.source
-  language=snippet.language
-  dynamic=(hash
-    inputType=inputType
-  )
-}}
-
-{{/let}} +{{#code-block language="handlebars"}}{{get (get-code-snippet "static.hbs") "source"}}{{/code-block}} From a23086e3b7fad884a5a536577d3dffbcb9d3554f Mon Sep 17 00:00:00 2001 From: simonihmig Date: Sun, 23 Jun 2019 21:34:44 +0200 Subject: [PATCH 10/11] Add component example to Readme --- README.md | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 57a685e..125a90d 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,7 @@ The following example will render a `
` tag with a given code snippet:
 
 ```hbs
 {{#let (get-code-snippet "static.hbs") as |snippet|}}
-
{{snippet.source}}
+
{{snippet.source}}
{{/let}} ``` @@ -144,7 +144,25 @@ primitives of this addon. The following is an example of rendering a code snippe [ember-prism](https://github.com/shipshapecode/ember-prism) addon: ```hbs -{{#code-block language="handlebars"}}{{get (get-code-snippet "demo.hbs") "source"}}{{/code-block}} +{{#let (get-code-snippet "demo.hbs") as |snippet|}} + + {{snippet.source}} + +{{/let}} +``` + +If you want to show multiple snippets, it makes sense to extract that template code into a reusable component. In fact +previous versions of `ember-code-snippet` shipped a `code-snippet` component, that you can replace now with the new +helper and your highlighting library of choice. The following template-only component could replace the previously +available component ``, again using `ember-prism` in this case: + +```hbs +{{!-- templates/components/code-snippet.hbs --}} +{{#let (get-code-snippet @name) as |snippet|}} + + {{snippet.source}} + +{{/let}} ``` ### JavaScript usage From 7694a5d678f85f87c376037be978d75469c6b002 Mon Sep 17 00:00:00 2001 From: simonihmig Date: Mon, 24 Jun 2019 10:54:25 +0200 Subject: [PATCH 11/11] Adapt returned language to prism.js supported languages --- README.md | 2 +- addon/-private/language.js | 2 +- tests/integration/helpers/get-code-snippet-test.js | 4 ++-- tests/unit/get-code-snippet-test.js | 8 ++++++++ 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 125a90d..f028f05 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,7 @@ for rendering: `{{get-code-snippet "my-nice-example.js"}}`. The returned value w following properties: * `source`: the source code extracted from the given snippet -* `language`: the snippets language, following the naming conventions of the popular `highlight.js` library, e.g. `htmlbars` for Ember templates +* `language`: the snippets language, following the naming conventions of the popular `prism.js` library, e.g. `handlebars` for Ember templates * `extension`: the file extension of the file containing the given snippet By default, the helper will try to unindent the code block by diff --git a/addon/-private/language.js b/addon/-private/language.js index be3f9bd..926b4e7 100644 --- a/addon/-private/language.js +++ b/addon/-private/language.js @@ -9,7 +9,7 @@ export default function getLanguage(name) { case 'coffee': return 'coffeescript'; case 'hbs': - return 'htmlbars'; + return 'handlebars'; case 'css': return 'css'; case 'scss': diff --git a/tests/integration/helpers/get-code-snippet-test.js b/tests/integration/helpers/get-code-snippet-test.js index 927047c..ce30365 100644 --- a/tests/integration/helpers/get-code-snippet-test.js +++ b/tests/integration/helpers/get-code-snippet-test.js @@ -22,7 +22,7 @@ module('Integration | Helper | get-code-snippet', function(hooks) { `); assert.dom('#source').hasText('function sample(){\n return 42;\n};'); - assert.dom('#language').hasText('javascript'); // language is determined by file extension, so JS ini this case + assert.dom('#language').hasText('javascript'); // language is determined by file extension, so JS in this case assert.dom('#extension').hasText('js'); }); @@ -42,7 +42,7 @@ module('Integration | Helper | get-code-snippet', function(hooks) { `); assert.dom('#source').hasText(' function sample(){\n return 42;\n };'); - assert.dom('#language').hasText('javascript'); // language is determined by file extension, so JS ini this case + assert.dom('#language').hasText('javascript'); // language is determined by file extension, so JS in this case assert.dom('#extension').hasText('js'); }); }); diff --git a/tests/unit/get-code-snippet-test.js b/tests/unit/get-code-snippet-test.js index f6ea707..4ff67bc 100644 --- a/tests/unit/get-code-snippet-test.js +++ b/tests/unit/get-code-snippet-test.js @@ -18,4 +18,12 @@ module('Unit | getCodeSnippet', function() { assert.equal(snippet.language, 'javascript'); assert.equal(snippet.extension, 'js'); }); + + test('it returns handlebars snippet', async function(assert) { + let snippet = getCodeSnippet('static.hbs'); + + assert.ok(snippet.source.includes('

I am a handlebars template!

')); + assert.equal(snippet.language, 'handlebars'); + assert.equal(snippet.extension, 'hbs'); + }); });