init
This commit is contained in:
3
.babelrc.js
Normal file
3
.babelrc.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module.exports = {
|
||||||
|
presets: [["@babel/env", { targets: { node: "6" } }]]
|
||||||
|
};
|
||||||
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
node_modules
|
||||||
|
dist
|
||||||
22
README.md
Normal file
22
README.md
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
[npm] card for Tommy Parnell
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
Via npx:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx terribledev
|
||||||
|
```
|
||||||
|
|
||||||
|
# Other
|
||||||
|
|
||||||
|
Idea and trend started by [Tierney (@bitandbang)]
|
||||||
|
|
||||||
|
To create your own, use [create-my-card].
|
||||||
|
|
||||||
|
ie: `npm init my-card`
|
||||||
|
|
||||||
|
[npm]: https://www.npmjs.com/
|
||||||
|
[tierney (@bitandbang)]: https://www.npmjs.com/package/bitandbang
|
||||||
|
[create-my-card]: https://www.npmjs.com/package/create-my-card
|
||||||
|
|
||||||
9
bin/index.js
Normal file
9
bin/index.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
const verMajor = parseInt(process.versions.node.split(".")[0], 10);
|
||||||
|
|
||||||
|
if (verMajor <= 6) {
|
||||||
|
require("../dist/node6-card");
|
||||||
|
} else {
|
||||||
|
require("../dist/card");
|
||||||
|
}
|
||||||
34
index.html
Normal file
34
index.html
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Tommy Parnell (@terribledev) 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"><pre>
|
||||||
|
<span style="color:#AAA"> <span style="color:#AAA">Tommy Parnell<span style="color:#AAA"><span style="color:#0A0"> / <span style="color:#AAA"><span style="color:#0AA">terribledev<span style="color:#AAA"><span style="color:#FFF"></span></span></span></span></span></span></span></span>
|
||||||
|
|
||||||
|
<span style="color:#AAA"><b><span style="color:#55F">Work<span style="color:#AAA">: <span style="color:#FFF"><span style="color:#AAA">Sr. Software Engineer<span style="color:#FFF"></span></span></span></span></span></b></span>
|
||||||
|
|
||||||
|
<span style="color:#AAA"><b>Twitter: </b><span style="color:#FFF"><a href="https://twitter.com/terribledev"><span style="color:#AAA">https://twitter.com/<span style="color:#0AA">terribledev<span style="color:#AAA"><span style="color:#FFF"></a></span></span></span></span></span></span>
|
||||||
|
<span style="color:#AAA"><b>npm: </b><span style="color:#FFF"><a href="https://www.npmjs.com/~terribledev"><span style="color:#AAA">https://www.npmjs.com/<span style="color:#A00">~terribledev<span style="color:#AAA"><span style="color:#FFF"></a></span></span></span></span></span></span>
|
||||||
|
<span style="color:#AAA"><b>GitHub: </b><span style="color:#FFF"><a href="https://github.com/terribledev"><span style="color:#AAA">https://github.com/<span style="color:#0A0">terribledev<span style="color:#AAA"><span style="color:#FFF"></a></span></span></span></span></span></span>
|
||||||
|
<span style="color:#AAA"><b>LinkedIn: </b><span style="color:#FFF"><a href="https://www.linkedin.com/in/tommy-parnell-63a72224"><span style="color:#AAA">https://www.linkedin.com/in/<span style="color:#55F">tommy-parnell-63a72224<span style="color:#AAA"><span style="color:#FFF"></a></span></span></span></span></span></span>
|
||||||
|
<span style="color:#AAA"><b>Web: </b><span style="color:#FFF"><a href="https://blog.terribledev.io"><span style="color:#AAA"><span style="color:#0AA">https://blog.terribledev.io<span style="color:#AAA"><span style="color:#FFF"></a></span></span></span></span></span></span>
|
||||||
|
|
||||||
|
<span style="color:#AAA"><b>Card: </b><span style="color:#FFF"><span style="color:#AAA"><span style="color:#A00">npx<span style="color:#AAA"> terribledev<span style="color:#FFF"></span></span></span></span></span></span>
|
||||||
|
</pre></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
5996
package-lock.json
generated
Normal file
5996
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
96
package.json
Normal file
96
package.json
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
{
|
||||||
|
"name": "terribledev",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "Personal npm card for Tommy Parnell (@terribledev)",
|
||||||
|
"main": "index.html",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/terribledev/terribledev.git"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"prepare": "node src/htmlify",
|
||||||
|
"prepublishOnly": "webpack"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"terribledev": "bin/index.js"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"bin",
|
||||||
|
"dist",
|
||||||
|
"index.html"
|
||||||
|
],
|
||||||
|
"keywords": [
|
||||||
|
"card",
|
||||||
|
"npm",
|
||||||
|
"npm card",
|
||||||
|
"npx",
|
||||||
|
"npx card",
|
||||||
|
"business card"
|
||||||
|
],
|
||||||
|
"author": "Tommy Parnell",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.2.2",
|
||||||
|
"@babel/preset-env": "^7.2.3",
|
||||||
|
"ansi-to-html": "^0.6.9",
|
||||||
|
"babel-loader": "^8.0.4",
|
||||||
|
"boxen": "^2.1.0",
|
||||||
|
"chalk": "^2.4.1",
|
||||||
|
"lodash.get": "^4.4.2",
|
||||||
|
"webpack": "^4.28.1",
|
||||||
|
"webpack-bundle-analyzer": "^3.0.3",
|
||||||
|
"webpack-cli": "^3.1.2"
|
||||||
|
},
|
||||||
|
"myCard": {
|
||||||
|
"info": {
|
||||||
|
"name": "Tommy Parnell",
|
||||||
|
"handle": "terribledev",
|
||||||
|
"twitter": "terribledev",
|
||||||
|
"npm": "terribledev",
|
||||||
|
"github": "terribledev",
|
||||||
|
"linkedin": "tommy-parnell-63a72224",
|
||||||
|
"web": "https://blog.terribledev.io",
|
||||||
|
"work": "Sr. Software Engineer"
|
||||||
|
},
|
||||||
|
"data": [
|
||||||
|
" <white>{{name}}</><green> / </><cyan>{{handle}}</>",
|
||||||
|
"",
|
||||||
|
{
|
||||||
|
"label": "<blue>Work</>",
|
||||||
|
"text": "{{work}}"
|
||||||
|
},
|
||||||
|
"",
|
||||||
|
{
|
||||||
|
"label": "Twitter",
|
||||||
|
"text": "https://twitter.com/<cyan>{{twitter}}</>",
|
||||||
|
"when": "{{twitter}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "npm",
|
||||||
|
"text": "https://www.npmjs.com/<red>~{{npm}}</>",
|
||||||
|
"when": "{{npm}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "GitHub",
|
||||||
|
"text": "https://github.com/<green>{{github}}</>",
|
||||||
|
"when": "{{github}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "LinkedIn",
|
||||||
|
"text": "https://www.linkedin.com/in/<blue>{{linkedin}}</>",
|
||||||
|
"when": "{{linkedin}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Web",
|
||||||
|
"text": "<cyan>{{web}}</>",
|
||||||
|
"when": "{{web}}"
|
||||||
|
},
|
||||||
|
"",
|
||||||
|
{
|
||||||
|
"label": "Card",
|
||||||
|
"text": "<red>npx</> {{_packageName}}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
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"
|
||||||
|
}
|
||||||
|
};
|
||||||
14
stubs/term-size.js
Normal file
14
stubs/term-size.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const xrequire = eval(`require`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
module.exports = xrequire("term-size");
|
||||||
|
} catch {
|
||||||
|
module.exports = function() {
|
||||||
|
return {
|
||||||
|
rows: 24,
|
||||||
|
columns: 80
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
51
webpack.config.js
Normal file
51
webpack.config.js
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const Path = require("path");
|
||||||
|
const webpack = require("webpack");
|
||||||
|
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
|
||||||
|
|
||||||
|
const base = {
|
||||||
|
mode: process.env.ANALYZE_BUNDLE ? "development" : "production",
|
||||||
|
//devtool: "source-map",
|
||||||
|
entry: {
|
||||||
|
"card.js": Path.resolve("src/card.js")
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
process.env.ANALYZE_BUNDLE && new BundleAnalyzerPlugin()
|
||||||
|
].filter(x => x),
|
||||||
|
resolve: {
|
||||||
|
symlinks: false, // don't resolve symlinks to their real path
|
||||||
|
alias: {
|
||||||
|
"term-size": Path.resolve("stubs/term-size.js")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
filename: `[name]`,
|
||||||
|
path: Path.resolve("dist"),
|
||||||
|
libraryTarget: "commonjs2"
|
||||||
|
},
|
||||||
|
target: "node",
|
||||||
|
node: {
|
||||||
|
__filename: false,
|
||||||
|
__dirname: false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const node6 = Object.assign({}, base, {
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.js$/,
|
||||||
|
exclude: x => x.indexOf("node_modules") > 0,
|
||||||
|
use: "babel-loader"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
filename: `node6-[name]`,
|
||||||
|
path: Path.resolve("dist"),
|
||||||
|
libraryTarget: "commonjs2"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = [base, node6];
|
||||||
Reference in New Issue
Block a user