Skip to content

Commit

Permalink
0.0.9. Major refactor to remove embed templates. Adds UnCSS. Fixes #17,
Browse files Browse the repository at this point in the history
fixes #16, fixes #15, fixes #14, fixes #12, fixes #11, fixes #10, fixes #9.
  • Loading branch information
hobbes7878 committed May 30, 2017
1 parent ac51db8 commit 943e585
Show file tree
Hide file tree
Showing 56 changed files with 438 additions and 524 deletions.
39 changes: 33 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@



A [Yeoman](http://yeoman.io) generator to scaffold a development environment for building Politico interactives.
A [Yeoman](http://yeoman.io) generator to scaffold a development environment for building POLITICO interactives.

### What it does:

- Scaffolds your project's development directory, either for an embeddable feature or a complete interactive page.
- Scaffolds your project's development directory.
- Compiles SCSS and bundles JS written in either ES5 or ES2015 using your choice of browserify or webpack.
- Creates responsive image sets optimized for mobile devices.
- Publishes your project to an Amazon S3 bucket.
Expand Down Expand Up @@ -102,6 +102,34 @@ There is also an extra filter specifically for rendering [Markdown](https://gith
<h1>{{sectionTitle|markdown(strip=true)}}</h1>
```
#### UnCSS
When building for production, this app uses [UnCSS](https://github.com/giakki/uncss) to remove unused styles. If you have rules that apply to classes set with JavaScript, you must explicitly tell UnCSS not to remove them with a special comment. By default, we also tell UnCSS to ignore any rules set inside a graphics section or with a class of `dataviz`.
```CSS
/* These rules will all be preserved by UnCSS */
/* uncss:ignore */
.myClass {
/* ... */
}
section.graphic{
/*...*/
.myClass {
/*...*/
}
}
.dataviz {
/*...*/
.myClass {
/*...*/
}
}
```
#### ArchieML
Optionally, there is a gulp task available which allows you to use [ArchieML](http://archieml.org/#demo) and Google Docs to render content into your templates.
Expand Down Expand Up @@ -162,16 +190,15 @@ To change styles, simply update the scss files in the following directory within
If you need to add a new SCSS file, ask a developer to help you write the line that loads your new file into a user's development directory.

If you need to make changes to HTML templates, they are split between these folder, depending on what kind of project you're updating:
If you need to make changes to HTML templates, they are here:

- `generators/templates-embeddable/src/templates`
- `generators/templates-interactive/src/templates`
- `generators/templates/src/templates`

Again, if you need to add a new HTML file, rather than simply change an old one, talk to a developer.

#### Publishing

Once you're satisfied with your changes, publish your updates through the following steps:
Once you're satisfied with your changes and have tested your update, publish your updates through the following steps:
1. Increment the version number in `package.json`, e.g., `0.0.3` --> `0.0.4`
2. Commit your changes to github
3. Run:
Expand Down
155 changes: 10 additions & 145 deletions generators/app/index.js
Original file line number Diff line number Diff line change
@@ -1,165 +1,30 @@
const Generator = require('yeoman-generator');
const S = require('string');

module.exports = class extends Generator {
constructor(args, opts) {
super(args, opts);
// Bundler options
this.BROWSERIFY = 'browserify';
this.WEBPACK = 'webpack';
// Project type options
this.EMBED = 'embed';
this.PAGE = 'page';
}

initializing() {
this.composeWith(require.resolve('../linters'));
this.composeWith(require.resolve('../gulp'));
this.composeWith(require.resolve('../styles'));
this.composeWith(require.resolve('../aws'));
}

prompting() {
const questions = [{
type: 'list',
name: 'projectType',
message: 'Yo Politico! What do you want to make today?',
choices: [
{
name: 'embeddable',
value: this.EMBED,
},
{
name: 'interactive page',
value: this.PAGE,
},
],
}, {
type: 'input',
name: 'projectTitle',
message: 'OK, what do we call it?',
}, {
type: 'list',
name: 'projectBundler',
message: 'Which module bundler would you like to use?',
default: this.BROWSERIFY,
choices: [
{
name: 'Browserify (default)',
value: this.BROWSERIFY,
},
{
name: 'Webpack (ES2015 + SCSS)',
value: this.WEBPACK,
},
],
}, {
type: 'confirm',
name: 'archieML',
message: 'Would like to include an ArchieML configuration?',
default: false,
}, {
name: 'awsAccessKey',
message: 'What\'s your AWS access key?',
store: true,
}, {
name: 'awsSecretKey',
message: 'What\'s your AWS secret key?',
store: true,
name: 'title',
message: 'Welcome to your new interactive. What will we call it?',
}];

return this.prompt(questions).then((answers) => {
this.projectType = answers.projectType;
this.projectTitle = answers.projectTitle;
this.projectSlug = S(answers.projectTitle).slugify().s;
this.projectBundler = answers.projectBundler;
this.archieML = answers.archieML;
this.awsAccessKey = answers.awsAccessKey;
this.awsSecretKey = answers.awsSecretKey;
this.title = answers.title;
});
}
template() {
switch (this.projectType) {
case 'embed':
this.composeWith(require.resolve('../templates-embeddable'), {
title: this.projectTitle,
webpack: this.projectBundler === this.WEBPACK,
archie: this.archieML,
});
break;
default:
this.composeWith(require.resolve('../templates-page'), {
title: this.projectTitle,
webpack: this.projectBundler === this.WEBPACK,
archie: this.archieML,
});
}
}
writing() {
this.fs.copy(
this.templatePath('aws.json.example'),
this.destinationPath('aws.json.example'));

this.fs.copy(
this.templatePath('gitignore'),
this.destinationPath('./.gitignore'));

this.fs.copyTpl(
this.templatePath('package.json'),
this.destinationPath('package.json'), {
slug: this.projectSlug,
userName: this.user.git.name(),
userEmail: this.user.git.email(),
});

const awsJSON = {
accessKeyId: this.awsAccessKey,
secretAccessKey: this.awsSecretKey,
params: {
Bucket: 'com.politico.interactives.politico.com',
CloudFront: 'E3V6OHE700RHMR',
},
};

const timestamp = new Date();
const publishPath = this.projectType === 'embed' ?
`${timestamp.getFullYear()}/embed/${this.projectSlug}/` :
`${timestamp.getFullYear()}/${this.projectSlug}/`;

const metaJSON = {
id: (Math.floor(Math.random() * 100000000000) + 1).toString(),
publishPath,
url: `http://www.politico.com/interactives/${publishPath}`,
share: {
fbook: {
card_title: this.projectTitle,
card_description: '<Text>',
author: 'politico',
},
twitter: {
card_title: this.projectTitle,
card_description: '<Text>',
author: '@politico',
},
image: {
url: `http://www.politico.com/interactives/${publishPath}images/share.jpg`,
alt: '<Text>',
type: 'image/jpeg',
width: '600',
height: '315',
},
keywords: 'Politico, News, Washington D.C.',
},
telium: {
free_paid_content: 'free',
site_section: 'white house',
ad_unit_section: 'whitehouse',
content_author: 'Polly Politico|Peter Politico',
content_byline: 'By Polly Politico and Peter Politico',
page_name: `${this.projectTitle} — POLITICO`,
},
};

this.fs.writeJSON('aws.json', awsJSON);
this.fs.writeJSON('meta.json', metaJSON);
this.composeWith(require.resolve('../meta'), {
title: this.title,
});
this.composeWith(require.resolve('../templates'), {
title: this.title,
});
}
};
37 changes: 37 additions & 0 deletions generators/aws/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
const Generator = require('yeoman-generator');

