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