Tuesday 16 June 2020

create an npm package with a simple node.js module on ubuntu

Today I want to create a npm package for a simple javascriptlibrary with modules and some tests. Src:https://egghead.io/lessons/javascript-how-to-write-a-javascript-library-configuring-npm-and-creating-a-package-json

At first we need a git repository on github.

Create a repository named "starwarsNames"

Login into your github account and create a new repository "starwarsNames"

echo "# starwarsNames" >> README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin https://github.com/pboethig/starwarsNames.git
git push -u origin master

create an account on https://www.npmjs.com, if you dont have one
You will need an account there to publish your extension. 

Remember your <npm-username> you will need it.

Install nodejs
$ apt-get install nodejs
$ sudo ln -s /usr/bin/nodejs /usr/bin/node  

Install npm, if npm is not installed 
$ apt-get install npm 


If you are on windows you have to install it manualy, If you are on mac, you can use the packagemanager,

At next we inititialize the npm project. 
$ npm set init-author-name 'Your Name'
$ npm set init-author-email 'your email'
$ npm set init-author-license 'MIT'
$ npm set save-exact true

If you want to check that config, you can do it with
$ cat ~/.npmrc

Add your npm user to your project 
$ npm adduser
Username: <your npm-username>
Password: <your npm-password>
Email: (this IS public) <your npm-email>

Initilize your npm project
$ npm init

this will ask some data from you, and puts outs the package.json for you

name: (starwars-names-<your npm username>)
version: (1.0.0)
license: (MIT)
About to write to /var/www/html/starwarsNames/package.json:

{
  "name": "starwars-names",
  "version": "1.0.0",
  "description": "get random starwars names",
  "main": "src/index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+ssh://git@github.com/pboethig/starwarsNames.git"
  },
  "keywords": [
    "random",
    "starwars"
  ],
  "author": "pboethig",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/pboethig/starwarsNames/issues"
  },
  "homepage": "https://github.com/pboethig/starwarsNames#readme"
}

Okay. Lets create our first module:
- create a folder "src" in your projectroot to store our module sources.
- now , create a file "index.js" in the new src folder

Open this new file in your code editor. I am using vscode for it. That editor  has great node.js plugins.

Now we want to define our modulestructure. 
Type following code in index.js

var starWarsNames = require('./starwars-names.json');
module.exports =
{
    all,
    random
};
             


 
This tells node that you want to store the "starwars-names.json" list in a variable, that your module will use and it exports 2 properties ("all" and "random")

At next save the starwarsnames in a file "starwars-names.json" in your "src" folder:
 
 
[
  "4-LOM",
  "Ayla Secura",
  "Admiral Ackbar",
  "Ahsoka Tano",
  "Anakin Solo",
  "Asajj Ventress",
  "Aurra Sing",
  "Senator Bail Organa",
  "Barris Offee",
  "Bastila Shan",
  "Ben Skywalker",
  "Bib Fortuna",
  "Boba Fett",
  "Bossk",
  "Brakiss",
  "C-3PO",
  "Cad Bane",
  "Cade Skywalker",
  "Callista Ming",
  "Captain Rex",
  "Carnor Jax",
  "Chewbacca",
  "Clone Commander Cody",
  "Count Dooku",
  "Darth Bane",
  "Darth Krayt",
  "Darth Malgus",
  "Darth Maul",
  "Darth Nihilus",
  "Darth Vader",
  "Dash Rendar",
  "Dengar",
  "Durge",
  "Emperor Palpatine",
  "Exar Kun",
  "Galen Marek",
  "General Crix Madine",
  "General Dodonna",
  "General Grievous",
  "General Veers",
  "Gilad Pellaeon",
  "Grand Moff Tarkin",
  "Greedo",
  "Han Solo",
  "IG 88",
  "Jabba The Hutt",
  "Jacen Solo",
  "Jaina Solo",
  "Jango Fett",
  "Jarael",
  "Jerec",
  "Joruus CBaoth",
  "Kent C. Dodds",
  "Ki-Adi-Mundi",
  "Kir Kanos",
  "Kit Fisto",
  "Kueller",
  "Kyle Katarn",
  "Kyp Durron",
  "Lando Calrissian",
  "Luke Skywalker",
  "Luminara Unduli",
  "Lumiya",
  "Mace Windu",
  "Mara Jade",
  "Mission Vao",
  "Natasi Daala",
  "Nom Anor",
  "Obi-Wan Kenobi",
  "Padmé Admidala",
  "Plo Koon",
  "Pre Vizsla",
  "Prince Xizor",
  "Princess Leia",
  "Proxy",
  "Qui-Gon Jinn",
  "Quinlan Vos",
  "R2-D2",
  "Rahm Kota",
  "Satele Shan",
  "Savage Opress",
  "Sebulba",
  "Shaak Ti",
  "Shmi Skywalker",
  "Talon Karrde",
  "Ulic Qel-Droma",
  "Visas Marr",
  "Watto",
  "Wedge Antilles",
  "Yoda",
  "Zam Wesell",
  "Zayne Carrick",
  "Zuckuss"
]

