Tip:
Highlight text to annotate it
X
[applause]
Anthony Pipkin: As Jenny mentioned, I just recently joined YUI as a core developer, and
that happened back at the beginning of July. Before then I was noted as one of the top
single individual contributors to the gallery with 28 modules. I’ve of course been surpassed
by a couple of people, but I say that to say that I know the pains that goes into creating
gallery modules and a lot of the questions that come up.
You can find me on Twitter @apipkin. I’m known throughout most of the internet by apipkin.
With the old gallery, generally what you would do is you would fork the yui3-gallery. Right
now it’s got 454 modules in there, so for your one or two modules it gets kind of lost
in the search. Then you have to go to the gallery site, register your metadata with
the gallery site, sync up everything with GitHub, and push your commits to GitHub. Then
issue a pull request or a CDN request through the site.
You have to write your code, which sometimes can be a little cumbersome. I’ll show you
an example of one of the more common errors that I’ve seen. You have to use Ant, which
is always a pain, especially if you’re on Windows and you’re trying to set up the
Ant environment to run build with the Java.
You run into errors that most of the time don’t show up until you think that it’s
going to be pushed and committed to the gallery, and then you find out on Wednesday that you
get an email that something failed, your build failed or something like that, and now you
have to wait a whole ’nother week for your gallery module to go in.
All this comes up to being headaches. It causes a lot of headaches, a lot of frustrations,
a lot of emails, a lot of time spent in the IRC channel asking questions that usually
should be avoided.
Have you ever seen something like this, where you end up writing your code and you put your
YUI.add inside of your JS file and then whenever you build it it gets the YUI.add wrapped around
it? It passes because it’s valid JavaScript, but whenever you go to actually use it it
runs into an error because, well, it’s invalid as far as the YUI standard is concerned.
This comes to a stigma that a lot of the gallery code is really poor quality, maybe that they’re
subpar developers that are out there contributing code. But there’s a lot of YUI core developers
or former core developers that are contributing stuff into the gallery too, so that stigma
shouldn’t really be valid, and there’s a lot of really intelligent people that are
writing code for the gallery. That’s just a really bad stigma.
Subpar documentation. It’s up to the developer to write documentation. It’s not really
comparable to the stuff that you would normally see inside of YUI. That’s one of the things
that’s changing.
After a while, it becomes unsupported. Usually it’s someone who wrote some code, pushed
it up, and they just wanted it on the CDN so that they could use it in a use statement
without having to run their own local combo loader.
The last one is that it’s just not as good as the core. If you have to prefix something,
like if you were including gallery treeview, or gallery button, or anything from the gallery,
just because you have to put the gallery in the tag for the use statement, you kind of
feel like it’s some other third party that may not be as good code as if it was right
off the core.
In comes Yogi. There’s a lot of tools that we’ve been using separately, a lot of revamped
ideas that Dav has put into Yogi to mediate a lot of the stuff that we’ve been doing
and having to fight with the gallery codes. It’s actually the same stuff that we use
on the YUI core to build, write documentation, run tests, test things out, submit stuff over.
It raises the bar for how you develop your gallery modules. It makes things a lot easier.
You don’t have to fight nearly as much. But it also levels the field between where
the gallery code is and how it looks and how you can find it and search for it. It looks
the same as how the core modules are.
It’s also powered by Dav Glass. He’s written a lot of tools, and they’re really awesome.
I think that speaks for itself, the fact that he wrote it. Like he said yesterday in his
talk, he was able to pull the core build from 25 minutes down to under 2 minutes, and that’s
just phenomenal right by itself. It’s also super fast. It’s super awesome.
Let’s get into a demo of how we would actually get this set up.
The first thing we want to do is we would run npm –g install yogi. I’m not going
to do this because I’ve already got it pulled down and it’s got quite a number of dependencies,
but that’s how you would pull it down. The first thing that you would want to do after
you get it in is to actually log in. This is going to be your YUILibrary.com username.
If you aren’t on YUILibrary.com and you’re wanting to commit code, you’ll need to make
sure you have a username and password for that.
Then the other thing that we want to do is we want to actually sync up to our GitHub
account. You would do that with yogi gh, for GitHub in case that was confusing. Then it
asked you if you’re sure you want to sync up your account. It pulled my username down
from my profile off of YUILibrary.com. In this case it just happens to be apipkin because
I use the same name in both places.
Now it’s synced up it’s going to be saved in there for the instance of Yogi that I have
on the computer, so we can change in any direction we want to, or in any directory we want to.
Right now I’m in projects conference and there’s nothing in here. If we go over to
Sublime we’ll see that the directory’s empty.
What we want to do is we actually want to create the module. Normally this takes in
going and creating a source directory if we don’t already have one, creating the module’s
directory, creating the JS directory, docs directory, test directory, all the meta files
and stuff like that. It takes... If you don’t have a template that you’re copying over
that you just want to change names in, it takes a good bit of time. Yogi is here to
help us.
We’ll do yogi help, and then - -detailed, and we’ll see in here there is a create
option. Then it takes the module name. We’re going to initialize the file tree and then
we’re also going to declare that it is a widget, because what we’re actually going
to make is this placeholder resizer. We’re using place kitten. If you were at Derek’s
talk he mentioned it yesterday.
The structure is that it’s placekitten.com/the-width-of-the-image, and then /the-height-of-the-image. We’ll
be able to get those dimensions from the resize and then load in a new cat or multiple kittens
as we resize. It’s going to be super useful for everyone to pull down from the gallery
and use in their projects.
All right, so we’re going to do it as a widget, and then the path is by default going
to be the widget name. If you don’t have source created already as a directory then
it will create the source directory and then build the file tree for you there. Let’s
do yogi create and then init. Our type is off the side of the screen. There we go. Widget,
and then we’re going to call this gallery-sizer. It checks on the gallery site, checks in the
database to make sure that the namespace is available, and it says yeah, it’s available,
fortunately for us. Then it says do you want to proceed? We say yes. Then it asks again
to make sure that everything looks correct. Because we created it as a widget it’s marked
as skinnable. So we’ll say yes, everything looks correct.
Then it went through the tedious process of creating this entire file tree for us. Those
are files we don’t have to worry about creating or touching or anything. You’ll notice that
there is a CSS directory. This won’t be used. If we were creating a gallery CSS module
then we would put our code in the CSS directory, but because it’s a widget we are using skins,
so we’ll be putting that up into the assets directory.
Let’s get into actually looking at the files that are generated. Now you’ll see that
in Sublime, we have all the files that are created. It creates a read me file with our
name already at the top, a history file, which should be updated every time you make a change
and do a push, for your benefit as well as the community’s benefit.
The build.json file. You’ll notice that there’s no longer the build.property, or
the build.xml file that Ant was using. There’s just one JSON file now. It’s already populated
with the name of the module. And then the JavaScript files that are created that need
to be supported for.
There’s already a test. As Dav said yesterday, the test is written to automatically fail
for us, which is great because that’s off to a good start. We know that there’s something
that we need to fix initially. The metadata, what it requires, it requires widget.
We also, because we’re going to use build.create as contrary to Ryan’s talk. If we wanted
to have multiple instances of this we would probably want to do something a little bit
more time saving, but for the sake of the talk we’ll use base.create. To get base.create
we need to require base-build. Because we’re going to be using the resizer utility, we
also need to require resize. It’s going to be skinnable, so we’ll leave that as
true, and we’ll save that file. Our JavaScript comes in, tells you exactly where to write
your code, which is super handy because I wasn’t really sure what we were going to
do with the JavaScript file here.
Let’s go ahead and write our code.
[applause]
You’ll notice in the code that I spent a while preparing this so I didn’t have to
do the live coding and have a bunch of errors to fix, because that’s how I write code.
We already have our JavaScript documentation built into it, and this is going to come into
play whenever we are using YUI Docs with Yogi to create our API documentation, just the
same way that you would see your API documentation whenever you’re looking at YUI core modules
on YUI Library.
We have our description, the name of the module, the class, the version since. We haven’t
done anything except this one instance of it. Saving it out to Y.Sizer. Every method
has documentation to go with it, with a description, whether it’s public or protected or private,
if you want to list it as private, the method name, and what version it’s been since.
If you were passing in parameters you would do param, if it was returning a value you
would do returns. There’s a lot more documentation that’s out there under yui.github.com/yuidoc.
It’s really good, really resourceful. It tells you how to define the types, and you
can also do stacked if you were passing in an object with different properties in it.
It’s really handy for that.
We’ll go down to some protected methods, like makeResize, where it’s initialized
the resize component. We’ll notice that it’s listed as protected, so that’s going
to come into play whenever we look at the API documentation.
For the attributes you’ll see that there’s a description in here, the type is a string,
and by default we’re going to placekitten.com. There is a couple of other ones out there,
like placedog and lorempixel. They use the same format. You would be able to change this
configuration if you got tired of seeing kittens all the time in your resize placeholder. You
could change that through the configuration.
The default skin, our default width and height are set. Resize utility provides a way to
set our constrain proportions to whether it can be resized any smaller than a certain
size or resized larger than a certain size, so that’s where min and max come in, the
configuration. Whenever we instantiate the resize utility we pass directly into that.
Even though it’s hidden inside the module, we still provide a way to get through it.
Then the text template that was on top of the resize utility is just a simple string
that we’re using the Y.Lang.sub to go in and do simple string replacement on.
For the documentation, that will come in for the user guides. We’ll get into that in
just a moment. Our CSS, we don’t need that directory because it’s a widget, and the
CSS is going to go into a skin so that’s going to be under the assets folder.
For the core, we’ll write some CSS for that. Then the particular thing that you do with
different skins is of course going to be something that is common CSS that goes across all of
the skin types, whereas for sam skin or the night skin or whatever you want to call your
skin would be based on the skin name. Generally that would change colors or font styles or
something like that. We’ll just put a little bit of code in there for that one.
For our documentation, we get something stubbed out here that tells you that your summary
goes here, your module description goes here. Let’s get rid of this and let’s type our
documentation. This is our documentation. We’ve got a couple of really awesome things
for Mustache to come in. This is all taken care of with Selleck, like the documentation
is generated with Selleck. In our component.json file we have our name... This is already generated
by Yogi for us. We have our name, our display name, which is how it would be listed on the
site itself. So if we go over to this and we go to user guides, this is where the display
name would be taken care of.
What we’re doing now is the user guides. This is where the description shows up, and
then the getting started is boilerplate that we put in that automatically builds that small
section for you. This is where your description goes in. We’ll say my name is going in as
the author. If you have multiple authors it’s an array, so it supports that. The tags...
We want to say that it’s a widget as well as a gallery component. We’ll say that and
come back to the example side.
The getting started, like I was saying a while ago, it’s boilerplate. This is a partial
that’s stored up in Selleck that will automatically generate this section, this getting started
section, for us. To pull over the configuration attributes, so you don’t have to always
go to the API to read how the configuration works out, it’s generally a good idea to
build a table so that we can see that.
Dav showed you yesterday that Yogi has an internal server built in to it to run our
API documentation and our user guides. Let’s go ahead and serve Yogi after we go into the
correct directory. It tells us that we’re serving off of local host 5000. This is what
Yogi actually generates for us. It lets us know that it’s actually here to help.
Our API documentation that we had with our JavaScript file, with the JDoc syntax in there,
we have our methods created with our descriptions. There were some protected methods, so if we
want to see those we can check the box and we have our protected methods listed as well
as our public methods. If we had private there’s a checkbox for that as well. For attributes,
same way. Because they have the... It’s done through attribute and it has all the
change events in it. That’s automatically added for us. We don’t have to worry about
adding that documentation into our API docs. So that’s really awesome.
With our gallery or with our user guides, the examples in the landing page, it comes
in here. This is our display name, our short description, our getting started code that
was included automatically for us with the partial, and then our configuration table.
One thing that’s really missing is our examples, so let’s go in and add an example real quick.
I’ll see how fast we can actually make this happen. We’ll go into the examples array
and we’ll write some metadata for our example with the name, display name, description,
the modules, and tags for it. We’ll need to create file, so this is going to be...
That is going to be incorrect. The name, it’s either simple... And then we’ll save it
as a Mustache file. Not that one.
So this is going to be our demo code. We have our CSS that we’re going to include, any
additional HTML that we want to include in the example, any JavaScript that we want to
put in there, and then we’ll also display the JavaScript and the CSS.
I don’t know how familiar you are with how Mustache and Handlebars work, but with the
partial, we’ll create a new directory called partials. These are going to be custom partials
that we’re creating, so the name of the file followed by .mustache. We’ll do this
for each one of the partials that we want to create.
Our example is going to be really complicated because all we have to do is initialize the
JavaScript, or the component itself. That’s just sizer is equal to new Y.Sizer, and then
we want to render it into the demo node for our documentation. CSS we want to jazz it
up just a little bit, so we’re just going to modify how the demo style actually looks.
We’ll save our example... We don’t need any HTML, so that’s just in there. I put
that in there just in case I wanted to add any extra HTML around it, but it turns out
we didn’t need it.
We’ll have this actually get the JavaScript actually be implemented because it’s inside
of script tags. We don’t need this in here. But we’ll actually be able to see the code
example, print it out inside of the triple backtick enclosure.
Let’s refresh this. Now we have our example. Hm, undefined is not a function. Our use statement
didn’t work, okay. Let’s go back in and update that. Let’s make sure I didn’t
leave out a name somewhere.
[Dav Glass makes inaudible comment]
Anthony: Yeah. Make sure this isn’t the issue.
Dav: Yogi build.
Anthony: Yogi build? All right, so let’s stop the server. Tell it to build. That actually
runs Shifter under the hood to build our min files. That was a good catch, Dav. That’s
why I’m glad he’s back there. A lot of this stuff is really new, I actually just
got this this past Friday with the create methods inside of it. And we need to restart
our server. All right, we’ll come back to that. I’ve got an example in another file
that works.
The other thing that I want to show is the tests. Right now there is a test that’s
automatically generated and it fails for us. If we go into our tests we’ve already got
a test suite created. We’ll want to have sizer equal to null for our instance that
we’re going to create. We’ll get rid of this one test that’s created that fails,
and then we’ll write some test code.
Our test code will initialize sizer. We’re going to check to make sure that setting the
width and height through the attributes is actually changing the width and height of
the component itself. The way we do that at first is we check to make sure that what it’s
currently set to is what it actually is, then we’ll set it and then we’ll check again
to make sure what it’s currently set to is actually where it’s at.
The next thing that we’ll do is we’ll check for whenever we... After the image loads,
so once we resize and it gets a new image in, we’ll want to make sure that the URL
that we’re passing in with the width and height being replaced is actually the URL
that’s being loaded into the image.
Just some general tests, we’re not testing functionality of drag. That’s a little bit
more involved. Now that we have the test in here, let’s make sure we save, and we’re
going to run into the same issue with the test not being able to find it. We’ll go
up to my other...
Now we’ll be able to see that it actually renders and we can still resize it, and then
if we run the tests again it resizes it down to the size that we had in here, for 250 by
250. It says that all the tests passed, and we had a total of two tests.
The other thing is doing it with Yogi or with coverage. Right now you have to start your
server running… Istanbul is an option, but soon I believe that’s going to be set by
default. If we run it with Istanbul and it’s on the same port, our coverage will actually
take our test, give us a report back that says that we only covered 50 per cent of our
branches with our test and 75 per cent of our function calls. We can go into the directory
and then go into the actual file to see the printout of it. This lets us know that the
else path wasn’t taken, this branch wasn’t taken, this branch wasn’t taken, these functions
weren’t actually called because these are being called whenever you actually drag and
resize. It’s super useful.
The benefit of this is that if we go into gallery sizer and we make changes to the code,
we’re able to just hit a button and run tests and make sure we don’t have any regressions.
That gives us our API documentation, it gives us our user guide documentation. We’ve got
our test. So the last thing that we want to do is we want to actually get this pushed
up to the gallery. Before you would push this over you would commit this to GitHub. You’d
go into the website, you would find your last commit statement in Git and issue a CDN pull
request.
Now let’s go back to our clean one that we just created. We’ll add it in and actually
do a commit. We’ll add in our build statements. All right, so now I have a clean build, or
a clean Git. We’ll push this over. Let’s actually go over to GitHub and create a repository
for it. So we’ll create a repository, we’ll add it in.
Audience member: Clear your screen.
Anthony: Okay, it’s already set to our YUI conference. That’s good, I’m good with
that one. We’ll push up.
Then the magic at Yogi actually comes in where we’ll do a CDN request. Then it says do
we want to do initial release, and we’ll say yes, that’s the one we want. Now it
is successfully in the CDN queue. No more having to go to the gallery website, surfing
around trying to find your module, clicking request. You can do this all from the command
line.
Now if we want to check on our status, we can check that it’s not in the queue yet.
Then once it actually gets approved you can use yogi history and you’ll see that it was actually approved.
Dav: It wasn’t approved.
Audience member: Dav Glass denied it.
Anthony: Oh.
[laughter]
Dav Glass automatically denied us apparently. But it was auto-approved whenever we first
created it…
Dav: Do it again.
Anthony: And the module itself was approved. But whenever we did the CDN request it was
denied.
[Dav Glass makes inaudible comment]
We’ll do another one. It was successfully pushed, or it was successfully requested.
Now it’s still waiting approval on the status. Now we can see that it’s in the CDN deployment
queue as of just a few minutes ago. Now you can get all of that information and see, if
we go into yogi history we’ll see what it tells us. It tells us that it was denied a
while ago, and now it’s approved even though we didn’t make any changes to our code.
[applause]
Excellent.
So a few commands that we went over. You have to log in with Yogi to get things going up
to the gallery. Sync your Yogi with GitHub. Create your Yogi module. You can initialize
it if you need the file tree. If you’ve already got the file tree – say it’s a
module that you’re wanting to get converted over to something Yogi supports - Dav showed
you yesterday that it’s just yogi update and then changing where your source directory
is.
You can see that it went to a repo called yuiconf2012, not our fork of yui3-gallery.
It’s the only thing that’s sitting in that repo, and that makes my life easier whenever
I’m trying to search through and get my module to make some changes to it.
That will register a new module. It will initialize the tree for you, and then you can define
the type. If you don’t want to define the type you’ll get a default branch or default
tree built, but I recommend defining the type. That way you get all the files that you know
you need.
Yogi serve will give you the page that we saw a while ago with this list in it. It gives
you your two types of documentation and your two types of tests, one without coverage and
one with coverage. Both of those are equally important to run through. Then if you run
Istanbul as the option, you’ll get even better coverage information.
Yogi lint, we didn’t cover this, but yogi lint is really awesome because it will lint
your JavaScript to make sure that it’s written very well. Then there’s yogi test that will
run it on the command line.
Let’s take a look at that one real quick. This is actually running the same tests that
we had a while ago, but what we saw that was happening with undefined, that it wasn’t
able to pull in the gallery module, we can see that the same errors that we were seeing
in the console log are coming into the command line. Let’s go to the one that was working
before on the test we’re passing. You’ll see that we actually get information that
the test passed. We can actually run our coverage in here with Istanbul and we’ll get the
same output in some nice fancy ASCII art. It’s nice and legible.
Then there’s yogi help. Better yet, there’s yogi help with detailed information that gives
you a super long list, because Yogi is jam packed and here to help write modules for
you, or help you write modules.
Whenever you’re in the community, there are the forums that are out there. If you’re
writing modules and you need help, feel free to jump on the forums. You can file tickets
if you find bugs in Yogi or in other gallery modules or core modules. Or better yet write
a pull request, because that means that we don’t have to debug it and then write the
code and make sure that it works. If you know what the issue is and you can write the pull
request, submit it up and we’ll pull it in.
Another way to really interact with the community is how I got involved with it about three
or four years ago, and that was joining on the IRC channel. A lot of really helpful people.
Luke Smith was actually the first Yahoo! core developer that I talked to that got me super
motivated in writing YUI modules, and now I’m up here talking about it.
Special thanks to Dav Glass for giving me a hard time during the presentation and for
writing awesome tools, Krishnan who wrote Istanbul for us, and then Mark James who is
the author of place kitten.
Thank you very much.
[applause]
Jenny Han Donnelly: Thanks Tony. Is Krishnan here? Bummer. Krishnan’s a super awesome
Yahoo! who wrote Istanbul, which is a JS based coverage tool that we are super excited about,
and you can find that on GitHub.
Question over here?
Audience member: Can you use all of these... Let’s say that I’m writing my own code
for my company and I don’t necessarily want to publish that in the gallery, but can I
still use Yogi for doing all that and creating the templates and all that?
Anthony: Right now you can’t. That is coming, to be able to initialize the file tree without
having to submit it as... Hm?
Dav: Yogi init.
Anthony: Hm?
Dav: Yogi init.
Anthony: Oh, is that in now? Oh, sweet. Yeah, apparently you can. Yogi init is in there.
Let’s go and create another directory and see this work. That way we can call him out
if it doesn’t.
[laughter]
Then just the module name, Dav?
Dav: Yep. It’s going to be a git repo.
Anthony: And then we’ll say yes, and there’s our file tree. So without even having to connect
to YUILibrary.com we can create modules and never have to push up to the gallery, yeah.
So that’s awesome. Thanks for getting that done, Dav.
[laughter]
Yeah?
Audience member: Hi, I had a question. When you create a pull request, is it a good idea
to create a ticket first, or can we create a GitHub issue, or how does that work?
Anthony: I would let someone else...
Jenny: I’ll take a stab. If there’s a bug, file the bug and then issue a pull request
because we may or may not merge in your pull request if it meets our contribution standards
or not. But at least if the pull request doesn’t get merged in, the bug is still long lived
and other people can try to fix the bug. If it’s not a bug and more of an enhancement,
that’s really up to you. We don’t necessarily need to track it by a bug, but if it is a
true bug please file a bug first.
Over here.
Audience member: So this Yogi test runs only for one module, or you can run multiple modules?
Anthony: You can run multiple modules. Whenever we run in the core, we can have it run across
the entire all 90 something modules that we have.
Yeah?
Audience member: Yeah, so I noted in the metadata there was an array for authors. Does that
mean that we’re approaching a time when if you and I are collaborating on a gallery
module, either of us could submit a CDN request and maintain that module?
Anthony: I would imagine so, yes, and then both of us be listed on there as the author.
Dav: Coming soon.
Audience member: Thanks Dav.
[laughter]
Audience member: Is there any easy way to move our core modules from the gallery to
a different repo? Conserving all the history and all that, I mean.
Anthony: That would be more something with Git to take care of that. But I’m sure Dav’s
got a...
Dav: Yeah, actually I showed it yesterday in my keynote. To move a module from the yui3-gallery
repo into your own, yogi info has a couple of set methods on it that you can set the
path to the module and the repo name. So you could actually move it to a different repo
and you could put it in foo, bar, baz source my module, so you don’t have to keep everything
at the top of the tree like we do and you can name it whatever you want.
Anthony: That will keep your history with the gallery but you would lose...
Dav: You could actually do a couple of get commands to pull your directory over and just
morph your history if you wanted to.
Anthony: Okay.
Any more questions?
Jenny: All right, thanks Tony.
Tony: Thank you.
[applause]