Improve class handling in PDF

* Update phar
* Fix several sniff errors
* Remove unused converter file
* Update README with better quickstart information
This commit is contained in:
Craig Davis 2014-01-12 14:33:43 -07:00
parent d225525927
commit b87c193db5
6 changed files with 58 additions and 749 deletions

View File

@ -16,17 +16,19 @@ at the [blog post for the project][blog].
## Features
* Three styles to choose from: modern, blockish, unstyled
* Three styles to choose from: modern, blockish, unstyled (Fork and add more!)
* PDF generation via [wkhtmltopdf][wkhtmltopdf]
* Responsive design for multiple device viewport sizes
* Simple Markdown formatting
* Single file deployment
* Single file deployment (no external stylesheets)
* You can now version control and branch your resume.
## Quickstart
php ./bin/resume.php --source resume/sample.md
php ./bin/resume.php --source resume/sample.md --pdf
There is no installation or need to run composer. Just run the phar file:
./bin/md2resume html examples/source/sample.md examples/output/
./bin/md2resume pdf examples/source/sample.md examples/output/
## Help
@ -57,45 +59,56 @@ at the [blog post for the project][blog].
Choose a template with the -t option.
php ./bin/resume.php --source resume/sample.md -t blockish
./bin/md2resume html --template blockish examples/source/sample.md examples/output/
If you want to edit your markdown resume in your editor while watching it
update in your browser, run this command:
watch php ./bin/resume.php -s resume/sample.md -r
watch ./bin/md2resume html --refresh examples/source/sample.md examples/output/
This makes the build script run periodically, and html document will refresh
every two seconds via a meta tag. Open the `./ouput/sample.html` file in
your browser, and then just save your markdown document when you want to see
every two seconds via a meta tag. Open the `./examples/ouput/sample.html` file
in your browser, and then just save your markdown document when you want to see
a fresh preview.
## Development
## Authoring Your Resume
Markdown is limited to basic html markup. Follow the `resume/sample.md` file
as a guideline. This file includes various headers and several nested elements.
This allows us to construct a semantic HTML document for the resume, and then
use a CSS rules to display a very nice resume. Note that because we have very
few ways to nest or identify elements that many of the css rules are based
on descendant and adjacent selectors.
Markdown is limited to basic html markup. Follow the `examples/source/sample.md`
file as a guideline. This file includes various headers and several nested
elements. This allows us to construct a semantic HTML document for the resume,
and then use a CSS rules to display a very nice resume. Note that because we
have very few ways to nest or identify elements that many of the css rules are
based on descendant and adjacent selectors.
## Development Dependencies
## Feature Development
* composer install
* pear install PHP_CodeSniffer
The application is deployed as a compiled phar file. In order to add new
commands, you'll need to first install the dependencies:
* `composer install`
* `pear install PHP_CodeSniffer`
* [install pake][pake]
After that, you can run the `md2resume_dev.php` file from the command line.
Check out the pake tooling for more information about the build.
## TODO
* Google Analytics include
* CDN for fonts
## Acknowledgments
The initial inspiration is from the [Sample Resume Template][srt].
However, no HTML from that project has been used in this. General layout has been reused, and media queries
have been added. It's a nice template, and if you are a more comfortable with html than markdown, you should use it.
However, no HTML from that project has been used in this. General layout has
been reused, and media queries have been added. It's a nice template, and if you
are a more comfortable with html than markdown, you should use it.
## Changelog
* __2.0.0__ : Complete rewrite with the [symfony console component][console].
Deployment is no done with a compiled phar file, and development dependencies
are managed with composer.
* __0.9.0__ : Add composer and update README with new changelog
* __0.8.8__ : Add Chinese text example (@ishitcno1)
* __0.8.7__ : Update pdf formatting of the modern template (@roleary)
@ -110,3 +123,4 @@ have been added. It's a nice template, and if you are a more comfortable with ht
[blog]: http://there4development.com/blog/2012/12/31/markdown-resume-builder/
[pake]: https://github.com/indeyets/pake/wiki/Installing-Pake
[wkhtmltopdf]: https://github.com/pdfkit/pdfkit/wiki/Installing-WKHTMLTOPDF
[console]: http://symfony.com/doc/current/components/console/introduction.html

