Replacing `gulp-inject` - node.js

We have an old JS project which uses Gulp as its build tool. As our project is not too complex, we intend to replace Gulp plain NPM scripts and call the underlying tools (browserify, sass, uglifyjs, ...) directly as suggested in this blog .
We are 95% there. The only thing for which I have not yet found a solution is how to replace gulp-inject for compiling our frontend.html. The main source file main.html is a HTML skeleton with various HTML comments of the sort <!-- inject: path/to/file/whose/content/belongs/here.html -->.
Basically, I am looking for a NPM module which provides a simple CLI tool which takes main.html as an input, parses it for special comments and replaces those comments by the content of the designated files and writes the result into frontend.html.
Any suggestions?
I have already tried to search https://www.npmjs.com/ for "bundle html", "inject html", etc., but all I get are modules which dynamically inject HTML into a HTML DOM at runtime in the browser. That is not what I am looking for.

Related

Interactive dependency map on rustdoc?

When I make projects with C++, I often use doxygen to generate the documentations, doxygen has a neat feature that generates interactive dependency graphs (like call dependencies, inheritance dependencies etc...)
This tool, embedded in the html docs, allows you to zoom in and out and drag things around.
I am trying to generate a dependency graph for the current crates of a project, this looks like this:
The image is generated using depgraph.
I have 2 issues.
Issue 1) is, as the dependency graph grows, the image becomes harder and harder to read:
This could be solved by having a zoom and pan feature like doxygen, but I have got no idea how to generate and inject that kind of html (and maybe js?) into the autodocs from rustod.
Issue 2) is that the svg file is unaffected by the css and having the white and black color scheme looks kinda ugly, this is less important but it would be nice if the svg could mirror the css theme.
Rustdoc allows for the injection of custom CSS and HTML/JS before and after the generated content. You can do this via various command-line arguments.
see: https://doc.rust-lang.org/rustdoc/command-line-arguments.html
To add custom HTML to the header you can use the --html-in-header argument.
$ rustdoc src/lib.rs --html-in-header header.html
Where header.html is your custom header HTML
This flag takes a list of files, and inserts them inside the <body>
tag but before the other content rustdoc would normally produce in the
rendered documentation.
see: https://doc.rust-lang.org/rustdoc/command-line-arguments.html#--html-before-content-include-more-html-before-the-content
$ rustdoc src/lib.rs --html-after-content extra.html
Where extra.html is your custom HTML to include after the content.
This flag takes a list of files, and inserts them before the </body>
tag but after the other content rustdoc would normally produce in the
rendered documentation.
see: https://doc.rust-lang.org/rustdoc/command-line-arguments.html#--html-after-content-include-more-html-after-the-content
Finally for custom CSS
$ rustdoc src/lib.rs --extend-css extra.css
Where extra.css is your custom css definitions.
With this flag, the contents of the files you pass are included at the
bottom of Rustdoc's theme.css file.
While this flag is stable, the contents of theme.css are not, so be
careful! Updates may break your theme extensions.
see: https://doc.rust-lang.org/rustdoc/command-line-arguments.html#-e--extend-css-extend-rustdocs-css
Unfortunately I don't have any example rust doc html - so it is hard to say exactly what should be included in your injected HTML/CSS/JS to achieve your desired results. My suggestion is that you try and if you get stuck to ask a more specific question and provide an example of the code.

Parcel - add svg sprite

