npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

angular-expander

v3.0.11

Published

Generate an SEO-friendly version of an Angular 1 template file

Downloads

29

Readme

Angular Template Expander

Generate an SEO-friendly version of an Angular 1 template file

Install

npm install -g angular-expander

Usage

var expander = require('angular-expander');
// Path of the template to expand
var mainPath = "src/index.html";
// The (possibly partial) scope that will be used for expanding the template
var $scope = {
    title: "My Page",
    body: "This is the body of the page",
    og: {
        title: "My Page",
        image: "https://acme.oom/images/myimage.png"
    }
};
// Optional: if your template contains a ng-view directive, you can specify
// the path of the template used for the route you wish to expand
var viewPath = "src/fragments/myView.html";
expander.expand(mainPath, { scope: $scope, viewTemplate: viewPath }).then(function(html) {
    // This is the text of the expanded template.
    console.log(html);
});

Why do I need this?

I use this module to pre-generate a static HTML file from an Angular template file. The $scope is a partial instance of the angular $scope that would be seen at browser execution time. It will typically contain enough material such as text, titles, og:* values , etc., to make it SEO/social friendly for bots such as Google, Facebook, Slack etc.

Note that it is not necessary to pass a complete $scope to the expander, so only SEO-related content can be expanded and all the true dynamic stuff can be left to the client side of things.

Using that module, I have been able to get rid of PhantomJS to generate SEO-friendly stuff, which was way too heavy for that matter and had too many issues (for instance tags such as AddThis or the FB pixel are half broken when pre-expanded via Phantom).

This module is now part of my build process, to build the static and searchable pages of my site. I also use it in an AWS Lambda function, to dynamically generate some pages with the proper SEO stuff, especially open graph information.

Supported constructions

####<ng-include src="...">

The content of the included file will be expanded inside the node. The ng-include tag will be replaced with a <noop> tag. This way, Angular will not try to interpret the include again at browser execution time. If a ng-show attribute was attached to that directuve, it will be added to the noop element.

####<... ng-include="...">

The content of the included file will be expanded inside the node and the ng-include attribute will be removed. This way, Angular will not try to interpret the include again at browser execution time.

####<... ng-repeat="...">

The repeat expression (ie: b in a in b) is evaluated against the provided $scope. If the expression can be evaluated (no exception thrown, no undefined value), each item is expanded against a scope enhanced with the value of the repeat expression for the ith index, and the value of the index.

####<... ng-bind="...">

If the value of the ng-bind expression can be interpreted against the $scope (no exception thrown, no undefined value), it is inserted inside the element. The ng-bind attribute is then removed.

####<... ng-bind-html="...">

If the value of the ng-bind-html expression can be interpreted against the $scope (no exception thrown, no undefined value), it is inserted inside the element. The ng-bind-html attribute is then removed.

####<ng-view>

If an ng-view directive is found and a viewPath argument was provided, the content of the template file designated by viewPath is expanded and appended inside the ng-view. Note that the ng-view directive is kept so that the routing mechanism is kept on the client. It means that the content inserted is only for SEO purpose.

{{...}}

Any expression inside double curly-braces will be evaluated against the $scope (possibly enriched if a repeat directive is being expanded). If that expression can be interpreted (no exception thrown, no undefined value), it will replace the content if the curly-braces.

Limitations

This module has been tailored for a specific set of HTML files, ie. the ones I wrote for my current web project (https://sende.rs). See examples in the data directory. There are certainly tons of edge cases that are not handled here. Feel free to extend this module to fit your needs.

Release notes

3.0.0

Changed the signature of the expand method so that the template path is a mandatory parameters, and others are gathered in an options object. I also took the opportunity to make the parsing fully async and all promise-based.

2.0.0

I refactored the code in order to make it as asynchronous as possible. Therefore, I changed the signature of the expander, returning a Promise instead of the html result. I still load included template files synchronously because it would change the code too drastically. I'll tackle this down in a next release.

API

expand(mainTemplate, [options]) ⇒ Promise

Expand the given Angular template

Kind: global function
Returns: Promise - HTML text of the expanded template

| Param | Type | Description | | --- | --- | --- | | mainTemplate | String | the path of the Angular template to expand. eg: index.html. Relative to options.srcDir, if provided. | | [options] | Object | | | [options.scope] | Object | The Angular-like $scope object to use when generating the template. This scope does not need to be complete: expressions using non-provided values of the scope will not be evaluated at generation time and will be kept for browser instantiation time | | [options.viewTemplate] | String | Path of the Angular template to instantiate in lieu of the ng-view directive. Relative to options.srcDir, if provided. | | [options.srcDir] | String | Source directory relative to which the paths of the main template, the view template and the included template files will be computed. | | [options.baseUrl] | String | Base url relative to which the paths of the main template, the view template and the included template files will be computed. If provided, then templates are loaded as URLs and the srcDir option is not taken into account. |