Binary file not shown.

View File

@ -1,691 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Craig Davis | Senior PHP Developer, UX Director</title>
<style type="text/css">
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
nav,
section,
summary {
display: block;
}
audio,
canvas,
video {
display: inline-block;
*display: inline;
*zoom: 1;
}
audio:not([controls]) {
display: none;
}
[hidden] {
display: none;
}
html {
font-size: 100%;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}
html,
button,
input,
select,
textarea {
font-family: sans-serif;
}
body {
margin: 0;
}
a:focus {
outline: thin dotted;
}
a:hover,
a:active {
outline: 0;
}
h1 {
font-size: 2em;
margin: 0.67em 0;
}
h2 {
font-size: 1.5em;
margin: 0.83em 0;
}
h3 {
font-size: 1.17em;
margin: 1em 0;
}
h4 {
font-size: 1em;
margin: 1.33em 0;
}
h5 {
font-size: 0.83em;
margin: 1.67em 0;
}
h6 {
font-size: 0.75em;
margin: 2.33em 0;
}
abbr[title] {
border-bottom: 1px dotted;
}
b,
strong {
font-weight: bold;
}
blockquote {
margin: 1em 40px;
}
dfn {
font-style: italic;
}
mark {
background: #ff0;
color: #000;
}
p,
pre {
margin: 1em 0;
}
pre,
code,
kbd,
samp {
font-family: monospace, serif;
_font-family: 'courier new', monospace;
font-size: 1em;
}
pre {
white-space: pre;
white-space: pre-wrap;
word-wrap: break-word;
}
q {
quotes: none;
}
q:before,
q:after {
content: '';
content: none;
}
small {
font-size: 75%;
}
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sup {
top: -0.5em;
}
sub {
bottom: -0.25em;
}
dl,
menu,
ol,
ul {
margin: 1em 0;
}
dd {
margin: 0 0 0 40px;
}
menu,
ol,
ul {
padding: 0 0 0 40px;
}
nav ul,
nav ol {
list-style: none;
list-style-image: none;
}
img {
border: 0;
-ms-interpolation-mode: bicubic;
}
svg:not(:root) {
overflow: hidden;
}
figure {
margin: 0;
}
form {
margin: 0;
}
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
legend {
border: 0;
padding: 0;
white-space: normal;
*margin-left: -7px;
}
button,
input,
select,
textarea {
font-size: 100%;
margin: 0;
vertical-align: baseline;
*vertical-align: middle;
}
button,
input {
line-height: normal;
}
button,
input[type="button"],
input[type="reset"],
input[type="submit"] {
cursor: pointer;
-webkit-appearance: button;
*overflow: visible;
}
button[disabled],
input[disabled] {
cursor: default;
}
input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box;
padding: 0;
*height: 13px;
*width: 13px;
}
input[type="search"] {
-webkit-appearance: textfield;
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box;
box-sizing: content-box;
}
input[type="search"]::-webkit-search-decoration,
input[type="search"]::-webkit-search-cancel-button {
-webkit-appearance: none;
}
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}
textarea {
overflow: auto;
vertical-align: top;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
body.pdf {
color: black;
}
body.pdf a {
text-decoration: none;
color: black;
}
body.pdf .container {
width: 1000px;
margin: 0 auto;
padding: 0;
background: none;
border: none;
border-width: 8px 0 2px 0;
text-align: left;
}
body.pdf .resume {
position: relative;
padding: 40px 80px;
}
body.pdf a[href$='.pdf'] {
display: none;
}
body.pdf h1 {
letter-spacing: 0;
margin-top: 0;
font-size: 48px;
text-transform: uppercase;
font-weight: normal;
}
body.pdf h2 {
letter-spacing: 0;
text-transform: uppercase;
font-style: italic;
font-weight: normal;
}
body.pdf h3 {
float: left;
width: 16%;
font-style: normal;
}
body.pdf h3+p {
float: left;
width: 84%;
}
body.pdf blockquote {
top: 40px;
right: 50px;
position: absolute;
}
body.pdf ul li {
width: 28%;
float: left;
}
body.pdf ul dl {
margin: 0;
padding: 0.3em 0 0;
}
body.pdf ul dl dt {
font-size: 122%;
font-weight: normal;
margin: 0 0 .75em;
}
body.pdf ul dl dd {
padding: 0 4em 0 0;
}
body.pdf ol {
float: left;
width: 84%;
margin: .7em 0 0;
}
body.pdf ol li {
width: 33%;
margin: 0;
}
body.pdf ol li:nth-child(3n) {
width: 34%;
}
body.pdf ol li:nth-child(1),
body.pdf ol li:nth-child(2),
body.pdf ol li:nth-child(3) {
border-top: none;
}
body.pdf dl {
margin: .7em 0 0;
page-break-inside: avoid !important;
display: block;
width: 84%;
float: left;
}
body.pdf dl strong {
float: right;
margin-top: -2em;
}
body.pdf dl em {
font-size: 130%;
font-style: normal;
}
.clearfix {
zoom: 1;
}
.clearfix:after {
display: block;
visibility: hidden;
height: 0;
clear: both;
content: ".";
}
body {
font-family: 'Hoefler Text', Times New Roman, Times, serif;
color: #444;
}
h1,
h2,
h3,
h4,
ul dl dt {
font-family: Futura, "Century Gothic", AppleGothic, sans-serif;
}
.container {
margin: 0 auto;
padding: 0;
background: whiteSmoke;
border: solid #666;
border-width: 8px 0 2px 0;
text-align: left;
}
.resume {
position: relative;
padding: 10px 20px;
}
a {
color: #990003;
}
a[href$='.pdf'] {
display: inline-block;
background: #666;
color: white;
padding: 6px 12px;
margin-bottom: 6px;
text-decoration: none;
}
blockquote {
margin: 0;
padding: 0;
line-height: 1.4em;
}
hr {
display: block;
position: relative;
padding: 0;
margin: 18px auto;
width: 100%;
clear: both;
border: none;
border-top: 1px solid #CCC;
font-size: 1px;
line-height: 0;
overflow: visible;
page-break-after: avoid;
}
h1 {
margin: 0;
padding: 0;
font-size: 36px;
letter-spacing: -1px;
font-weight: normal;
}
h2 {
margin: 0;
padding: 0;
font-size: 18px;
font-style: italic;
letter-spacing: -1px;
font-weight: normal;
}
h3 {
margin: 0;
padding: 0 0 .5em;
font-size: 150%;
font-style: italic;
font-weight: normal;
}
h3+p {
margin: .6em 0 16px;
padding: 0;
display: block;
font-size: 104%;
line-height: 24px;
}
ul {
margin: 0;
padding: 0;
list-style: none;
}
ul li {
margin: 0;
padding: 0;
}
ul dl {
margin: .3em 0 0;
padding: 0;
width: 100%;
}
ul dl dt {
font-size: 100%;
}
ul dl dd {
margin: 0 0 1em;
padding: 0 2em 0 0;
font-size: .8em;
line-height: 1.5em;
}
ol {
margin: 0;
padding: 0 0 .75em;
width: 84%;
display: inline-block;
}
ol li {
margin: 0 0 0 1em;
padding: 0;
border-top: 1px solid #CCCCCC;
width: 100%;
float: left;
list-style: none;
line-height: 24px;
font-size: 14px;
}
ol li:nth-child(1) {
border-top: none;
}
dl {
display: inline-block;
width: 75%;
margin: 0;
padding: 0;
}
dl dt {
margin: 0;
padding: 0;
font-size: 140%;
}
dl dd {
margin: 0 0 1.5em;
padding: 0;
font-size: 80%;
line-height: 1.4em;
}
dl strong {
display: block;
}
dl em {
display: block;
font-size: 110%;
margin: .15em 0 .5em;
font-style: bold;
}
#footer {
display: none;
}
#footer + p {
width: 100%;
font-size: 11px;
text-align: center;
}
@media screen and (min-width: 37.5em) {
body {
padding: 2em 0;
}
blockquote {
top: 10px;
right: 50px;
position: absolute;
}
h1 {
margin-top: .5em;
}
ol {
margin: 0 0 0 1em;
}
ol li {
width: 50%;
margin: 0;
}
ol li:nth-child(1),
ol li:nth-child(2) {
border-top: none;
}
}
@media screen and (min-width: 57em) {
.container {
width: 912px;
}
.resume {
position: relative;
padding: 40px 50px;
}
blockquote {
top: 40px;
right: 50px;
position: absolute;
}
h1 {
margin-top: 0;
font-size: 48px;
text-transform: uppercase;
letter-spacing: 3px;
font-weight: normal;
}
h2 {
text-transform: uppercase;
font-style: italic;
letter-spacing: 2px;
font-weight: normal;
}
h3 {
float: left;
width: 16%;
}
h3+p {
float: left;
width: 84%;
}
ul li {
width: 28%;
float: left;
}
ul dl dt {
font-size: 122%;
font-weight: normal;
margin-bottom: .75em;
}
ul dl dd {
padding: 0 4em 0 0;
}
ol {
float: left;
width: 84%;
margin: .6em 0 0;
}
ol li {
width: 33%;
margin: 0;
}
ol li:nth-child(3n) {
width: 34%;
}
ol li:nth-child(1),
ol li:nth-child(2),
ol li:nth-child(3) {
border-top: none;
}
dl {
margin: .5em 0 0;
}
dl strong {
float: right;
margin-top: -2em;
}
dl em {
font-size: 130%;
font-style: normal;
}
}
</style>
</head>
<body class="">
<div class="container">
<div class="resume">
<h1>Craig Davis</h1>
<h2>Senior PHP Developer, UX Director</h2>
<blockquote>
<p><a href="resume.pdf">Download PDF</a><br />
<a href="craig@there4development.com">craig@there4development.com</a><br />
(999) 888-7777</p>
</blockquote>
<hr />
<h3 id="profile">Profile</h3>
<p>Progressively evolve cross-platform ideas before impactful infomediaries. Energistically visualize tactical initiatives before cross-media catalysts for change.</p>
<hr />
<h3 id="skills">Skills</h3>
<ul>
<li><dl>
<dt>Web Design</dt>
<dd>Assertively exploit wireless initiatives rather than synergistic core competencies.</dd>
</dl></li>
<li><dl>
<dt>Interface Design</dt>
<dd>Credibly streamline mission-critical value with multifunctional functionalities.</dd>
</dl></li>
<li><dl>
<dt>Project Direction</dt>
<dd>Proven ability to lead and manage a wide variety of design and development projects in team and independent situations.</dd>
</dl></li>
</ul>
<hr />
<h3 id="technical">Technical</h3>
<ol>
<li>XHTML</li>
<li>CSS</li>
<li>Javascript</li>
<li>Jquery</li>
<li>PHP</li>
<li>CVS / Subversion</li>
<li>OS X</li>
<li>Windows XP/Vista</li>
<li>Linux</li>
</ol>
<hr />
<h3 id="experience">Experience</h3>
<dl>
<dt>Initrode Conglomerated</dt>
<dd><em>Principal and Creative Lead</em>
<strong>2004-2005</strong>
Intrinsicly transform flexible manufactured products without excellent intellectual capital. Energistically evisculate orthogonal architectures through covalent action items. Assertively incentivize sticky platforms without synergistic materials.</dd>
<dt>Gizmonic Institute Company (GIM)</dt>
<dd><em>Lead Web Designer</em>
<strong>2001-2004</strong>
Globally re-engineer cross-media schemas through viral methods of empowerment. Proactively grow long-term high-impact human capital and highly efficient innovation. Intrinsicly iterate excellent e-tailers with timely e-markets.</dd>
</dl>
<hr />
<h3 id="footer">Footer</h3>
<p>Craig Davis &#8212; <a href="craig@there4development.com">craig@there4development.com</a> &#8212; (999) 888-7777</p>
<hr />
</div>
</div>
</body>
</html>

