init
This commit is contained in:
22
src/card.html
Normal file
22
src/card.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{{ cardTitle }} npm card</title>
|
||||
<style>
|
||||
.card {
|
||||
border-radius: 15px;
|
||||
border: 2px solid #73ad21;
|
||||
padding: 5px;
|
||||
margin: 25px;
|
||||
background: black;
|
||||
padding-left: 25px;
|
||||
padding-right: 25px;
|
||||
width: fit-content;
|
||||
background-image: url("http://cdn.backgroundhost.com/backgrounds/subtlepatterns/burried.png");
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="card">{{ card }}</div>
|
||||
</body>
|
||||
</html>
|
||||
13
src/card.js
Normal file
13
src/card.js
Normal file
@@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
* Note that it's important that sources are all under a single level of directory
|
||||
* like src and webpack bundle output is dist. That way, all the relative
|
||||
* require paths such as `../` continue to work as is.
|
||||
*/
|
||||
|
||||
const xrequire = eval(`require`);
|
||||
const makeCard = require("./make-card");
|
||||
const myPkg = xrequire("../package.json");
|
||||
|
||||
console.log(makeCard(myPkg).boxenText);
|
||||
28
src/color-marks.js
Normal file
28
src/color-marks.js
Normal file
@@ -0,0 +1,28 @@
|
||||
"use strict";
|
||||
|
||||
const get = require("lodash.get");
|
||||
const chalk = require("chalk");
|
||||
|
||||
//
|
||||
// convert color markers in a string to terminal color codes with chalk
|
||||
// color marker format is "<red>red text</red><blue.bold>blue bold text</blue.bold>"
|
||||
// the end marker can simply be "</>" also
|
||||
// the marker is converted to chalk methods directly, for example:
|
||||
// - chalk.red is called for "<red>"
|
||||
// - chalk.blue.bold is called for "<blue.bold>"
|
||||
//
|
||||
function format(s) {
|
||||
return s.replace(/<([a-z.]+)>([^<]+)($|<\/[^>]*>)/g, (a, b, c) => {
|
||||
return get(chalk, b)(c);
|
||||
});
|
||||
}
|
||||
|
||||
// remove the color marker like <red>text</> from strings
|
||||
function remove(s) {
|
||||
return s.replace(/<[^>]*>/g, "").trim();
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
format,
|
||||
remove
|
||||
};
|
||||
56
src/htmlify.js
Normal file
56
src/htmlify.js
Normal file
@@ -0,0 +1,56 @@
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
* Note that it's important that sources are all under a single level of directory
|
||||
* like src and webpack bundle output is dist. That way, all the relative
|
||||
* require paths such as `../` continue to work as is.
|
||||
*/
|
||||
|
||||
process.env.FORCE_COLOR = 1;
|
||||
|
||||
const Path = require("path");
|
||||
const xrequire = eval(`require`);
|
||||
const makeCard = require("./make-card");
|
||||
const AnsiToHtml = require("ansi-to-html");
|
||||
const myPkg = xrequire("../package.json");
|
||||
const Fs = require("fs");
|
||||
const colorMarks = require("./color-marks");
|
||||
const get = require("lodash.get");
|
||||
|
||||
function makeHtmlCard(pkg) {
|
||||
const myCard = pkg.myCard;
|
||||
const info = Object.assign({ _packageName: pkg.name }, myCard.info);
|
||||
// replace {{token}} in string with info[token]
|
||||
const processString = str => str.replace(/{{([^}]+)}}/g, (a, b) => get(info, b, ""));
|
||||
|
||||
pkg.myCard.data = pkg.myCard.data.map(l => {
|
||||
if (typeof l !== "string") {
|
||||
if (l.hasOwnProperty("link")) {
|
||||
l._link = processString(l.link);
|
||||
} else {
|
||||
const link = processString(colorMarks.remove(l.text));
|
||||
if (link.indexOf("http") >= 0) {
|
||||
l._link = link;
|
||||
}
|
||||
}
|
||||
}
|
||||
return l;
|
||||
});
|
||||
|
||||
const card = makeCard(pkg);
|
||||
const ansi = new AnsiToHtml();
|
||||
const html = card.cardLines.map(l => ansi.toHtml(l)).join("\n");
|
||||
const template = Fs.readFileSync(Path.join(__dirname, "card.html")).toString();
|
||||
|
||||
Fs.writeFileSync(
|
||||
"index.html",
|
||||
template.replace("{{ cardTitle }}", `${info.name} (@${info.handle})`).replace(
|
||||
"{{ card }}",
|
||||
`<pre>
|
||||
${html}
|
||||
</pre>`
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
makeHtmlCard(myPkg);
|
||||
102
src/make-card.js
Normal file
102
src/make-card.js
Normal file
@@ -0,0 +1,102 @@
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
* Note that it's important that sources are all under a single level of directory
|
||||
* like src and webpack bundle output is dist. That way, all the relative
|
||||
* require paths such as `../` continue to work as is.
|
||||
*/
|
||||
|
||||
const boxen = require("boxen");
|
||||
const chalk = require("chalk");
|
||||
const get = require("lodash.get");
|
||||
const cardStyle = require("./style.js");
|
||||
const colorMarks = require("./color-marks");
|
||||
|
||||
module.exports = makeCard;
|
||||
|
||||
function makeCard(pkg) {
|
||||
// get myCard info from package
|
||||
const myCard = pkg.myCard;
|
||||
const info = Object.assign({ _packageName: pkg.name }, myCard.info);
|
||||
const data = myCard.data;
|
||||
|
||||
// replace {{token}} in string with info[token]
|
||||
const processString = str => str.replace(/{{([^}]+)}}/g, (a, b) => get(info, b, ""));
|
||||
|
||||
// find the longest label string and its corresponding URL
|
||||
// for later padding of spaces to do alignment
|
||||
const maxLens = data.reduce(
|
||||
(a, x) => {
|
||||
// if line is a literal string or has no label, skip
|
||||
if (typeof x === "string" || !x.hasOwnProperty("label")) return a;
|
||||
a.label = Math.max(a.label, colorMarks.remove(x.label).length);
|
||||
a.text = Math.max(a.text, colorMarks.remove(x.text).length);
|
||||
return a;
|
||||
},
|
||||
{ label: 0, text: 0 }
|
||||
);
|
||||
|
||||
const defaultStyle = Object.assign({ label: x => x, text: x => x }, cardStyle._default);
|
||||
|
||||
const cardLines = data.reduce((a, x) => {
|
||||
let line;
|
||||
|
||||
// line has when field and it's empty, so skip it
|
||||
if (x.when && processString(x.when).trim() === "") {
|
||||
return a;
|
||||
}
|
||||
|
||||
// line has only text and no label, so take it as literal string
|
||||
if (!x.hasOwnProperty("label") && x.hasOwnProperty("text")) {
|
||||
x = x.text || "";
|
||||
}
|
||||
|
||||
if (typeof x === "string") {
|
||||
// process a string literal line directly
|
||||
line = defaultStyle.text(colorMarks.format(processString(x)));
|
||||
} else {
|
||||
// replace any info token in label and text
|
||||
const xLabel = processString(x.label);
|
||||
const xText = processString(x.text);
|
||||
// get label literal without any color markers
|
||||
const label = colorMarks.remove(xLabel);
|
||||
// get style for the label
|
||||
const style = Object.assign(
|
||||
{},
|
||||
defaultStyle,
|
||||
cardStyle[label] || cardStyle[label.toLowerCase()]
|
||||
);
|
||||
// add leading spaces for alignment
|
||||
const pad = x.hasOwnProperty("pad")
|
||||
? x.pad
|
||||
: new Array(maxLens.label - label.length + 1).join(" ");
|
||||
line =
|
||||
pad +
|
||||
style.label(colorMarks.format(xLabel)) +
|
||||
style.text(colorMarks.format(xText), x._link);
|
||||
}
|
||||
|
||||
a.push(line);
|
||||
|
||||
return a;
|
||||
}, []);
|
||||
|
||||
// join all the text lines into a single string with newline
|
||||
const cardText = cardLines.join("\n");
|
||||
|
||||
// get options for boxen
|
||||
const boxenStyle = cardStyle._boxen || {
|
||||
padding: 1,
|
||||
margin: 1,
|
||||
borderColor: "green",
|
||||
borderStyle: "round"
|
||||
};
|
||||
|
||||
const boxenText = boxen(cardText, boxenStyle);
|
||||
|
||||
return {
|
||||
cardLines,
|
||||
cardText,
|
||||
boxenText
|
||||
};
|
||||
}
|
||||
30
src/style.js
Normal file
30
src/style.js
Normal file
@@ -0,0 +1,30 @@
|
||||
"use strict";
|
||||
|
||||
const chalk = require("chalk");
|
||||
|
||||
const linkify = (text, link) => {
|
||||
return link ? `<a href="${link}">${text}</a>` : text;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
// style override for Work label
|
||||
work: {
|
||||
text: x => chalk.white(x)
|
||||
},
|
||||
// style override for Card label
|
||||
card: {
|
||||
text: x => chalk.white(x)
|
||||
},
|
||||
// any label without a style defined will use this
|
||||
_default: {
|
||||
label: x => (x && chalk.white.bold(x + ": ")) || " ",
|
||||
text: (x, link) => linkify(chalk.white(x), link)
|
||||
},
|
||||
// options for boxen
|
||||
_boxen: {
|
||||
padding: 1,
|
||||
margin: 1,
|
||||
borderColor: "green",
|
||||
borderStyle: "round"
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user