What's wrong with this metalsmith-in-place build script? - nunjucks

I am trying to use metalsmith-in-place to do some in-place templating on files in subdirectories of my source dir. It doesn't work. Template tags are not replaced by the frontmatter.
My build script:
var Metalsmith = require('metalsmith'),
inplace = require('metalsmith-in-place'),
nunjucks = require('nunjucks');
Metalsmith(__dirname)
.source('./source')
.use(inplace({
engine: 'nunjucks',
pattern: '*.html',
directory: 'source/deeper'
}))
.destination('./build')
.build(function(err) {
if (err) {
console.log(err);
}
else {
console.info('Built it.');
}
});
My template:
metalsmith_debug$ cat source/deeper/index.html
---
title: My pets
---
{{title}}
My output:
metalsmith_debug$ cat build/deeper/index.html
{{title}}
It works on files in source; but I need it to work on subdirectories.

A couple of changes:
build.js:
var Metalsmith = require('metalsmith');
var inplace = require('metalsmith-in-place');
// var nunjucks = require('nunjucks');
Metalsmith(__dirname)
.source('./source')
.use(inplace({
engine: 'nunjucks',
pattern: '**/*.html' // modified pattern
// directory: 'source/deeper' // Not needed
}))
.destination('./build')
.build(function(err) {
if (err) {
console.log(err);
}
else {
console.info('Built it.');
}
});
You don't need to require nunjucks within the build file, metalsmith-in-place uses consolidate, this will require it where necessary. (Line can be removed)
Modify pattern within inplace to **/*.html. For more information see Globbing patterns.
directory isn't needed within inplace. (Line can be removed)
... and a minor change to source/deeper/index.html:
---
title: My pets
---
{{ title }}
Added space around the placeholder {{ title }} - Nunjucks seems to think this is important.
Should work now for you, let me know if not.

The accepted answer is outdated now, because metalsmith-in-place switched to use the jstransformer framework instead of consolidate.
I've written an article on how to use the in-place plugin to pair Nunjucks with Metalsmith:
Making Metalsmith to work with Nunjucks
Here's the minified working example:
const Metalsmith = require('metalsmith');
const inPlace = require('metalsmith-in-place');
Metalsmith(__dirname)
.source('./src')
.destination('./build')
.use(inPlace({
pattern: '**/*.njk',
engineOptions: {
path: __dirname + '/src'
}
}))
.build(function (error) {
if (error) {
throw error;
}
})
;

Your pattern in the inplace configuration should most likely be **/*.html rather than just *.html

Related

How do I mix promises and pipe in gulp?

In my project I compile multiple bundles from source files in nested directories using rollup.
I had a gulpfile with the following code, which worked fine:
function build_app_js(file, name) {
return gulp.src(file)
.pipe(sourcemaps.init())
.pipe(rollup({format:'iife'}))
.pipe(terser())
.pipe(rename(name + '.js'))
.pipe(rename({suffix: '.min'}))
.pipe(sourcemaps.write())
.pipe(gulp.dest(js_apps_dir))
}
// call the above for multiple sets of file+app_name
But then I changed one of the dependencies in my ES6 code which I accessed by relative path into an npm package, so it is now in node_modules. Rollup needs a plugin to resolve this, so I changed the above to this:
.pipe(rollup({plugins: [resolveNodeModules()], format:'iife'}))
However this simply does not work.
I consulted rollup's docs on gulp, and adapted the example to my case, so it now looks like this:
function build_app_js(file, name) {
return rollup.rollup({
input: file,
plugins: [
resolveNodeModules()
]
}).then(bundle => {
return bundle.write({
file: js_apps_dir + '/' + name + '.js',
format: 'iife',
sourcemap: true
});
});
}
This works, but has no minification step, and I don't know how to add one.
More generally, this is a totally different paradigm from using pipe(), and I do not know how to make both work together.
Do I try to add minification in the Promise syntax, or do I wrap the Promise function in such a way that I can use it with pipe?
Answering own question after 8 days.
Minification can be achieved via rollup plugins, such as rollup-plugin-terser.
You just need to be careful with how you import them:
var rollup = require('rollup');
var resolveNodeModules = require('rollup-plugin-node-resolve');
//var terser = require('rollup-plugin-terser'); // WRONG
var {terser} = require('rollup-plugin-terser'); // CORRECT
function build_app_js(file, name) {
return rollup.rollup({
input: file,
plugins: [
resolveNodeModules(),
terser()
]
}).then(bundle => {
return bundle.write({
file: js_apps_dir + '/' + name + '.js',
format: 'iife',
sourcemap: true
});
});
}
If you import it the wrong way, you will get a terser() is not a function type error, which is because it will have imported terser as a module.
It's a bit annoying that different rollup-plugins can't be imported the same way, but hey.

How to load csv files into a nuxt vue component

I am currently trying to load a csv file into a Nuxt page. The folder structure is below and produces the error "Failed to load resource: the server responded with a status of 404 (Not Found)":
Project
|
+--pages
|
+--lesson
|
+--index.vue
+--file.csv
import * as d3 from 'd3';
export default{
data(){
return{
dataset1:[]
}
mounted(){
d3.csv('file.csv', (myData) => {
console.log('Mydta', myData);
this.dataset1 = myData;
})
}
}
I have added the following to the web pack config in the nuxt-folder:
build: {
/*
** You can extend webpack config here
*/
extend(config, ctx) {
config = {
module: {
rules: [
{
test: /\.csv$/,
loader: 'csv-loader',
options: {
dynamicTyping: true,
header: true,
skipEmptyLines: true
}
}
]
}
}
}
}
Thanks in advance
I recently had the same question and ended up using the #nuxt/content module – worked like a charm, didn't even need to include d3 (which is usually my go-to for parsing CSV files).
I believe the issue is you cannot access the csv file the way you are attempting to, the way to do that would be storing the file in the '/assets' directory which you can then access as shown in the docs I linked ~/assets/file.csv I think this is also a more correct location for storing such files to avoid having lingering files throughout the project
This worked for me:
async mounted() {
const d = await d3.csv("/data.csv");
console.log(d);
}
With data.csv placed in public folder.