View File

@ -1,9 +0,0 @@
<?php
namespace Resume\Cli;
class Converter
{
}
/* End of file Converter.php */

View File

@ -31,17 +31,17 @@ class HtmlCommand extends Command
'Output destination folder'
)
->addOption(
'template',
't',
InputOption::VALUE_OPTIONAL,
'Which of the templates to use'
'template',
't',
InputOption::VALUE_OPTIONAL,
'Which of the templates to use'
)
->addOption(
'refresh',
'r',
InputOption::VALUE_NONE,
'If set, the html will include a meta command to refresh the ' .
'document every 5 seconds.'
'refresh',
'r',
InputOption::VALUE_NONE,
'If set, the html will include a meta command to refresh the ' .
'document every 5 seconds.'
);
}
@ -86,12 +86,8 @@ class HtmlCommand extends Command
if (!$template) {
$template = $this->app->defaultTemplate;
}
$templatePath = join(DIRECTORY_SEPARATOR, array(
$this->app->templatePath, basename($template)
));
$templateIndexPath = join(DIRECTORY_SEPARATOR, array(
$templatePath, 'index.html'
));
$templatePath = join(DIRECTORY_SEPARATOR, array($this->app->templatePath, basename($template)));
$templateIndexPath = join(DIRECTORY_SEPARATOR, array($templatePath, 'index.html'));
if (!file_exists($templateIndexPath)) {
$output->writeln(
sprintf(

View File

@ -26,10 +26,10 @@ class PdfCommand extends HtmlCommand
'Output destination folder'
)
->addOption(
'template',
't',
InputOption::VALUE_NONE,
'Which of the templates to use'
'template',
't',
InputOption::VALUE_NONE,
'Which of the templates to use'
);
}
@ -46,13 +46,10 @@ class PdfCommand extends HtmlCommand
exec('wkhtmltopdf -V', $results, $returnVal);
if ($returnVal) {
$output->writeln(
sprintf(
"\n<error>Error:</error> Unable to locate wkhtmltopdf.\n" .
" Please make sure that it is installed and available in " .
"your path. \n For installation help, please read: " .
"https://github.com/pdfkit/pdfkit/wiki/Installing-WKHTMLTOPDF \n\n",
$destination
),
"\n<error>Error:</error> Unable to locate wkhtmltopdf.\n" .
" Please make sure that it is installed and available in " .
"your path. \n For installation help, please read: " .
"https://github.com/pdfkit/pdfkit/wiki/Installing-WKHTMLTOPDF \n\n",
$this->app->outputFormat
);
@ -63,8 +60,10 @@ class PdfCommand extends HtmlCommand
// The pdf needs some extra css rules, and so we'll add them here
// to our html document
// TODO: Update this with the simple DOM to add class
$rendered = str_replace('body class=""', 'body class="pdf"', $rendered);
$simpleDom = new \simple_html_dom($rendered);
$body = $simpleDom->find('body', 0);
$body->class = $body->class . ' pdf';
$rendered = (string) $simpleDom;
// Save to a temp destination for the pdf renderer to use
file_put_contents($pdfSource, $rendered);
@ -78,7 +77,7 @@ class PdfCommand extends HtmlCommand
$output->writeln(
sprintf(
"Wrote pdf resume to: <info>%s</info>",
$destination
$destFilename
),
$this->app->outputFormat
);