Showing posts with label yeoman. Show all posts
Showing posts with label yeoman. Show all posts

Tuesday, October 7, 2014

Generating Super Simple Polymer (JS)


I really want a minimal Polymer code generator. I thought Yeoman might have something to fit my needs, but upon further review, I am not so sure.

I missed some of what Yeoman's Polymer was doing yesterday. Most the sub-generators wind up installing a lot. I had thought yo polymer:seed might be the answer to my needs. Even though it installed testing stuff too soon (and the wrong testing library) for my tastes, the rest was close. But it turns out that it just installs crazy amounts of dependencies in the parent directory thanks to the hidden .bowerrc file that it includes:
{
  "directory": "../"
}
The end result is 9 directories containing 52 files:
$ tree       
.
├── core-component-page
│   └── ...
├── elements
│   ├── bower.json
│   ├── demo.html
│   ├── index.html
│   ├── README.md
│   ├── test
│   │   ├── index.html
│   │   ├── tests.html
│   │   └── x-pizza-basic.html
│   ├── x-pizza.css
│   └── x-pizza.html
├── platform
│   ├── platform.js
│   └── ...
├── polymer
│   ├── polymer.html
│   ├── polymer.js
│   └── ...
└── polymer-test-tools
    ├── chai
    │   └── ...
    ├── karma-common.conf.js
    ├── mocha
    │   ├── mocha.js
    │   └── ...
    └── ...

9 directories, 52 files
My goal here is to generate the minimal setup required to start coding a Polymer element. I need to keep it small so that my screencasts are short—both on time and concepts.

The end result of my first screencast should be something like:
$ tree
.
├── index.html
├── elements
│   ├── x-pizza.html
│   └── x_pizza.js
├── bower.json
└── bower_components
    └── ...
I should be able to run a python simple HTTP server in the root and see the <x-pizza> element working in the index.html page.

So, I am going to let Emacs generate the index.html page. I will likely stick with a very simple HTML skeleton and add the platform.js <script> tag and the element link by hand (or keyboard shortcut). I tend to think of these as important enough to type out by hand.

For the Bower stuff, I think I will approach it by creating a minimal bower.json on the command-line:
$ echo '{"name": "x_pizza"}' > bower.json
Then install and save my Polymer dependencies:
$ bower install -S Polymer/polymer
bower polymer#*                 cached git://github.com/Polymer/polymer.git#0.4.2
...
polymer#0.4.2 bower_components/polymer
So that takes care of the index.html page and Bower, what about the element? The polymer:el generator is close to what I need, but... there are two things that give me pause.

First, the element is generated in the wrong directory (I think). Where I would prefer it go directly in elements, polymer:el puts it in app/elements/<name-of-element>/:
$ yo polymer:el x-pizza
? Would you like an external CSS file for this element? No
? Would you like to include an import in your elements.html file? No
   create app/elements/x-pizza/x-pizza.html
I could move it, but then I would have to change the polymer.html import in the generated output since bower_components will wind up in the parent directory instead of the grandparent directory:
<link rel="import" href="../../bower_components/polymer/polymer.html">
<polymer-element name="<%= elementName %>" attributes="">
  <template><% if (!externalStyle) { %>
    <-- ... -->
  </template>
  <script>
    (function () {
      'use strict';

      Polymer({
        // define element prototype here
      });

    })();
  </script>
</polymer-element>
Even that I could live with, but I think including the Polymer prototype definition in the HTML, coupled with my other pet peeves, is what will keep me from Yeoman. Emacs has a nifty JavaScript mode that I would prefer to use in a separate .js file. There are multi-minor mode solutions for working with both HTML and JavaScript in the same file, but something about it just does not feel as nice.

So I think I will wind up relying on Emacs for this as well. Speaking of Emacs, I need to dust off some of my extremely rusty elisp to modify the built-in HTML mode to accommodate <polymer-element> definition elements. Something like this in my .emacs ought to work:
(setq html-tag-alist (cons '("polymer-element" (\n
        "<template>\n    " _
        "\n  </template>\n"
        "  <script src=\"x_element.js\"></script>"
  ))
 html-tag-alist
))
When I used the HTML mode insert-element command for polymer-element, the above template will be inserted with the cursor being placed after the initial <template> tag (by virtue of the underscore). I may fiddle with yasnippet as an alternative, but I have never been able to get on board with snippets. I can remember the most obscure Emacs keyboard combinations, but I have never been able to use snippets often enough to remember them.

Regardless, I think that I will not be using Yeoman in the screencasts. It sets up beautiful Polymer elements and development layouts, but feels too noisy for my needs. Hopefully this low-key approach will work better.

Day #206

Monday, October 6, 2014

Simple Polymer Generators with Yeoman