Gulp not copying Angular2 to lib-npm

I'm following this tutorial. http://www.c-sharpcorner.com/article/using-mvc-6-and-angularjs-2-with-net-core/
I have gotten to the point of using gulp to copy files to the lib-npm folder. All the expected files copy except angular. I receive no error message, the files just are there.
here is my gulp file
/// <binding />
/*
This file in the main entry point for defining Gulp tasks and using Gulp plugins.
Click here to learn more. http://go.microsoft.com/fwlink/?LinkId=518007
*/
"use strict";
var gulp = require("gulp");
var root_path = {
webroot: "./wwwroot/"
};
//library source
root_path.nmSrc = "./node_modules/";
//library destination
root_path.package_lib = root_path.webroot + "lib-npm/";
gulp.task("copy-systemjs", function () {
return gulp.src(root_path.nmSrc + '/systemjs/dist/**/*.*', {
base: root_path.nmSrc + '/systemjs/dist/'
}).pipe(gulp.dest(root_path.package_lib + '/systemjs/'));
});
gulp.task("copy-angular2", function () {
return gulp.src(root_path.nmSrc + '/angular2/bundles/**/*.js', {
base: root_path.nmSrc + '/angular2/bundles/'
}).pipe(gulp.dest(root_path.package_lib + '/angular2/'));
});
gulp.task("copy-es6-shim", function () {
return gulp.src(root_path.nmSrc + '/es6-shim/es6-sh*', {
base: root_path.nmSrc + '/es6-shim/'
}).pipe(gulp.dest(root_path.package_lib + '/es6-shim/'));
});
gulp.task("copy-rxjs", function () {
return gulp.src(root_path.nmSrc + '/rxjs/bundles/*.*', {
base: root_path.nmSrc + '/rxjs/bundles/'
}).pipe(gulp.dest(root_path.package_lib + '/rxjs/'));
});
gulp.task("copy-all", ["copy-rxjs", 'copy-angular2', 'copy-systemjs', 'copy-es6-shim']);
I have also noticed that my .\node_modules\Angular2 folder in my project doesn't have an .js files in it. Is this normal?
Angular2 version is 1.0.2
I receive the following errors on build because the files are missing
Cannot find name 'Component'.
Build:Cannot find module 'angular2/core'.
Build:Cannot find module 'angular2/platform/browser'.
Build:Cannot find name 'Component'.
Cannot find module 'angular2/core'.
Cannot find module 'angular2/platform/browser'
I would suggest you not to copy node_modules every time you build an app. You can easily amend the UseStaticFiles middleware inside the Startup.cs class as described here. By doing this your node_modules stay where they are and you don't need to repeatedly copy them.
Btw. Recently (before switching to UseStatisFiles modification) I have done the same in the Gulp and the following has worked well:
gulp.task('build-angular-js', function () {
return gulp.src(paths.angularJs)
.pipe(cache('linting'))
.pipe(gulp.dest(paths.jsNgDest));
});
..where paths equals to:
var paths = {
webroot: "./wwwroot/",
angularJs: [
"./node_modules/core-js/client/shim.min.js",
"./node_modules/zone.js/dist/zone.js",
"./node_modules/reflect-metadata/Reflect.js",
"./node_modules/systemjs/dist/system.src.js",
"./App/External/systemjs.config.js",
"./node_modules/#angular/**/*.js",
"./node_modules/rxjs/**/*.js"
],
appJs: [
"./App/App/**/*.js"
]
};
paths.jsDest = paths.webroot + "app";
paths.jsNgDest = paths.webroot + "app";
The complete template and all sources including gulpfile.js can be found here on GitHub. Note that cache is a gulp plugin to avoid copying not modified files. As said above though - better to avoid copying node_modules.

RequireJS automatic single file cache bust