At next we need a further npm library called unique-random-array.
Lets install it with:

$ npm install --save unique-random-array

This will save the new library to our dependency definition in package.json

Now lets use the new array library in our index.js
 
var uniqueRandomArray = require('unique-random-array');
var starWarsNames = require('./starwars-names.json');
module.exports =
{
    all,
    random
};


Our index.js now looks like that

var uniqueRandomArray = require('unique-random-array');
var starWarsNames = require('./starwars-names.json');
module.exports =
{
    all: starWarsNames,
    random:uniqueRandomArray(starWarsNames)
};
Now that we have the library included, lets use it in our module.

In the export function, we want to reference all starwars-names to the property "all" and a random startwars-name to the property "random".

To to that we only have to export the local variable "starwarsNames" to the global scope by referencing the  exportproperty "all" and the array-function uniqueRandomArray(starwarsNames) from our new library to the export-property "random". Here is the code of "index.js".
Now our index.js looks like that 

 var uniqueRandomArray = require('unique-random-array');
var starWarsNames = require('./starwars-names.json');
module.exports =
{
    all: starWarsNames,
    random:uniqueRandomArray(starWarsNames)
};

Yeah, we havehacked our first node module.

Lets test it!
- open a terminal and navigate to the root folder of your app 
$ node
$ var starwarsNames = require('./src/index.js');
$ starwarsNames.all
$ starwarsNames.random()  

The single commands will output the whole list of names and a random name from the list. Thats realy great!


Now we want to publish it in npm as an own package. 
For that, we have to commit it to our git repository.

open a terminal:
$ cmd to your projectroot
$ touch .gitignore
$ nano .gitignore

add "node_modules" to your .gitignore to prevent commiting the node_modules.

$ git add *
$ git commit -m "init"
$ git push origin master

Thats it.

Now we can publish it to npm.
Thats realy simple.

Just type:
$ npm publish

That it. Now you should directly see your new package on npm !

This is awesome!

Now we want to test, if our module is directly usable via npm.
- open a terminal to the desktop 
$ npm install starwars-names-<your npm_user> 

Super. Now you can use your library, from anywhere in the world.
switch to the desktop and create a file named "test.js" with following content:

var starwarsNames = require('starwars-names-mittax');
console.log(starwarsNames.all);
console.log(starwarsNames.random());

Now run a terminal and cd to the directory where you have stored test.js and run:
$ node test.js

You will now see the results from your library.

This is realy cool!


Thanky to Kent.C.Dotts for the great video! 

Monday 8 June 2020

Step to Create Your Own Blogger Template


I've always wanted to create my own Blogger template and tried so many times before but couldn't really get it right. I think I finally understood a somehow large chunk of it. I think.
Anyway, here in this post, I will note about the things I have learned/will learn in creating your own template. I won't be getting into much detailed stuff on HTML and CSS how to's. I'm assuming that you already have basic knowledge on these subjects and that you know your way around Blogger. Still, if you have any questions or there is something I didn't explain well, just feel free to leave a comment, and hopefully I can answer it.
Also, since I am also just learning about this, please don't expect a fully functional and Template-Designer-compatible template -- especially since I don't really use the Template Designer. However, I will try to make it as flexible as possible.
If you are to follow along the stuff I will note below, here are some suggested steps on getting started:
  1. Create a new blog for your test template, if you haven't got one yet and select a Simple template. It's best if everything is in its default state. This way, you can really see the changes you apply in your template. Also you wouldn't want to play around with your live blogs and unintentionally mess it up.
  2. Before making any changes, download a copy of the template (Template » Backup/Restore) for reference.
  3. For your test blog, in the Layout page, remove all widgets (Archive, Profile, Lists...) except for Blog Posts. If you can't get rid of the Header and Attribution widgets, edit the template (Template » Edit HTML) and search for Header1. On that line of code, change locked='true' to locked='false'. Do the same for the Attribution by searching Attribution1. Once done, go back to the Layout page and try deleting them. Hopefully that should work. UPDATE: Removing the widget in Blogger's HTML editor will also remove the widget from your template layout (unlike before). Yay!
  4. Once you remove all possible widgets, create a New Post. You can use default text templates found here at Html Ipsum. These templates already consists of HTML tags you would normally use in a blog post. Having a test post like this will be a big help in designing your template.
  5. Also, don't forget to set your test blog's privacy settings - Not listed on Blogger; Not visible to search engines. If you won't be using external apps for further testing, you can also set the permission (Blog readers) to Blog author instead of Anyone.