I shaved 3 minutes off the Patterns in Polymer screencast that deals with the initial Polymer element generation in Dart. I still need to find another 3 minutes, but that is a good start. Good enough that I would to explore doing the same with JavaScript Polymer elements. Since I would like to stick with standard, maintained generators, this means Yeoman.

In all honesty, I have never used Yeoman. I tend to prefer writing initial applications / widgets by hand. I regard code that I maintain directly as too important to trust without hand-writing. If code is a starship, then I side with Sarris that a captain “know every bolt, every weld in his ship.” I might treat the inner workings of bolt creation and welding tools as abstractions that I can delve into later, but I will understand them well enough and know where they reside in my code.

That said, I don't hate code generation. Especially if they save me 3+ minutes in screencasts.

So I start by installing Yeoman:
$ npm install -g yo
/home/chris/local/node-v0.10.20/bin/yo -> /home/chris/local/node-v0.10.20/lib/node_modules/yo/cli.js

> yo@1.3.0 postinstall /home/chris/local/node-v0.10.20/lib/node_modules/yo
> node ./scripts/doctor

[Yeoman Doctor] Everything looks alright!

yo@1.3.0 /home/chris/local/node-v0.10.20/lib/node_modules/yo
├── ...
└── yeoman-generator@0.17.7 (...)
Next, I install the Polymer generator for Yeoman:
$ npm install -g generator-polymer
...
generator-polymer@0.5.1 /home/chris/local/node-v0.10.20/lib/node_modules/generator-polymer
...
With that, I am ready to run the generator in a new (temporary) project:
$ cd ~/tmp
$ mkdir x_pizza
$ cd !$
$ yo polymer
? Would you like to include core-elements? No
? Would you like to include paper-elements? No
? Would you like to use SASS/SCSS for element styles? No
   create .gitignore
   create .gitattributes
   create .bowerrc
   create bower.json
   create .jshintrc
   create .editorconfig
   create Gruntfile.js
   create package.json
   create app/404.html
   create app/favicon.ico
   create app/robots.txt
   create app/styles/main.css
   create app/scripts/app.js
   create app/.htaccess
   create app/elements/elements.html
   create app/elements/yo-list/yo-list.html
   create app/elements/yo-list/yo-list.css
   create app/elements/yo-greeting/yo-greeting.html
   create app/elements/yo-greeting/yo-greeting.css
   create app/index.html
   create app/test/index.html
   create app/test/tests.html
   create app/test/yo-greeting-basic.html
   create app/test/yo-list-basic.html
...
Yikes! That is a lot of infrastructure. I would rather focus on teaching Polymer than Polymer-on-Yeoman in these screencasts. The default page in app/index.html file and the sample Polymer element that it includes are nice demos, but I have the feeling that I may end up deleting a bunch of this for use in the screencast. On the other hand, it is nice that it creates a useful bower.json and runs bower.json. I will have to consider this.

The element generator is pretty clean however:
$ yo polymer:el x-pizza
? Would you like an external CSS file for this element? No
? Would you like to include an import in your elements.html file? No
   create app/elements/x-pizza/x-pizza.html
$ cat app/elements/x-pizza/x-pizza.html
<link rel="import" href="../../bower_components/polymer/polymer.html">
<polymer-element name="x-pizza" attributes="">
  <template>
    <style>
      :host {
        display: block;
      }
    </style>
  </template>
  <script>
    (function () {
      'use strict';
      Polymer({
        // define element prototype here
      });
    })();
  </script>
</polymer-element>
I might quibble with the Polymer class being inline instead of in a separate script file, but that is close to what I want.

But in the end, I think the seed-element generator is closer to what I need for the screencasts. There is less infrastructure, but it still generates a smoke test page and a skeleton for the template:
$ cd ..    
$ rm -rf x_pizza 
$ mkdir x_pizza
$ cd !$
$ yo polymer:seed

     _-----_
    |       |    .--------------------------.
    |--(o)--|    | Out of the box I include |
   `---------´   |        the Polymer       |
    ( _´U`_ )    |       seed-element.      |
    /___A___\    '--------------------------'
     |  ~  |     
   __'.___.'__   
 ´   `  |° ´ Y ` 

? What is your GitHub username? eee-c
? What is your element's name: x-pizza
   create .gitignore
   create .gitattributes
   create .bowerrc
   create bower.json
   create .jshintrc
   create .editorconfig
   create x-pizza.css
   create x-pizza.html
   create index.html
   create demo.html
   create README.md
   create test/index.html
   create test/x-pizza-basic.html
   create test/tests.html
...
This also runs bower install, so I will be ready to start coding right away. The demo.html page that uses the generated <x-pizza> element is welcomingly brief. The generated element, however, is crazy long—it even includes a fireLasers() method.

So it does not seem that generating scaffold code in JavaScript is going to be as easy in JavaScript as in Dart. Hopefully I can work with it to keep the running time under 10 minutes. Time will tell.


Day #205