This commit is contained in:
Tommy Parnell
2018-12-26 20:39:29 -05:00
commit e71c076567
15 changed files with 6478 additions and 0 deletions

22
src/card.html Normal file
View 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
View 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
View 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
View 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
View 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
View 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"
}
};