Colleagues, I'm trying Parcel as an alternative to webpack project builder and I like it, but there are two BUTs that I still can't beat (here are links to starting builds - build on Parcel
and build on webpack):
1) In the assembly under the webpack, I used svg-sprite-loader to create svg sprites, which adds immediately after opening body svg with symbols like this:
there is no such plugin in the parcel assembly, I tried to install parcel-plugin-svg-sprite, but it does not compile a separate sprite (at least I did not find such a solution in the documentation).
As a result, for now, I am inserting svg in the way described in the parcel documentation (I use a pug in the project):
svg
use (href = "../../ icons / facebook.svg")
but in this case, I only get an empty space ((
2) When building a project, i get one folder with a lot of files, which is not very convenient, in the documentation I found that i can use the -d flag to set a name for the folder in which building the project, but did not find how to separate html/css/js/imgs by folders.
Thanks in advance for any help.
I don't think that there is yet a plugin for parcel2 that will allow you to easily create svg sprites. The parcel-plugin-svg-sprite package you mentioned is for parcel 1, so it is not expected to work. (In general, you can expect parcel 2 plugins to conform to this naming scheme - packages that start with parcel-plugin are probably for parcel 1).
As a workaround, the easiest way to use svgs in a pug template built with parcel would be to use an <img> or an <object> tag with a src property, e.g:
img(src="../../icons/facebook.svg")
or
object(data="../../icons/facebook.svg")
Doing it this way, where the svg file is "external" has a few limitations(discussed in the docs), notably there will be an extra round trip to download each svg (this would be good for caching, but bad if there were hundreds of svgs on your site). Also, you can't style the svg with css from the surrounding document.
You can avoid the first limitation (extra server round trip) by using css background-image/background property with a data URL (see docs)
.pug file
.icon-test
.(s)css file
.icon-test {
background-image: url('data-url:../../icons/facebook.svg'); ​
​}
​(In react-based projects there is a way to avoid both these limitations and get parcel to inject the SVG as inline JSX through the #parcel/transformer-react-svg plugin (see docs), but I'm not aware of a similar plugin (yet) for pug templates.)
You can control the structure of the output files in parcel's dist folder by writing a custom namer plugin. I explained how to do this in this answer.
The plugin developer for the first parcel made the build for the parcel v2, and I say thank you! Here is the plugin, tested it with html and pug, everything works! https://github.com/Epimodev/parcel-plugin-svg-sprite

Can Asciidoctor render a separate HTML page per chapter?

If I have something like the following:
The Manual
====================
Gregg Bolinger
v1.0, 2014-15
:doctype: book
:icons: font
:imagesdir: images
Preamble paragraph
include::chapter1.ad[]
include::chapter2.ad[]
I'd like so that each chapter renders in its own HTML file and is linked to from the TOC rather than everything being in a single book.html, for example. It seems to generate separate files already, but that's only because they are in the source directory. It is still combining everything into a single HTML page. I'm using the Gradle Asciidoctor plugin, if that helps to know.
Unless there's something in the gradle plugin that does chunked html, asciidoctor does not handle chunked output at the moment. It's on the list of things to do, but it hasn't been done. If you look at the issue, however, someone has create a custom script/converter to do it though, perhaps that will work for your case as well.
Using the asciidoctor-multipage extension, each chapter can be rendered in its own HTML file. The links in the TOC points to the respective HTML chapters rather than everything being in a single book.html. At the end of every HTML page, the extension also adds links to the next or previous page, as seen on this website.
Assuming you have already installed the asciidoctor, just do $ gem install asciidoctor-multipage in your command line to install the multipage extension.
After making your file-name.adoc with various chapters, $ cd to that folder and then do $ asciidoctor -r asciidoctor-multipage -b multipage_html5 -D test/out --backend multipage_html5 -a data-uri file-name.adoc. This command will embed any images in the file-name.adoc to the new .html files which will be saved in newly created test/out folder. I only tested this using Ubuntu 20.04.
As Sam Macharia answered, asciidoctor-multipage can achieve your goal.
Also, most Docbook toolchains let you control how content is "chunked" into HTML pages, including at the book, chapter, and section levels.
Antora is the "official" way to achieve your goal.

Liferay 6.1.20 : Minimize and bundle theme Javascript

Is there a way to apply Liferay's built-in javascript minimizing and bundling capability to the javascript I've included in my theme? I have javascript.fast.load=true in portal-ext.properties and Liferay's javascript is getting bundled & minified in everything.jsp as expected. Also, all portlet javascript that is included via a portlet's liferay-portal.xml file is getting minified as expected. However, I've got many javascript files that are included in my theme because they are utilized on every page and I would like them to get minimized and bundled into everything.jsp along with all the Liferay portal javascript. I've tried the approach suggested by this question, but I think this will only work with a hook because the MinifyFilter will look for files to minify & bundle within the context of the portal web app, i.e. <TOMCAT>/webapps/ROOT. Is there a way I can specify a path to files in a different web app (the theme in this case) as the javascript.bundle.dir parameter? In other words, something like javascript.bundle.dir[javascript.jquery.files]=/<theme-path>/js. I've tried many variations and combinations of javascript.bundle.ids, javascript.bundle.dependencies, etc. to no avail. I know I can get around the problem by putting the javascript in a hook or putting it in portlet and embedding it in the theme but I'd really like to just keep the javascript in the theme. Is there a reasonable way to accomplish this?
There doesn't seem to be a good way to include javascript files from the theme with the minified and bundled Liferay javascript. While you can define a javascript bundle in portal-ext.properties that includes your files, you can't order the dependencies the way you need to in order to get everything to work using only configuration. You can configure the "everything" bundle to depend on your custom bundle but that's not very useful. It would be far more useful if you could configure Liferay to use your custom bundle as the new "everything" bundle and tell Liferay that your bundle depends on Liferay's "everything" bundle. However, the actual bundle ids that are included are hard-coded in Liferay's top_js.jspf file. So the only way to get everything to work would be to override Liferay's definition of javascript.everything.files to include both Liferay's files and your custom javascript. This doesn't seem like a very good solution since it tampers with Liferay's list of included javascript which would certainly be a pain when you need to upgrade Liferay. As Olaf suggested, you can minify and bundle the js yourself and just include it in the portal_normal template. That is a very reasonable solution and what I would normally recommend. Unfortunately I was in a situation where my customer was requesting that all the files be bundled in one file and we are not allowed to modify the build process.
Hook Workaround
There is a workaround using a hook that I don't necessarily recommend but it does accomplish the goal of getting all javascript minimized and bundled along with Liferay's javascript. The basic process is to move the javascript from the theme into a hook, configure a new bundle in portal-ext.properties that includes all of your files, then create a jsp hook for top_js.jspf that includes your new bundle instead of the hard-coded javascript.everything.files or javascript.barebones.files bundles. The steps are:
Move your javascript files into a hook project and place them under html/js. This will cause
the files to be copied to the javascript directory under the portal
web app, i.e. <TOMCAT_HOME>/ROOT/html/js. This is where the Liferay
MinifyFilter looks for javascript files to minify & bundle.
Define a javascript bundle in portal-ext.properties that references
all of your javascript files that need to be included in the bundle
created by the MinifyFilter. Your portal-ext.properties file should
look something like this:
minifier.enabled=true
javascript.fast.load=true
javascript.my.js.files =\
jquery.1.11.1,\
my-js-lib.js,\
my-other-js-lib.js
javascript.bundle.ids=\
javascript.barebone.files,\
javascript.everything.files,\
javascript.my.js.files
javascript.bundle.dir[javascript.my.js.files]=/html/js
# our bundle depends on all the files in the "everything" bundle
javascript.bundle.dependencies[javascript.my.js.files]=javascript.everything.files
Create a JSP hook for top_js.jspf. This file is under
<TOMCAT_HOME>/ROOT/html/common/themes. It is the file that includes
either the barebones.jsp or everything.jsp based on whether the user
is authenticated (if the user is authenticated they get
everything.jsp otherwise barebones.jsp is included). Replace the
references to the javascript.everything.files and/or
javascript.barebones.files bundles with a reference to your new
bundle based on your requirements. For example, if you only want to
include your javascript when the user is authenticated you just have
to replace references to javascript.everything.files.
Specifically, you make the following changes:
This line:
<script src="<%= HtmlUtil.escape(PortalUtil.getStaticResourceURL(request, themeDisplay.getCDNDynamicResourcesHost() + themeDisplay.getPathJavaScript() + "/everything.jsp", "minifierBundleId=javascript.everything.files", javaScriptLastModified)) %>" type="text/javascript"></script>
is changed to this:
<script src="<%= HtmlUtil.escape(PortalUtil.getStaticResourceURL(request, themeDisplay.getCDNDynamicResourcesHost() + themeDisplay.getPathJavaScript() + "/everything.jsp", "minifierBundleId=javascript.my.js.files", javaScriptLastModified)) %>" type="text/javascript"></script>
and this line:
javaScriptFiles = JavaScriptBundleUtil.getFileNames(PropsKeys.JAVASCRIPT_EVERYTHING_FILES);
is changed to this:
javaScriptFiles = JavaScriptBundleUtil.getFileNames("javascript.my.js.files");
* Non-Global Hook Caveat *
If you are putting the javascript and top_js.jspf hooks in a project with other hooks and the project is configured to use non-global jsp hooks, i.e. <custom-jsp-global>false</custom-jsp-global> the solution becomes more complicated. This is because setting <custom-jsp-global>true</custom-jsp-global> makes Liferay rename your hook jsp files rather than renaming the portal's jsp files. For example, if custom-jsp-global is set to true, which is the default setting, then when I make a hook for a page called top_js.jspf, the portal will rename the original top_js.jspf file to top_js.portal.jsp and my hook file will be used instead of the original. However, when custom-jsp-global is set to false then the original file stays intact and the jsp hook file is renamed to something that includes the name of the hook like top_js.my-hook.jspf. This is a problem when you're creating a hook for included files such as top_js.jspf because the file that includes top_js.jspf will still reference the old file, not the hook which is named top_js.my-hook.jspf. This means you have to also create a hook for the file that includes your hook. Likewise, if that file is included by another file you have to make hook for that file and so on until you reach the top level page. So, in the example of trying to create a hook for top_js.jspf we have to also do the following:
Create a hook for top_head.jspf and replace the reference to top_js.jspf with a reference to our hook, top_js.my-hook.jspf.
So this line
<%# include file="/html/common/themes/top_js.jspf" %>
becomes this
<%# include file="/html/common/themes/top_js.my-hook.jspf" %>
The top_head.jspf file is actually included by the theme in
portal_normal.vm using a Velocity variable that is initialized in
init.vm on the following line:
You need to assign $top_head_include to the top_head.my-hook.jspf hook in the theme's init_custom.vm, like this:
#set ($top_head_include = "$dir_include/common/themes/top_head.my-hook.jsp")
Your Theme has access to all of the HTML the portal generates. While you might need one extra file to be loaded (css gets minified for the whole theme anyway), you can easily add all of the (already) minified js files to your theme and include them in your templates/portal-normal.ftl implementation.
It would be as easy as having this section in portal-normal.ftl:
<head>
<title>${the_title} - ${company_name}</title>
<meta content="initial-scale=1.0, width=device-width" name="viewport" />
${theme.include(top_head_include)}
<script src="${javascript_folder}/my-minified-javascript.js"/>
</head>
Note: All but the <script> line is already in the default ftl file. This way you'll end up with two js files being loaded (the barebones or everything, plus your own), but that's not too bad. You can also add the minification to your theme's build process, so that you don't have to maintain the minified code manually.
Another alternative, which I haven't tried, is examining the use of Liferay's javascript minifier (e.g. in webapps/ROOT/html/common/themes/tom_js.jsp) to see how to utilize it to dynamically minify your files.
For completeness reason (maybe it helps someone else) I'm leaving my first answer here, which you couldn't use as you say in the first comment:
There's a section in portal.properties, to be overloaded in portal-ext.properties with this heading:
##
## JavaScript
##
#
# Set a list of JavaScript files that will be loaded automatically in
# /html/common/themes/top_js.jsp.
#
# There are two lists of files specified in the properties
# "javascript.barebone.files" and "javascript.everything.files".
#
# As the name suggests, the barebone list is the minimum list of JavaScript
# files required for most cases. The everything list includes everything
# else not listed in the barebone list.
#
# The two lists of files exist for performance reasons because
# unauthenticated users usually do not utilize all the JavaScript that is
# available. See the property "javascript.barebone.enabled" for more
# information on the logic of when the barebone list is used and when the
# everything list is used and how to customize that logic.
#
# The list of files are also merged and packed for further performance
# improvements. See the property "javascript.fast.load" for more details.
#
e.g. configure javascript.everything.files (the default is below that comment, for brevity I'm not copying that here)

grunt to build dynamic jade pages

I want to use grunt to build my node.js project (based on Kraken.js, but I've replaced dust with jade). I've installed grunt-contrib-jade. For jade files that contain no server side state this all works nicely and I get the HTML files output. However, where I have .jade files that contain logic and render server-side state it all goes wrong. For example, if I have h1 #{x.y} in my file the grunt output is cannot read property y of undefined. This makes complete sense as x is only defined at runtime.
So I'm now wondering do I just ignore my jade files in the grunt build and let the server process them all at runtime, or is there some alternative that I'm missing to 'pre-process' my .jade files to speed up execution?
Quoting an answer of mine (Would it benefit to pre-compile jade templates):
When Jade compiles the template, the template is cached. In production environment if you warm up the cache, then there is no need to pre-compile template. Even if you don't, the template will be cached after its first compilation.
In short: Compiling Jade template is useless. You'd better remove grunt-contrib-jade.

Resources