Stripped the Layout.
Fig.1 - Stripped the Layout.
Now onto the code and stuff. If you are editing your template's xml file in a different editor (like Notepad++) other than Blogger's, be sure to set its encoding to UTF-8 without BOM.

Understanding the <b:section> and <b:widget> tags

Must read: Intro, Section and Widget attributes. This page gives a brief explanation of the Section and Widget parts of the template. Also the attributes of the <b:section> and <b:widget> tags are listed here which we will use later on.
Blogger Template Sections and Widgets
Fig.2 - Just a quick summary minus the attributes.
So I made some tests and this is the leanest code I can upload to Blogger. This, by the way, is based on the Simple template - well at least the first 15 or so lines.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html>
<html b:version='2' class='v2' expr:dir='data:blog.languageDirection' xmlns='http://www.w3.org/1999/xhtml' xmlns:b='http://www.google.com/2005/gml/b' xmlns:data='http://www.google.com/2005/gml/data' xmlns:expr='http://www.google.com/2005/gml/expr'>
<head>
  <meta content='IE=EmulateIE7' http-equiv='X-UA-Compatible'/>
  <b:if cond='data:blog.isMobile'>
    <meta content='width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0' name='viewport'/>
  <b:else/>
    <meta content='width=1100' name='viewport'/>
  </b:if>
  <b:include data='blog' name='all-head-content'/>
  <title><data:blog.pageTitle/></title>
  <b:skin>
  </b:skin>
</head>

<body>
  
  <b:section id='header' class='header' maxwidgets='' showaddelement='yes'>
  </b:section>

</body>
</html>
Fig. 3 - Simplest template code.
I tried leaving out the <b:skin/> tags but I get a
We were unable to save your template. Your template could not be parsed as it is not well-formed. Please make sure all XML elements are closed properly. XML error message: (SyntaxError) : Unexpected token <
UPDATE: The XML error message now says "There should be one and only one skin in the template, and we found: 0"
Also, the <body> cannot be left empty. It should always at least have a <b:section> tag. Otherwise you would encounter this error:
... XML error message: Could not find a preferred section to add deleted widgets to.
UPDATE: The XML error message now says "We did not find any section in your template. A template must have at least one b:section tag."
So after uploading the template (Fig.3), a quick preview shows me this:
Fig.4 - Template preview.
As seen on the Layout page (Fig.1) and on the preview (Fig.4), the Blog widget will always be set. So looking at the HTML code in Blogger (Template » Edit HTML), you will see that a <b:widget id='Blog1' locked='false' title='Blog Posts' type='Blog'/> has been inserted in between the <b:section> tag we created. Note that the id I used for this section is header. This I will change in a bit since I don't think we should leave the Blog widget inside this header section. UPDATE: If you uploaded the template in Fig.3, what you would actually see is an empty page because the Blog widget will no longer be automatically created. You have to add this yourself for you to view any post on the page.
Fig.5 - A Blog widget is automatically created in our template. Make sure to include the Blog widget so that you can view your blog posts. This is no longer automatically created.
Ok so now fixing the Blog widget's location. I created a new <b:section> tag, with an id main for the Blog widget and updated the attributes of the header section. So now we get this:

<body>
  
  <b:section id='header' class='header' maxwidgets='1' showaddelement='yes'>
  </b:section>

  <b:section id='main' class="main" maxwidgets='' showaddelements='yes'>
    <b:widget id='Blog1' locked='false' title='Blog Posts' type='Blog'/>
  </b:section>
  