module.exports = class extends Generator {
prompting() {
const questions = [{
name: 'awsAccessKey',
message: 'What\'s your AWS access key?',
store: true,
}, {
name: 'awsSecretKey',
message: 'What\'s your AWS secret key?',
store: true,
}];

return this.prompt(questions).then((answers) => {
this.awsAccessKey = answers.awsAccessKey;
this.awsSecretKey = answers.awsSecretKey;
});
}

writing() {
this.fs.copy(
this.templatePath('aws.json.example'),
this.destinationPath('aws.json.example'));

const awsJSON = {
accessKeyId: this.awsAccessKey,
secretAccessKey: this.awsSecretKey,
params: {
Bucket: 'com.politico.interactives.politico.com',
CloudFront: 'E3V6OHE700RHMR',
},
};

this.fs.writeJSON('aws.json', awsJSON);
}
};
File renamed without changes.
24 changes: 5 additions & 19 deletions generators/bundler-browserify/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,6 @@ module.exports = class extends Generator {
constructor(args, opts) {
super(args, opts);

this.option('embed', {
type: Boolean,
required: false,
default: false,
desc: 'Whether building an embeddable',
});
this.option('archie', {
type: Boolean,
required: false,
Expand All @@ -19,16 +13,6 @@ module.exports = class extends Generator {
}

writing() {
if (this.options.embed) {
this.fs.copy(
this.templatePath('src/js/main-embed.js'),
this.destinationPath('src/js/main.js'));
} else {
this.fs.copy(
this.templatePath('src/js/main.js'),
this.destinationPath('src/js/main.js'));
}

this.fs.copyTpl(
this.templatePath('gulpfile.js'),
this.destinationPath('gulpfile.js'), {
Expand Down Expand Up @@ -66,9 +50,13 @@ module.exports = class extends Generator {
'fs-extra',
'gulp',
'gulp-babili',
'gulp-cssnano',
'gulp-env',
'gulp-if',
'gulp-nunjucks-render',
'gulp-sass',
'gulp-sourcemaps',
'gulp-uncss',
'gulp-util',
'marked',
'nunjucks',
Expand All @@ -78,9 +66,7 @@ module.exports = class extends Generator {
'vinyl-source-stream',
'watchify',
];
if (this.options.embed) {
dependencies.push('pym.js');
}

this.yarnInstall(dependencies, { save: true });
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ marked.setOptions({ smartypants: true });
const manageEnvironment = (environment) => {
environment.addFilter('markdown', (str, kwargs) => {
// strip outer <p> tags?
const strip = kwargs.strip || false;
const strip = typeof kwargs === 'undefined' ?
false : kwargs.strip || false;
return !strip ? safe(marked(str)) :
safe(marked(str).trim().replace(/^<p>|<\/p>$/g, ''));
});
Expand Down
26 changes: 19 additions & 7 deletions generators/bundler-browserify/templates/gulp/tasks/scss.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
const gulp = require('gulp');
const gulpif = require('gulp-if');
const nano = require('gulp-cssnano');
const rename = require('gulp-rename');
const sass = require('gulp-sass');
const sourcemaps = require('gulp-sourcemaps');
const uncss = require('gulp-uncss');

const production = task => gulpif(process.env.NODE_ENV === 'production', task);

module.exports = () =>
gulp.src(['./src/scss/**/*.scss', './src/scss/**/*.css'])
// eslint-disable-next-line no-param-reassign
.pipe(rename((filePath) => { filePath.basename += '.bundle'; }))
.pipe(sourcemaps.init())
.pipe(sass({ outputStyle: 'compressed' }).on('error', sass.logError))
.pipe(sourcemaps.write())
.pipe(gulp.dest('./dist/css'));
gulp.src(['./src/scss/**/*.scss', './src/scss/**/*.css'])
// eslint-disable-next-line no-param-reassign
.pipe(rename((filePath) => { filePath.basename += '.bundle'; }))
.pipe(sourcemaps.init())
.pipe(sass().on('error', sass.logError))
.pipe(production(uncss({
html: ['**/*.html'],
ignore: [
/section\.graphic.*/,
/\.dataviz.*/,
],
})))
.pipe(production(nano()))
.pipe(sourcemaps.write())
.pipe(gulp.dest('./dist/css'));
Loading

0 comments on commit 943e585

Please sign in to comment.