view_component 3.22.0 → 4.0.0.alpha1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/concerns/view_component/preview_actions.rb +2 -9
  3. data/app/controllers/view_components_system_test_controller.rb +17 -20
  4. data/app/views/test_mailer/test_asset_email.html.erb +1 -0
  5. data/app/views/view_components/preview.html.erb +1 -9
  6. data/docs/CHANGELOG.md +127 -1
  7. data/lib/view_component/base.rb +41 -61
  8. data/lib/view_component/collection.rb +11 -17
  9. data/lib/view_component/compiler.rb +50 -74
  10. data/lib/view_component/config.rb +0 -21
  11. data/lib/view_component/deprecation.rb +1 -1
  12. data/lib/view_component/engine.rb +3 -82
  13. data/lib/view_component/errors.rb +16 -22
  14. data/lib/view_component/inline_template.rb +2 -3
  15. data/lib/view_component/instrumentation.rb +4 -10
  16. data/lib/view_component/preview.rb +3 -10
  17. data/lib/view_component/request_details.rb +30 -0
  18. data/lib/view_component/slot.rb +2 -5
  19. data/lib/view_component/slotable.rb +31 -39
  20. data/lib/view_component/system_test_helpers.rb +1 -2
  21. data/lib/view_component/template.rb +106 -83
  22. data/lib/view_component/test_helpers.rb +22 -42
  23. data/lib/view_component/translatable.rb +24 -23
  24. data/lib/view_component/use_helpers.rb +3 -4
  25. data/lib/view_component/version.rb +3 -3
  26. data/lib/view_component.rb +0 -1
  27. metadata +73 -220
  28. data/app/assets/vendor/prism.css +0 -4
  29. data/app/assets/vendor/prism.min.js +0 -12
  30. data/app/helpers/preview_helper.rb +0 -85
  31. data/app/views/view_components/_preview_source.html.erb +0 -17
  32. data/lib/rails/generators/abstract_generator.rb +0 -56
  33. data/lib/rails/generators/component/USAGE +0 -13
  34. data/lib/rails/generators/component/component_generator.rb +0 -67
  35. data/lib/rails/generators/component/templates/component.rb.tt +0 -16
  36. data/lib/rails/generators/erb/component_generator.rb +0 -33
  37. data/lib/rails/generators/erb/templates/component.html.erb.tt +0 -1
  38. data/lib/rails/generators/haml/component_generator.rb +0 -22
  39. data/lib/rails/generators/haml/templates/component.html.haml.tt +0 -1
  40. data/lib/rails/generators/locale/component_generator.rb +0 -46
  41. data/lib/rails/generators/preview/component_generator.rb +0 -39
  42. data/lib/rails/generators/preview/templates/component_preview.rb.tt +0 -9
  43. data/lib/rails/generators/rspec/component_generator.rb +0 -31
  44. data/lib/rails/generators/rspec/templates/component_spec.rb.tt +0 -15
  45. data/lib/rails/generators/slim/component_generator.rb +0 -22
  46. data/lib/rails/generators/slim/templates/component.html.slim.tt +0 -1
  47. data/lib/rails/generators/stimulus/component_generator.rb +0 -44
  48. data/lib/rails/generators/stimulus/templates/component_controller.js.tt +0 -7
  49. data/lib/rails/generators/stimulus/templates/component_controller.ts.tt +0 -9
  50. data/lib/rails/generators/tailwindcss/component_generator.rb +0 -11
  51. data/lib/rails/generators/tailwindcss/templates/component.html.erb.tt +0 -1
  52. data/lib/rails/generators/test_unit/component_generator.rb +0 -20
  53. data/lib/rails/generators/test_unit/templates/component_test.rb.tt +0 -12
  54. data/lib/view_component/component_error.rb +0 -6
  55. data/lib/view_component/docs_builder_component.html.erb +0 -22
  56. data/lib/view_component/docs_builder_component.rb +0 -96
  57. data/lib/view_component/rails/tasks/view_component.rake +0 -20
  58. data/lib/view_component/render_component_helper.rb +0 -10
  59. data/lib/view_component/render_component_to_string_helper.rb +0 -9
  60. data/lib/view_component/render_monkey_patch.rb +0 -13
  61. data/lib/view_component/render_to_string_monkey_patch.rb +0 -13
  62. data/lib/view_component/rendering_component_helper.rb +0 -9
  63. data/lib/view_component/rendering_monkey_patch.rb +0 -13
  64. data/lib/yard/mattr_accessor_handler.rb +0 -19