</body>
Fig.6 - Added a new section for the Blog widget.
Fig.7 - New Layout after adding a new section.
Now that we have an Add a Gadget option for the header section in the Layout page, let's add a Page Header widget. Then on the Edit HTML part of the Template page, you will see the Page Header widget right below the <b:section id='header' ...> tag. Note: Just leave the Expand Widgets Templates unchecked. We won't be needing this just yet.
As a precaution to prevent deleting the Header when someday we are drowsily updating our blog template, set the header's locked attribute to true.
By now, you can probably see the pattern of Blogger's template code. We create sections in the template and specify its attributes. Then on the Layout page, we can add widgets (using Add a Gadget) to the section we have created. Note that we don't necessarily have to use Add a Gadget to add a widget to our template. You can do this manually by coding it in your template.
So for example, I would like to add an HTML/Javascript widget below my blog posts. So following this link mentioned earlier, we can see the syntax and attributes of a <b:widget> tag. I would then code my template like this:

<body>
  
  <b:section id='header' class='header' maxwidgets='1' showaddelement='yes'>
    <b:widget id='Header1' locked='true' title='Testground (Header)' type='Header'/>
  </b:section>

  <b:section id='main' class="main" maxwidgets='' showaddelements='yes'>
    <b:widget id='Blog1' locked='false' title='Blog Posts' type='Blog'/>
    <b:widget id='HTML1' locked='false' title='Test HTML widget' type='HTML' />
  </b:section>
  
</body>
Fig.8 - Manually adding an HTML/Javascript widget.
Then, checking the Layout page, we can see that my HTML/Javascript widget is right in its place.
Fig.9 - HTML/Javascript widget added using the <b:section>tag.
Deleting widgets, however, can't be removed by deleting it from the template code. You need to remove it via the Layout page itself (Edit » Remove). If the Remove option isn't visible on the Edit widget window, check that the widget's locked attribute is set to falseAs mentioned earlier, deleting widgets can also be done now in Blogger's HTML template editor.
Let's now move on to defining the rest of the Sections of our template. Normally, it should have a Header, Navbar, Content, Sidebar and Footer. We already have our Header and Content (main) so let me just add the missing ones.
So after adding the sections along with some widgets, I now have this:

<body>
  
  <b:section id='header' class='header' maxwidgets='1' showaddelement='yes'>
    <b:widget id='Header1' locked='true' title='Testground (Header)' type='Header'/>
  </b:section>
  
  <b:section id='nav' class='nav' maxwidgets='1' showaddelements='yes'>
    <b:widget id='PageList1' locked='false' title='Pages' type='PageList'/>
  </b:section>
  
  <b:section id='main' class='main' maxwidgets='' showaddelements='yes'>
    <b:widget id='Blog1' locked='false' title='Blog Posts' type='Blog'/>
  </b:section>
  
  <b:section id='sidebar' class='sidebar' maxwidgets='' showaddelements='yes'>
    <b:widget id='CustomSearch1' locked='false' title='Search' type='CustomSearch'/>
    <b:widget id='BlogArchive1' locked='false' title='Archive' type='BlogArchive'/>
  </b:section>
  
  <b:section id='footer' class='footer' maxwidgets='' showaddelements='yes'>
    <b:widget id='Attribution1' locked='false' title='' type='Attribution'/>
  </b:section>
  
</body>
Fig.9 - Template code with added sections and widgets.
Fig.10 - Layout page with added sections and widgets.
Fig.11 - Template preview.
Some notes:
  • For the <b:section id='nav' ... > tag, I tried using navbar as the id earlier but it wouldn't show up in the saved template and Layout page. It was because the id navbar is already in use. See the navbar widget on the Layout page? I should have noticed that earlier :|
  • Using an invalid id for the widget (e.g. Pagelist1 instead of PageList1) will generate an error.
  • I can't find a complete list of widget types so that I end up using Add a Gadget to install a widget (e.g. PageList, CutomSearch...) then edit its attributes on the template file. If anyone knows where to find one, I'd appreciate a holler..
  • There can be multiple instances of the same widget type. Just be sure to set a different id for each widget - [widgetType][number] (e.g. HTML1, HTML2)
  • I tried removing the title attribute from the PageList in the code but it still remained in the Layout until I removed it via the Gadget's settings.
  • If you are to use you a fluid layout for your blog instead of Blogger's mobile version, I suggest removing the entire <b:if cond='data:blog.isMobile'> block within the <head> tag and replacing it with <meta content='width=device-width,initial-scale=1.0' name='viewport'/> instead.
I think I finally got the Section and Widget basics covered. All you would need now is to style your template and fix the layout using CSS and I guess you would be good to go. For customizing certain areas on your template, I'll be writing separate blog posts for it. But if you want to jump right into customizing your widgets, here is another must-read.
So if you have any questions, don't hesitate to leave a comment and let's see if we can figure it out. Cheers!