I've seen the many solutions for using urlArgs to force the file to change but is there an efficient way to have it automatically change only single files if the file has been updated?
Is it possible to bust the cache of only files that have been modified?
The biggest example being this topic.
function bust(path) {
return path + '?bust=' + (new Date()).getTime();
}
require.config({
baseUrl: '/base/path',
paths: {
'fileAlias': bust('fileLikelyToChange'),
'anotherFileAlias': bust('anotherFileLikelyToChange'),
'jQuery': 'jQuery'
},
});
The problem is this solution busts the cache every time instead of only when the file has been modified.
My solution may be a bit heavy handed and is a hybrid of this and other solutions posted but it works for me.
Part 1:
In the html, append all dependent scripts with cache busting query string-->
<script type="text/javascript">
var require = {
urlArgs : "bust="+ Math.random()
}
</script>
<script data-main="js/app" src="js/require.js"></script>
Part 2:
Then in app.js add a custom bust method to apply to only the files that may have changed:
function bust(path) {
return path + '.js?bust=' + Math.random();
}
Part 3:
update the urlArs with an empty string: urlArgs: "" to overide cache busting query string ubiquitously applied in Part 1 and add the cache busting method only to files of your choice:
requirejs.config({
urlArgs: "",
paths: {
'utilities': 'utilities',
'controller': bust('controller'),
'main': 'main'
}
});

Sass variable interpolation with backslash in output

I'm creating some icon font rules for using in my site. Using Sass I wanted to list all the icons in a list variable and use #each to loop through them all.
Code looks like this:
$icons:
wifi 600,
wifi-hotspot 601,
weather 602;
#each $icon in $icons {
.icon-#{nth($icon, 1)},
%icon-#{nth($icon, 1)} {
content: "\#{nth($icon, 2)}";
}
}
The problem is the backslash on the content: line. I need it for the character encoding, but it escapes the variable interpolation, outputting CSS that looks like this:
.icon-wifi {
content: "\#{nth($icon, 2)}";
}
Adding one more backslash like this: content: "\\#{nth($icon, 2)}"; outputs this CSS:
.icon-wifi {
content: "\\600";
}
Is there a way to get the Sass to output CSS with only a single backslash while keeping the variable interpolation?
I got this to work by messing with the interpolation
sassmesiter demo
// ----
// Sass (v3.4.21)
// Compass (v1.0.3)
// ----
$icons:
wifi 600,
wifi-hotspot 601,
weather 602;
#each $icon in $icons {
.icon-#{nth($icon, 1)},
%icon-#{nth($icon, 1)} {
content: #{'"\\' + nth($icon, 2) + '"'}; // <------ See this line
}
}
compiles to
.icon-wifi {
content: "\600";
}
.icon-wifi-hotspot {
content: "\601";
}
.icon-weather {
content: "\602";
}
If you include the backslash in the actual variable, then when the sass generates the css, it will actually generate the calculated unicode character instead of outputting the unicode in the css output. This still usually works but it's hard to debug if something is going wrong and it is a bit more prone to cause issues in the browser in rendering the icon.
To output the actual unicode in the generated CSS, you can do this:
#function icon($character){
#return unquote('\"') + unquote(str-insert($character,'\\', 1)) + unquote('\"');
}
$icon-thing: "e60f";
.icon-thing:before {
content: icon($icon-thing); //outputs content: "\e60f";
}
You can add the backslash to the parameter in the $icons variable. That is,
$icons: wifi "\600", wifi-hotspot "\601", weather "\602";
#each $icon in $icons {
.icon-#{nth($icon, 1)}, %icon-#{nth($icon, 1)} {
content: "#{nth($icon, 2)}";
}
}
Generated CSS:
.icon-wifi {
content: "\600";
}
.icon-wifi-hotspot {
content: "\601";
}
.icon-weather {
content: "\602";
}
Use unquote and double slash
$var:123 → content:"\e123"
content:#{unquote('\"')+("\\")+("e")+$var+unquote('\"')};
If you are using Gulp to compile your Sass files, installing this Gulp plugin is probably the easiest way to get around the issue:
https://www.npmjs.com/package/gulp-sass-unicode
var sass = require('gulp-sass');
var sassUnicode = require('gulp-sass-unicode');
gulp.task('sass', function(){
gulp.src('style.scss')
.pipe(sass())
.pipe(sassUnicode()) // <-- This is the bit that does the magic
.pipe(gulp.dest( "css/" ));
});
There is no need to make any code alterations in your Sass files. Write out your Sass code how you want and the unicode characters are decoded back into regular escaped strings in the output CSS automatically.
Input SCSS
$testContent: "\f26e";
#test {
content: $testContent;
}
Output CSS
#test {
content: "\f26e";
}
Unfortunately, these solutions were not entirely working for me but I was finally able to get it working with SASS maps
//node-sass 4.11.0
//libsass 3.5.4
$hexes: (
checkmark: \2714
);
#function out-content($var) {
#return unquote("\"#{ $var }\"");
}
#each $mod, $code in $hexes {
.#{$mod}-after {
&:after {
content: out-content($code);
}
}
}
//output
//.checkmark-after:after {
//content: "\2714";
//}

Resources