@@ -1,12 +0,0 @@
1
- /* PrismJS 1.28.0
2
- https://prismjs.com/download.html#themes=prism-tomorrow&languages=markup+clike+erb+haml+markup-templating+ruby&plugins=line-highlight+highlight-keywords+normalize-whitespace */
3
- var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(e){var n=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,r={},a={manual:e.Prism&&e.Prism.manual,disableWorkerMessageHandler:e.Prism&&e.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof i?new i(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/\u00a0/g," ")},type:function(e){return Object.prototype.toString.call(e).slice(8,-1)},objId:function(e){return e.__id||Object.defineProperty(e,"__id",{value:++t}),e.__id},clone:function e(n,t){var r,i;switch(t=t||{},a.util.type(n)){case"Object":if(i=a.util.objId(n),t[i])return t[i];for(var l in r={},t[i]=r,n)n.hasOwnProperty(l)&&(r[l]=e(n[l],t));return r;case"Array":return i=a.util.objId(n),t[i]?t[i]:(r=[],t[i]=r,n.forEach((function(n,a){r[a]=e(n,t)})),r);default:return n}},getLanguage:function(e){for(;e;){var t=n.exec(e.className);if(t)return t[1].toLowerCase();e=e.parentElement}return"none"},setLanguage:function(e,t){e.className=e.className.replace(RegExp(n,"gi"),""),e.classList.add("language-"+t)},currentScript:function(){if("undefined"==typeof document)return null;if("currentScript"in document)return document.currentScript;try{throw new Error}catch(r){var e=(/at [^(\r\n]*\((.*):[^:]+:[^:]+\)$/i.exec(r.stack)||[])[1];if(e){var n=document.getElementsByTagName("script");for(var t in n)if(n[t].src==e)return n[t]}return null}},isActive:function(e,n,t){for(var r="no-"+n;e;){var a=e.classList;if(a.contains(n))return!0;if(a.contains(r))return!1;e=e.parentElement}return!!t}},languages:{plain:r,plaintext:r,text:r,txt:r,extend:function(e,n){var t=a.util.clone(a.languages[e]);for(var r in n)t[r]=n[r];return t},insertBefore:function(e,n,t,r){var i=(r=r||a.languages)[e],l={};for(var o in i)if(i.hasOwnProperty(o)){if(o==n)for(var s in t)t.hasOwnProperty(s)&&(l[s]=t[s]);t.hasOwnProperty(o)||(l[o]=i[o])}var u=r[e];return r[e]=l,a.languages.DFS(a.languages,(function(n,t){t===u&&n!=e&&(this[n]=l)})),l},DFS:function e(n,t,r,i){i=i||{};var l=a.util.objId;for(var o in n)if(n.hasOwnProperty(o)){t.call(n,o,n[o],r||o);var s=n[o],u=a.util.type(s);"Object"!==u||i[l(s)]?"Array"!==u||i[l(s)]||(i[l(s)]=!0,e(s,t,o,i)):(i[l(s)]=!0,e(s,t,null,i))}}},plugins:{},highlightAll:function(e,n){a.highlightAllUnder(document,e,n)},highlightAllUnder:function(e,n,t){var r={callback:t,container:e,selector:'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'};a.hooks.run("before-highlightall",r),r.elements=Array.prototype.slice.apply(r.container.querySelectorAll(r.selector)),a.hooks.run("before-all-elements-highlight",r);for(var i,l=0;i=r.elements[l++];)a.highlightElement(i,!0===n,r.callback)},highlightElement:function(n,t,r){var i=a.util.getLanguage(n),l=a.languages[i];a.util.setLanguage(n,i);var o=n.parentElement;o&&"pre"===o.nodeName.toLowerCase()&&a.util.setLanguage(o,i);var s={element:n,language:i,grammar:l,code:n.textContent};function u(e){s.highlightedCode=e,a.hooks.run("before-insert",s),s.element.innerHTML=s.highlightedCode,a.hooks.run("after-highlight",s),a.hooks.run("complete",s),r&&r.call(s.element)}if(a.hooks.run("before-sanity-check",s),(o=s.element.parentElement)&&"pre"===o.nodeName.toLowerCase()&&!o.hasAttribute("tabindex")&&o.setAttribute("tabindex","0"),!s.code)return a.hooks.run("complete",s),void(r&&r.call(s.element));if(a.hooks.run("before-highlight",s),s.grammar)if(t&&e.Worker){var c=new Worker(a.filename);c.onmessage=function(e){u(e.data)},c.postMessage(JSON.stringify({language:s.language,code:s.code,immediateClose:!0}))}else u(a.highlight(s.code,s.grammar,s.language));else u(a.util.encode(s.code))},highlight:function(e,n,t){var r={code:e,grammar:n,language:t};if(a.hooks.run("before-tokenize",r),!r.grammar)throw new Error('The language "'+r.language+'" has no grammar.');return r.tokens=a.tokenize(r.code,r.grammar),a.hooks.run("after-tokenize",r),i.stringify(a.util.encode(r.tokens),r.language)},tokenize:function(e,n){var t=n.rest;if(t){for(var r in t)n[r]=t[r];delete n.rest}var a=new s;return u(a,a.head,e),o(e,a,n,a.head,0),function(e){for(var n=[],t=e.head.next;t!==e.tail;)n.push(t.value),t=t.next;return n}(a)},hooks:{all:{},add:function(e,n){var t=a.hooks.all;t[e]=t[e]||[],t[e].push(n)},run:function(e,n){var t=a.hooks.all[e];if(t&&t.length)for(var r,i=0;r=t[i++];)r(n)}},Token:i};function i(e,n,t,r){this.type=e,this.content=n,this.alias=t,this.length=0|(r||"").length}function l(e,n,t,r){e.lastIndex=n;var a=e.exec(t);if(a&&r&&a[1]){var i=a[1].length;a.index+=i,a[0]=a[0].slice(i)}return a}function o(e,n,t,r,s,g){for(var f in t)if(t.hasOwnProperty(f)&&t[f]){var h=t[f];h=Array.isArray(h)?h:[h];for(var d=0;d<h.length;++d){if(g&&g.cause==f+","+d)return;var v=h[d],p=v.inside,m=!!v.lookbehind,y=!!v.greedy,k=v.alias;if(y&&!v.pattern.global){var x=v.pattern.toString().match(/[imsuy]*$/)[0];v.pattern=RegExp(v.pattern.source,x+"g")}for(var b=v.pattern||v,w=r.next,A=s;w!==n.tail&&!(g&&A>=g.reach);A+=w.value.length,w=w.next){var E=w.value;if(n.length>e.length)return;if(!(E instanceof i)){var P,L=1;if(y){if(!(P=l(b,A,e,m))||P.index>=e.length)break;var S=P.index,O=P.index+P[0].length,j=A;for(j+=w.value.length;S>=j;)j+=(w=w.next).value.length;if(A=j-=w.value.length,w.value instanceof i)continue;for(var C=w;C!==n.tail&&(j<O||"string"==typeof C.value);C=C.next)L++,j+=C.value.length;L--,E=e.slice(A,j),P.index-=A}else if(!(P=l(b,0,E,m)))continue;S=P.index;var N=P[0],_=E.slice(0,S),M=E.slice(S+N.length),W=A+E.length;g&&W>g.reach&&(g.reach=W);var z=w.prev;if(_&&(z=u(n,z,_),A+=_.length),c(n,z,L),w=u(n,z,new i(f,p?a.tokenize(N,p):N,k,N)),M&&u(n,w,M),L>1){var I={cause:f+","+d,reach:W};o(e,n,t,w.prev,A,I),g&&I.reach>g.reach&&(g.reach=I.reach)}}}}}}function s(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function u(e,n,t){var r=n.next,a={value:t,prev:n,next:r};return n.next=a,r.prev=a,e.length++,a}function c(e,n,t){for(var r=n.next,a=0;a<t&&r!==e.tail;a++)r=r.next;n.next=r,r.prev=n,e.length-=a}if(e.Prism=a,i.stringify=function e(n,t){if("string"==typeof n)return n;if(Array.isArray(n)){var r="";return n.forEach((function(n){r+=e(n,t)})),r}var i={type:n.type,content:e(n.content,t),tag:"span",classes:["token",n.type],attributes:{},language:t},l=n.alias;l&&(Array.isArray(l)?Array.prototype.push.apply(i.classes,l):i.classes.push(l)),a.hooks.run("wrap",i);var o="";for(var s in i.attributes)o+=" "+s+'="'+(i.attributes[s]||"").replace(/"/g,"&quot;")+'"';return"<"+i.tag+' class="'+i.classes.join(" ")+'"'+o+">"+i.content+"</"+i.tag+">"},!e.document)return e.addEventListener?(a.disableWorkerMessageHandler||e.addEventListener("message",(function(n){var t=JSON.parse(n.data),r=t.language,i=t.code,l=t.immediateClose;e.postMessage(a.highlight(i,a.languages[r],r)),l&&e.close()}),!1),a):a;var g=a.util.currentScript();function f(){a.manual||a.highlightAll()}if(g&&(a.filename=g.src,g.hasAttribute("data-manual")&&(a.manual=!0)),!a.manual){var h=document.readyState;"loading"===h||"interactive"===h&&g&&g.defer?document.addEventListener("DOMContentLoaded",f):window.requestAnimationFrame?window.requestAnimationFrame(f):window.setTimeout(f,16)}return a}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism);
4
- Prism.languages.markup={comment:{pattern:/<!--(?:(?!<!--)[\s\S])*?-->/,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/<!DOCTYPE(?:[^>"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|<!--(?:[^-]|-(?!->))*-->)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^<!|>$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",(function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&amp;/,"&"))})),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^<!\[CDATA\[)[\s\S]+?(?=\]\]>$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^<!\[CDATA\[|\]\]>$/i;var t={"included-cdata":{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,inside:s}};t["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var n={};n[a]={pattern:RegExp("(<__[^>]*>)(?:<!\\[CDATA\\[(?:[^\\]]|\\](?!\\]>))*\\]\\]>|(?!<!\\[CDATA\\[)[^])*?(?=</__>)".replace(/__/g,(function(){return a})),"i"),lookbehind:!0,greedy:!0,inside:t},Prism.languages.insertBefore("markup","cdata",n)}}),Object.defineProperty(Prism.languages.markup.tag,"addAttribute",{value:function(a,e){Prism.languages.markup.tag.inside["special-attr"].push({pattern:RegExp("(^|[\"'\\s])(?:"+a+")\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+(?=[\\s>]))","i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[e,"language-"+e],inside:Prism.languages[e]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml;
5
- Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/};
6
- !function(e){e.languages.ruby=e.languages.extend("clike",{comment:{pattern:/#.*|^=begin\s[\s\S]*?^=end/m,greedy:!0},"class-name":{pattern:/(\b(?:class|module)\s+|\bcatch\s+\()[\w.\\]+|\b[A-Z_]\w*(?=\s*\.\s*new\b)/,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:BEGIN|END|alias|and|begin|break|case|class|def|define_method|defined|do|each|else|elsif|end|ensure|extend|for|if|in|include|module|new|next|nil|not|or|prepend|private|protected|public|raise|redo|require|rescue|retry|return|self|super|then|throw|undef|unless|until|when|while|yield)\b/,operator:/\.{2,3}|&\.|===|<?=>|[!=]?~|(?:&&|\|\||<<|>>|\*\*|[+\-*/%<>!^&|=])=?|[?:]/,punctuation:/[(){}[\].,;]/}),e.languages.insertBefore("ruby","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}});var n={pattern:/((?:^|[^\\])(?:\\{2})*)#\{(?:[^{}]|\{[^{}]*\})*\}/,lookbehind:!0,inside:{content:{pattern:/^(#\{)[\s\S]+(?=\}$)/,lookbehind:!0,inside:e.languages.ruby},delimiter:{pattern:/^#\{|\}$/,alias:"punctuation"}}};delete e.languages.ruby.function;var t="(?:"+["([^a-zA-Z0-9\\s{(\\[<=])(?:(?!\\1)[^\\\\]|\\\\[^])*\\1","\\((?:[^()\\\\]|\\\\[^]|\\((?:[^()\\\\]|\\\\[^])*\\))*\\)","\\{(?:[^{}\\\\]|\\\\[^]|\\{(?:[^{}\\\\]|\\\\[^])*\\})*\\}","\\[(?:[^\\[\\]\\\\]|\\\\[^]|\\[(?:[^\\[\\]\\\\]|\\\\[^])*\\])*\\]","<(?:[^<>\\\\]|\\\\[^]|<(?:[^<>\\\\]|\\\\[^])*>)*>"].join("|")+")",i='(?:"(?:\\\\.|[^"\\\\\r\n])*"|(?:\\b[a-zA-Z_]\\w*|[^\\s\0-\\x7F]+)[?!]?|\\$.)';e.languages.insertBefore("ruby","keyword",{"regex-literal":[{pattern:RegExp("%r"+t+"[egimnosux]{0,6}"),greedy:!0,inside:{interpolation:n,regex:/[\s\S]+/}},{pattern:/(^|[^/])\/(?!\/)(?:\[[^\r\n\]]+\]|\\.|[^[/\\\r\n])+\/[egimnosux]{0,6}(?=\s*(?:$|[\r\n,.;})#]))/,lookbehind:!0,greedy:!0,inside:{interpolation:n,regex:/[\s\S]+/}}],variable:/[@$]+[a-zA-Z_]\w*(?:[?!]|\b)/,symbol:[{pattern:RegExp("(^|[^:]):"+i),lookbehind:!0,greedy:!0},{pattern:RegExp("([\r\n{(,][ \t]*)"+i+"(?=:(?!:))"),lookbehind:!0,greedy:!0}],"method-definition":{pattern:/(\bdef\s+)\w+(?:\s*\.\s*\w+)?/,lookbehind:!0,inside:{function:/\b\w+$/,keyword:/^self\b/,"class-name":/^\w+/,punctuation:/\./}}}),e.languages.insertBefore("ruby","string",{"string-literal":[{pattern:RegExp("%[qQiIwWs]?"+t),greedy:!0,inside:{interpolation:n,string:/[\s\S]+/}},{pattern:/("|')(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|(?!\1)[^\\#\r\n])*\1/,greedy:!0,inside:{interpolation:n,string:/[\s\S]+/}},{pattern:/<<[-~]?([a-z_]\w*)[\r\n](?:.*[\r\n])*?[\t ]*\1/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<[-~]?[a-z_]\w*|\b[a-z_]\w*$/i,inside:{symbol:/\b\w+/,punctuation:/^<<[-~]?/}},interpolation:n,string:/[\s\S]+/}},{pattern:/<<[-~]?'([a-z_]\w*)'[\r\n](?:.*[\r\n])*?[\t ]*\1/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<[-~]?'[a-z_]\w*'|\b[a-z_]\w*$/i,inside:{symbol:/\b\w+/,punctuation:/^<<[-~]?'|'$/}},string:/[\s\S]+/}}],"command-literal":[{pattern:RegExp("%x"+t),greedy:!0,inside:{interpolation:n,command:{pattern:/[\s\S]+/,alias:"string"}}},{pattern:/`(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|[^\\`#\r\n])*`/,greedy:!0,inside:{interpolation:n,command:{pattern:/[\s\S]+/,alias:"string"}}}]}),delete e.languages.ruby.string,e.languages.insertBefore("ruby","number",{builtin:/\b(?:Array|Bignum|Binding|Class|Continuation|Dir|Exception|FalseClass|File|Fixnum|Float|Hash|IO|Integer|MatchData|Method|Module|NilClass|Numeric|Object|Proc|Range|Regexp|Stat|String|Struct|Symbol|TMS|Thread|ThreadGroup|Time|TrueClass)\b/,constant:/\b[A-Z][A-Z0-9_]*(?:[?!]|\b)/}),e.languages.rb=e.languages.ruby}(Prism);
7
- !function(e){function n(e,n){return"___"+e.toUpperCase()+n+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(t,a,r,o){if(t.language===a){var c=t.tokenStack=[];t.code=t.code.replace(r,(function(e){if("function"==typeof o&&!o(e))return e;for(var r,i=c.length;-1!==t.code.indexOf(r=n(a,i));)++i;return c[i]=e,r})),t.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(t,a){if(t.language===a&&t.tokenStack){t.grammar=e.languages[a];var r=0,o=Object.keys(t.tokenStack);!function c(i){for(var u=0;u<i.length&&!(r>=o.length);u++){var g=i[u];if("string"==typeof g||g.content&&"string"==typeof g.content){var l=o[r],s=t.tokenStack[l],f="string"==typeof g?g:g.content,p=n(a,l),k=f.indexOf(p);if(k>-1){++r;var m=f.substring(0,k),d=new e.Token(a,e.tokenize(s,t.grammar),"language-"+a,s),h=f.substring(k+p.length),v=[];m&&v.push.apply(v,c([m])),v.push(d),h&&v.push.apply(v,c([h])),"string"==typeof g?i.splice.apply(i,[u,1].concat(v)):g.content=v}}else g.content&&c(g.content)}return i}(t.tokens)}}}})}(Prism);
8
- !function(e){e.languages.erb={delimiter:{pattern:/^(\s*)<%=?|%>(?=\s*$)/,lookbehind:!0,alias:"punctuation"},ruby:{pattern:/\s*\S[\s\S]*/,alias:"language-ruby",inside:e.languages.ruby}},e.hooks.add("before-tokenize",(function(n){e.languages["markup-templating"].buildPlaceholders(n,"erb",/<%=?(?:[^\r\n]|[\r\n](?!=begin)|[\r\n]=begin\s(?:[^\r\n]|[\r\n](?!=end))*[\r\n]=end)+?%>/g)})),e.hooks.add("after-tokenize",(function(n){e.languages["markup-templating"].tokenizePlaceholders(n,"erb")}))}(Prism);
9
- !function(n){n.languages.haml={"multiline-comment":{pattern:/((?:^|\r?\n|\r)([\t ]*))(?:\/|-#).*(?:(?:\r?\n|\r)\2[\t ].+)*/,lookbehind:!0,alias:"comment"},"multiline-code":[{pattern:/((?:^|\r?\n|\r)([\t ]*)(?:[~-]|[&!]?=)).*,[\t ]*(?:(?:\r?\n|\r)\2[\t ].*,[\t ]*)*(?:(?:\r?\n|\r)\2[\t ].+)/,lookbehind:!0,inside:n.languages.ruby},{pattern:/((?:^|\r?\n|\r)([\t ]*)(?:[~-]|[&!]?=)).*\|[\t ]*(?:(?:\r?\n|\r)\2[\t ].*\|[\t ]*)*/,lookbehind:!0,inside:n.languages.ruby}],filter:{pattern:/((?:^|\r?\n|\r)([\t ]*)):[\w-]+(?:(?:\r?\n|\r)(?:\2[\t ].+|\s*?(?=\r?\n|\r)))+/,lookbehind:!0,inside:{"filter-name":{pattern:/^:[\w-]+/,alias:"symbol"}}},markup:{pattern:/((?:^|\r?\n|\r)[\t ]*)<.+/,lookbehind:!0,inside:n.languages.markup},doctype:{pattern:/((?:^|\r?\n|\r)[\t ]*)!!!(?: .+)?/,lookbehind:!0},tag:{pattern:/((?:^|\r?\n|\r)[\t ]*)[%.#][\w\-#.]*[\w\-](?:\([^)]+\)|\{(?:\{[^}]+\}|[^{}])+\}|\[[^\]]+\])*[\/<>]*/,lookbehind:!0,inside:{attributes:[{pattern:/(^|[^#])\{(?:\{[^}]+\}|[^{}])+\}/,lookbehind:!0,inside:n.languages.ruby},{pattern:/\([^)]+\)/,inside:{"attr-value":{pattern:/(=\s*)(?:"(?:\\.|[^\\"\r\n])*"|[^)\s]+)/,lookbehind:!0},"attr-name":/[\w:-]+(?=\s*!?=|\s*[,)])/,punctuation:/[=(),]/}},{pattern:/\[[^\]]+\]/,inside:n.languages.ruby}],punctuation:/[<>]/}},code:{pattern:/((?:^|\r?\n|\r)[\t ]*(?:[~-]|[&!]?=)).+/,lookbehind:!0,inside:n.languages.ruby},interpolation:{pattern:/#\{[^}]+\}/,inside:{delimiter:{pattern:/^#\{|\}$/,alias:"punctuation"},ruby:{pattern:/[\s\S]+/,inside:n.languages.ruby}}},punctuation:{pattern:/((?:^|\r?\n|\r)[\t ]*)[~=\-&!]+/,lookbehind:!0}};for(var e=["css",{filter:"coffee",language:"coffeescript"},"erb","javascript","less","markdown","ruby","scss","textile"],t={},r=0,a=e.length;r<a;r++){var i=e[r];i="string"==typeof i?{filter:i,language:i}:i,n.languages[i.language]&&(t["filter-"+i.filter]={pattern:RegExp("((?:^|\\r?\\n|\\r)([\\t ]*)):{{filter_name}}(?:(?:\\r?\\n|\\r)(?:\\2[\\t ].+|\\s*?(?=\\r?\\n|\\r)))+".replace("{{filter_name}}",(function(){return i.filter}))),lookbehind:!0,inside:{"filter-name":{pattern:/^:[\w-]+/,alias:"symbol"},text:{pattern:/[\s\S]+/,alias:[i.language,"language-"+i.language],inside:n.languages[i.language]}}})}n.languages.insertBefore("haml","filter",t)}(Prism);
10
- !function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document&&document.querySelector){var e,t="line-numbers",i="linkable-line-numbers",n=/\n(?!$)/g,r=!0;Prism.plugins.lineHighlight={highlightLines:function(o,u,c){var h=(u="string"==typeof u?u:o.getAttribute("data-line")||"").replace(/\s+/g,"").split(",").filter(Boolean),d=+o.getAttribute("data-line-offset")||0,f=(function(){if(void 0===e){var t=document.createElement("div");t.style.fontSize="13px",t.style.lineHeight="1.5",t.style.padding="0",t.style.border="0",t.innerHTML="&nbsp;<br />&nbsp;",document.body.appendChild(t),e=38===t.offsetHeight,document.body.removeChild(t)}return e}()?parseInt:parseFloat)(getComputedStyle(o).lineHeight),p=Prism.util.isActive(o,t),g=o.querySelector("code"),m=p?o:g||o,v=[],y=g.textContent.match(n),b=y?y.length+1:1,A=g&&m!=g?function(e,t){var i=getComputedStyle(e),n=getComputedStyle(t);function r(e){return+e.substr(0,e.length-2)}return t.offsetTop+r(n.borderTopWidth)+r(n.paddingTop)-r(i.paddingTop)}(o,g):0;h.forEach((function(e){var t=e.split("-"),i=+t[0],n=+t[1]||i;if(!((n=Math.min(b,n))<i)){var r=o.querySelector('.line-highlight[data-range="'+e+'"]')||document.createElement("div");if(v.push((function(){r.setAttribute("aria-hidden","true"),r.setAttribute("data-range",e),r.className=(c||"")+" line-highlight"})),p&&Prism.plugins.lineNumbers){var s=Prism.plugins.lineNumbers.getLine(o,i),l=Prism.plugins.lineNumbers.getLine(o,n);if(s){var a=s.offsetTop+A+"px";v.push((function(){r.style.top=a}))}if(l){var u=l.offsetTop-s.offsetTop+l.offsetHeight+"px";v.push((function(){r.style.height=u}))}}else v.push((function(){r.setAttribute("data-start",String(i)),n>i&&r.setAttribute("data-end",String(n)),r.style.top=(i-d-1)*f+A+"px",r.textContent=new Array(n-i+2).join(" \n")}));v.push((function(){r.style.width=o.scrollWidth+"px"})),v.push((function(){m.appendChild(r)}))}}));var P=o.id;if(p&&Prism.util.isActive(o,i)&&P){l(o,i)||v.push((function(){o.classList.add(i)}));var E=parseInt(o.getAttribute("data-start")||"1");s(".line-numbers-rows > span",o).forEach((function(e,t){var i=t+E;e.onclick=function(){var e=P+"."+i;r=!1,location.hash=e,setTimeout((function(){r=!0}),1)}}))}return function(){v.forEach(a)}}};var o=0;Prism.hooks.add("before-sanity-check",(function(e){var t=e.element.parentElement;if(u(t)){var i=0;s(".line-highlight",t).forEach((function(e){i+=e.textContent.length,e.parentNode.removeChild(e)})),i&&/^(?: \n)+$/.test(e.code.slice(-i))&&(e.code=e.code.slice(0,-i))}})),Prism.hooks.add("complete",(function e(i){var n=i.element.parentElement;if(u(n)){clearTimeout(o);var r=Prism.plugins.lineNumbers,s=i.plugins&&i.plugins.lineNumbers;l(n,t)&&r&&!s?Prism.hooks.add("line-numbers",e):(Prism.plugins.lineHighlight.highlightLines(n)(),o=setTimeout(c,1))}})),window.addEventListener("hashchange",c),window.addEventListener("resize",(function(){s("pre").filter(u).map((function(e){return Prism.plugins.lineHighlight.highlightLines(e)})).forEach(a)}))}function s(e,t){return Array.prototype.slice.call((t||document).querySelectorAll(e))}function l(e,t){return e.classList.contains(t)}function a(e){e()}function u(e){return!!(e&&/pre/i.test(e.nodeName)&&(e.hasAttribute("data-line")||e.id&&Prism.util.isActive(e,i)))}function c(){var e=location.hash.slice(1);s(".temporary.line-highlight").forEach((function(e){e.parentNode.removeChild(e)}));var t=(e.match(/\.([\d,-]+)$/)||[,""])[1];if(t&&!document.getElementById(e)){var i=e.slice(0,e.lastIndexOf(".")),n=document.getElementById(i);n&&(n.hasAttribute("data-line")||n.setAttribute("data-line",""),Prism.plugins.lineHighlight.highlightLines(n,t,"temporary ")(),r&&document.querySelector(".temporary.line-highlight").scrollIntoView())}}}();
11
- "undefined"!=typeof Prism&&Prism.hooks.add("wrap",(function(e){"keyword"===e.type&&e.classes.push("keyword-"+e.content)}));
12
- !function(){if("undefined"!=typeof Prism){var e=Object.assign||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e},t={"remove-trailing":"boolean","remove-indent":"boolean","left-trim":"boolean","right-trim":"boolean","break-lines":"number",indent:"number","remove-initial-line-feed":"boolean","tabs-to-spaces":"number","spaces-to-tabs":"number"};n.prototype={setDefaults:function(t){this.defaults=e(this.defaults,t)},normalize:function(t,n){for(var r in n=e(this.defaults,n)){var i=r.replace(/-(\w)/g,(function(e,t){return t.toUpperCase()}));"normalize"!==r&&"setDefaults"!==i&&n[r]&&this[i]&&(t=this[i].call(this,t,n[r]))}return t},leftTrim:function(e){return e.replace(/^\s+/,"")},rightTrim:function(e){return e.replace(/\s+$/,"")},tabsToSpaces:function(e,t){return t=0|t||4,e.replace(/\t/g,new Array(++t).join(" "))},spacesToTabs:function(e,t){return t=0|t||4,e.replace(RegExp(" {"+t+"}","g"),"\t")},removeTrailing:function(e){return e.replace(/\s*?$/gm,"")},removeInitialLineFeed:function(e){return e.replace(/^(?:\r?\n|\r)/,"")},removeIndent:function(e){var t=e.match(/^[^\S\n\r]*(?=\S)/gm);return t&&t[0].length?(t.sort((function(e,t){return e.length-t.length})),t[0].length?e.replace(RegExp("^"+t[0],"gm"),""):e):e},indent:function(e,t){return e.replace(/^[^\S\n\r]*(?=\S)/gm,new Array(++t).join("\t")+"$&")},breakLines:function(e,t){t=!0===t?80:0|t||80;for(var n=e.split("\n"),i=0;i<n.length;++i)if(!(r(n[i])<=t)){for(var o=n[i].split(/(\s+)/g),a=0,l=0;l<o.length;++l){var s=r(o[l]);(a+=s)>t&&(o[l]="\n"+o[l],a=s)}n[i]=o.join("")}return n.join("\n")}},"undefined"!=typeof module&&module.exports&&(module.exports=n),Prism.plugins.NormalizeWhitespace=new n({"remove-trailing":!0,"remove-indent":!0,"left-trim":!0,"right-trim":!0}),Prism.hooks.add("before-sanity-check",(function(e){var n=Prism.plugins.NormalizeWhitespace;if((!e.settings||!1!==e.settings["whitespace-normalization"])&&Prism.util.isActive(e.element,"whitespace-normalization",!0))if(e.element&&e.element.parentNode||!e.code){var r=e.element.parentNode;if(e.code&&r&&"pre"===r.nodeName.toLowerCase()){for(var i in null==e.settings&&(e.settings={}),t)if(Object.hasOwnProperty.call(t,i)){var o=t[i];if(r.hasAttribute("data-"+i))try{var a=JSON.parse(r.getAttribute("data-"+i)||"true");typeof a===o&&(e.settings[i]=a)}catch(e){}}for(var l=r.childNodes,s="",c="",u=!1,m=0;m<l.length;++m){var f=l[m];f==e.element?u=!0:"#text"===f.nodeName&&(u?c+=f.nodeValue:s+=f.nodeValue,r.removeChild(f),--m)}if(e.element.children.length&&Prism.plugins.KeepMarkup){var d=s+e.element.innerHTML+c;e.element.innerHTML=n.normalize(d,e.settings),e.code=e.element.textContent}else e.code=s+e.code+c,e.code=n.normalize(e.code,e.settings)}}else e.code=n.normalize(e.code,e.settings)}))}function n(t){this.defaults=e({},t)}function r(e){for(var t=0,n=0;n<e.length;++n)e.charCodeAt(n)=="\t".charCodeAt(0)&&(t+=3);return e.length+t}}();
@@ -1,85 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module PreviewHelper
4
- # :nocov:
5
- include ActionView::Helpers::AssetUrlHelper if Rails.version.to_f < 6.1
6
- # :nocov:
7
-
8
- AVAILABLE_PRISM_LANGUAGES = %w[ruby erb haml]
9
- FALLBACK_LANGUAGE = "ruby"
10
-
11
- def preview_source
12
- return if @render_args.nil?
13
-
14
- render "preview_source"
15
- end
16
-
17
- def prism_css_source_url
18
- serve_static_preview_assets? ? asset_path("prism.css", skip_pipeline: true) : "https://cdn.jsdelivr.net/npm/prismjs@1.28.0/themes/prism.min.css"
19
- end
20
-
21
- def prism_js_source_url
22
- serve_static_preview_assets? ? asset_path("prism.min.js", skip_pipeline: true) : "https://cdn.jsdelivr.net/npm/prismjs@1.28.0/prism.min.js"
23
- end
24
-
25
- def find_template_data_for_preview_source(lookup_context:, template_identifier:)
26
- template = lookup_context.find_template(template_identifier)
27
-
28
- if Rails.version.to_f >= 6.1 || template.source.present?
29
- {
30
- source: template.source,
31
- prism_language_name: prism_language_name_by_template(template: template)
32
- }
33
- # :nocov:
34
- else
35
- # Fetch template source via finding it through preview paths
36
- # to accomodate source view when exclusively using templates
37
- # for previews for Rails < 6.1.
38
- all_template_paths = ViewComponent::Base.config.preview_paths.map do |preview_path|
39
- Dir.glob("#{preview_path}/**/*")
40
- end.flatten
41
-
42
- # Search for templates the contain `html`.
43
- matching_templates = all_template_paths.find_all do |path|
44
- path =~ /#{template_identifier}*.(html)/
45
- end
46
-
47
- raise ViewComponent::NoMatchingTemplatesForPreviewError.new(template_identifier) if matching_templates.empty?
48
- raise ViewComponent::MultipleMatchingTemplatesForPreviewError.new(template_identifier) if matching_templates.size > 1
49
-
50
- template_file_path = matching_templates.first
51
- template_source = File.read(template_file_path)
52
- prism_language_name = prism_language_name_by_template_path(template_file_path: template_file_path)
53
-
54
- {
55
- source: template_source,
56
- prism_language_name: prism_language_name
57
- }
58
- end
59
- # :nocov:
60
- end
61
-
62
- private
63
-
64
- def prism_language_name_by_template(template:)
65
- language = template.identifier.split(".").last
66
-
67
- return FALLBACK_LANGUAGE unless AVAILABLE_PRISM_LANGUAGES.include? language
68
-
69
- language
70
- end
71
-
72
- # :nocov:
73
- def prism_language_name_by_template_path(template_file_path:)
74
- language = template_file_path.gsub(".html", "").split(".").last
75
-
76
- return FALLBACK_LANGUAGE unless AVAILABLE_PRISM_LANGUAGES.include? language
77
-
78
- language
79
- end
80
- # :nocov:
81
-
82
- def serve_static_preview_assets?
83
- ViewComponent::Base.config.show_previews && Rails.application.config.public_file_server.enabled
84
- end
85
- end
@@ -1,17 +0,0 @@
1
- <link href="<%= prism_css_source_url %>" media="screen" rel="stylesheet" type="text/css">
2
- <div class="view-component-source-example">
3
- <h2>Source:</h2>
4
- <pre class="source">
5
- <% if @render_args[:component] %>
6
- <code class="language-ruby">
7
- <%= h @preview.preview_source(@example_name) %>
8
- </code>
9
- <% else %>
10
- <% template_data = find_template_data_for_preview_source(lookup_context: @view_renderer.lookup_context, template_identifier: @render_args[:template]) %>
11
- <code class="language-<%= template_data[:prism_language_name] %>">
12
- <%= h template_data[:source] %>
13
- </code>
14
- <% end %>
15
- </pre>
16
- </div>
17
- <script type="text/javascript" src="<%= prism_js_source_url %>"></script>
@@ -1,56 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ViewComponent
4
- module AbstractGenerator
5
- def copy_view_file
6
- template "component.html.#{engine_name}", destination unless options["inline"]
7
- end
8
-
9
- private
10
-
11
- def destination
12
- File.join(destination_directory, "#{destination_file_name}.html.#{engine_name}")
13
- end
14
-
15
- def destination_directory
16
- if sidecar?
17
- File.join(component_path, class_path, destination_file_name)
18
- else
19
- File.join(component_path, class_path)
20
- end
21
- end
22
-
23
- def destination_file_name
24
- "#{file_name}_component"
25
- end
26
-
27
- def file_name
28
- @_file_name ||= super.sub(/_component\z/i, "")
29
- end
30
-
31
- def component_path
32
- ViewComponent::Base.config.view_component_path
33
- end
34
-
35
- def stimulus_controller
36
- if stimulus?
37
- File.join(destination_directory, destination_file_name)
38
- .sub("#{component_path}/", "")
39
- .tr("_", "-")
40
- .gsub("/", "--")
41
- end
42
- end
43
-
44
- def sidecar?
45
- options["sidecar"] || ViewComponent::Base.config.generate.sidecar
46
- end
47
-
48
- def stimulus?
49
- options["stimulus"] || ViewComponent::Base.config.generate.stimulus_controller
50
- end
51
-
52
- def typescript?
53
- options["typescript"] || ViewComponent::Base.config.generate.typescript
54
- end
55
- end
56
- end
@@ -1,13 +0,0 @@
1
- Description:
2
- ============
3
- Creates a new component and test.
4
- Pass the component name, either CamelCased or under_scored, and an optional list of attributes as arguments.
5
-
6
- Example:
7
- ========
8
- bin/rails generate component Profile name age
9
-
10
- creates a Profile component and test:
11
- Component: app/components/profile_component.rb
12
- Template: app/components/profile_component.html.erb
13
- Test: test/components/profile_component_test.rb
@@ -1,67 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "rails/generators/abstract_generator"
4
-
5
- module Rails
6
- module Generators
7
- class ComponentGenerator < Rails::Generators::NamedBase
8
- include ViewComponent::AbstractGenerator
9
-
10
- source_root File.expand_path("templates", __dir__)
11
-
12
- argument :attributes, type: :array, default: [], banner: "attribute"
13
- check_class_collision suffix: "Component"
14
-
15
- class_option :inline, type: :boolean, default: false
16
- class_option :locale, type: :boolean, default: ViewComponent::Base.config.generate.locale
17
- class_option :parent, type: :string, desc: "The parent class for the generated component"
18
- class_option :preview, type: :boolean, default: ViewComponent::Base.config.generate.preview
19
- class_option :sidecar, type: :boolean, default: false
20
- class_option :stimulus, type: :boolean,
21
- default: ViewComponent::Base.config.generate.stimulus_controller
22
- class_option :skip_suffix, type: :boolean, default: false
23
-
24
- def create_component_file
25
- template "component.rb", File.join(component_path, class_path, "#{file_name}#{options[:skip_suffix] ? "" : "_component"}.rb")
26
- end
27
-
28
- hook_for :test_framework
29
-
30
- hook_for :preview, type: :boolean
31
-
32
- hook_for :stimulus, type: :boolean
33
-
34
- hook_for :locale, type: :boolean
35
-
36
- hook_for :template_engine do |instance, template_engine|
37
- instance.invoke template_engine, [instance.name]
38
- end
39
-
40
- private
41
-
42
- def parent_class
43
- return options[:parent] if options[:parent]
44
-
45
- ViewComponent::Base.config.component_parent_class || default_parent_class
46
- end
47
-
48
- def initialize_signature
49
- return if attributes.blank?
50
-
51
- attributes.map { |attr| "#{attr.name}:" }.join(", ")
52
- end
53
-
54
- def initialize_body
55
- attributes.map { |attr| "@#{attr.name} = #{attr.name}" }.join("\n ")
56
- end
57
-
58
- def initialize_call_method_for_inline?
59
- options["inline"]
60
- end
61
-
62
- def default_parent_class
63
- defined?(ApplicationComponent) ? ApplicationComponent : ViewComponent::Base
64
- end
65
- end
66
- end
67
- end
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- <% module_namespacing do -%>
4
- class <%= class_name %><%= options[:skip_suffix] ? "" : "Component" %> < <%= parent_class %>
5
- <%- if initialize_signature -%>
6
- def initialize(<%= initialize_signature %>)
7
- <%= initialize_body %>
8
- end
9
- <%- end -%>
10
- <%- if initialize_call_method_for_inline? -%>
11
- def call
12
- content_tag :h1, "Hello world!"<%= ", data: { controller: \"#{stimulus_controller}\" }" if options["stimulus"] %>
13
- end
14
- <%- end -%>
15
- end
16
- <% end -%>
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "rails/generators/erb"
4
- require "rails/generators/abstract_generator"
5
-
6
- module Erb
7
- module Generators
8
- class ComponentGenerator < Base
9
- include ViewComponent::AbstractGenerator
10
-
11
- source_root File.expand_path("templates", __dir__)
12
- class_option :sidecar, type: :boolean, default: false
13
- class_option :inline, type: :boolean, default: false
14
- class_option :stimulus, type: :boolean, default: false
15
-
16
- def engine_name
17
- "erb"
18
- end
19
-
20
- def copy_view_file
21
- super
22
- end
23
-
24
- private
25
-
26
- def data_attributes
27
- if stimulus?
28
- " data-controller=\"#{stimulus_controller}\""
29
- end
30
- end
31
- end
32
- end
33
- end
@@ -1 +0,0 @@
1
- <div<%= data_attributes %>>Add <%= class_name %> template here</div>
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "rails/generators/erb/component_generator"
4
-
5
- module Haml
6
- module Generators
7
- class ComponentGenerator < Erb::Generators::ComponentGenerator
8
- include ViewComponent::AbstractGenerator
9
-
10
- source_root File.expand_path("templates", __dir__)
11
- class_option :sidecar, type: :boolean, default: false
12
-
13
- def engine_name
14
- "haml"
15
- end
16
-
17
- def copy_view_file
18
- super
19
- end
20
- end
21
- end
22
- end
@@ -1 +0,0 @@
1
- %div Add <%= class_name %> template here
@@ -1,46 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "rails/generators/abstract_generator"
4
-
5
- module Locale
6
- module Generators
7
- class ComponentGenerator < ::Rails::Generators::NamedBase
8
- include ViewComponent::AbstractGenerator
9
-
10
- source_root File.expand_path("templates", __dir__)
11
- argument :attributes, type: :array, default: [], banner: "attribute"
12
- class_option :sidecar, type: :boolean, default: false
13
-
14
- def create_locale_file
15
- if ViewComponent::Base.config.generate.distinct_locale_files
16
- I18n.available_locales.each do |locale|
17
- create_file destination(locale), translations_hash([locale]).to_yaml
18
- end
19
- else
20
- create_file destination, translations_hash(I18n.available_locales).to_yaml
21
- end
22
- end
23
-
24
- private
25
-
26
- def translations_hash(locales = [:en])
27
- locales.map { |locale| [locale.to_s, translation_keys] }.to_h
28
- end
29
-
30
- def translation_keys
31
- keys = attributes.map(&:name)
32
- keys = %w[hello] if keys.empty?
33
- keys.map { |name| [name, name.capitalize] }.to_h
34
- end
35
-
36
- def destination(locale = nil)
37
- extension = ".#{locale}" if locale
38
- if sidecar?
39
- File.join(component_path, class_path, "#{file_name}_component", "#{file_name}_component#{extension}.yml")
40
- else
41
- File.join(component_path, class_path, "#{file_name}_component#{extension}.yml")
42
- end
43
- end
44
- end
45
- end
46
- end
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Preview
4
- module Generators
5
- class ComponentGenerator < ::Rails::Generators::NamedBase
6
- source_root File.expand_path("templates", __dir__)
7
- class_option :preview_path, type: :string, desc: "Path for previews, required when multiple preview paths are configured", default: ViewComponent::Base.config.generate.preview_path
8
-
9
- argument :attributes, type: :array, default: [], banner: "attribute"
10
- check_class_collision suffix: "ComponentPreview"
11
-
12
- def create_preview_file
13
- preview_paths = ViewComponent::Base.config.preview_paths
14
- optional_path = options[:preview_path]
15
- return if preview_paths.count > 1 && optional_path.blank?
16
-
17
- path_prefix = if optional_path.present?
18
- optional_path
19
- else
20
- preview_paths.one? ? preview_paths.first : "test/components/previews"
21
- end
22
-
23
- template "component_preview.rb", File.join(path_prefix, class_path, "#{file_name}_component_preview.rb")
24
- end
25
-
26
- private
27
-
28
- def file_name
29
- @_file_name ||= super.sub(/_component\z/i, "")
30
- end
31
-
32
- def render_signature
33
- return if attributes.blank?
34
-
35
- attributes.map { |attr| %(#{attr.name}: "#{attr.name}") }.join(", ")
36
- end
37
- end
38
- end
39
- end
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- <% module_namespacing do -%>
4
- class <%= class_name %>ComponentPreview < ViewComponent::Preview
5
- def default
6
- render(<%= class_name %>Component.new<%= "(#{render_signature})" if render_signature %>)
7
- end
8
- end
9
- <% end -%>
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "rails/generators/abstract_generator"
4
-
5
- module Rspec
6
- module Generators
7
- class ComponentGenerator < ::Rails::Generators::NamedBase
8
- include ViewComponent::AbstractGenerator
9
-
10
- source_root File.expand_path("templates", __dir__)
11
-
12
- def create_test_file
13
- template "component_spec.rb", File.join(spec_component_path, class_path, "#{file_name}_component_spec.rb")
14
- end
15
-
16
- private
17
-
18
- def spec_component_path
19
- return "spec/components" unless ViewComponent::Base.config.generate.use_component_path_for_rspec_tests
20
-
21
- configured_component_path = component_path
22
- if configured_component_path.start_with?("app#{File::SEPARATOR}")
23
- _app, *rest_of_path = Pathname.new(configured_component_path).each_filename.to_a
24
- File.join("spec", *rest_of_path)
25
- else
26
- "spec/components"
27
- end
28
- end
29
- end
30
- end
31
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "rails_helper"
4
-
5
- RSpec.describe <%= namespaced? ? "#{namespace.name}::" : '' %><%= class_name %>Component, type: :component do
6
- pending "add some examples to (or delete) #{__FILE__}"
7
-
8
- # it "renders something useful" do
9
- # expect(
10
- # render_inline(described_class.new(attr: "value")) { "Hello, components!" }.css("p").to_html
11
- # ).to include(
12
- # "Hello, components!"
13
- # )
14
- # end
15
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "rails/generators/erb/component_generator"
4
-
5
- module Slim
6
- module Generators
7
- class ComponentGenerator < Erb::Generators::ComponentGenerator
8
- include ViewComponent::AbstractGenerator
9
-
10
- source_root File.expand_path("templates", __dir__)
11
- class_option :sidecar, type: :boolean, default: false
12
-
13
- def engine_name
14
- "slim"
15
- end
16
-
17
- def copy_view_file
18
- super
19
- end
20
- end
21
- end
22
- end
@@ -1 +0,0 @@
1
- div Add <%= class_name %> template here
@@ -1,44 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "rails/generators/abstract_generator"
4
-
5
- module Stimulus
6
- module Generators
7
- class ComponentGenerator < ::Rails::Generators::NamedBase
8
- include ViewComponent::AbstractGenerator
9
-
10
- source_root File.expand_path("templates", __dir__)
11
- class_option :sidecar, type: :boolean, default: false
12
- class_option :typescript, type: :boolean, default: false
13
-
14
- def create_stimulus_controller
15
- template "component_controller.#{filetype}", destination
16
- end
17
-
18
- def stimulus_module
19
- return "stimulus" if legacy_stimulus?
20
-
21
- "@hotwired/stimulus"
22
- end
23
-
24
- private
25
-
26
- def filetype
27
- typescript? ? "ts" : "js"
28
- end
29
-
30
- def destination
31
- if sidecar?
32
- File.join(component_path, class_path, "#{file_name}_component", "#{file_name}_component_controller.#{filetype}")
33
- else
34
- File.join(component_path, class_path, "#{file_name}_component_controller.#{filetype}")
35
- end
36
- end
37
-
38
- def legacy_stimulus?
39
- package_json_pathname = Rails.root.join("package.json")
40
- package_json_pathname.exist? && JSON.parse(package_json_pathname.read).dig("dependencies", "stimulus").present?
41
- end
42
- end
43
- end
44
- end
@@ -1,7 +0,0 @@
1
- import { Controller } from "<%= stimulus_module %>";
2
-
3
- export default class extends Controller {
4
- connect() {
5
- console.log("Hello, Stimulus!", this.element);
6
- }
7
- }
@@ -1,9 +0,0 @@
1
- import { Controller } from "<%= stimulus_module %>";
2
-
3
- export default class extends Controller {
4
- declare element: HTMLElement;
5
-
6
- connect() {
7
- console.log("Hello, Stimulus!", this.element);
8
- }
9
- }
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "rails/generators/erb/component_generator"
4
-
5
- module Tailwindcss
6
- module Generators
7
- class ComponentGenerator < Erb::Generators::ComponentGenerator
8
- source_root File.expand_path("templates", __dir__)
9
- end
10
- end
11
- end
@@ -1 +0,0 @@
1
- <div<%= data_attributes %>>Add <%= class_name %> template here</div>