diff --git a/bin/build-site.js b/bin/build-site.js index 46a2fcbb..908cd4bb 100755 --- a/bin/build-site.js +++ b/bin/build-site.js @@ -95,11 +95,20 @@ function copyAssetToBuild( filename, content = null ) { return '/assets/' + destFilename; } +/** + * Return a URL to edit a page on GitHub. + */ +function githubEditUrl( filename ) { + return ( + 'https://github.com/remoteintech/remote-jobs/edit/master/' + + filename + ); +} + /** * Write a page's contents to an HTML file. */ function writePage( filename, pageContent ) { - console.log( 'Writing page "%s"', filename ); filename = path.join( siteBuildPath, filename ); if ( ! fs.existsSync( path.dirname( filename ) ) ) { fs.mkdirSync( path.dirname( filename ) ); @@ -183,6 +192,8 @@ async function buildSite() { url: copyAssetToBuild( 'wpcom-blog-styles.css', wpcomStylesheetContent ), }, { url: '//fonts.googleapis.com/css?family=Source+Sans+Pro:r%7CSource+Sans+Pro:r,i,b,bi&subset=latin,latin-ext,latin,latin-ext', + }, { + url: copyAssetToBuild( 'site.css' ), } ]; const scripts = []; if ( wpcomEmojiScript ) { @@ -192,46 +203,51 @@ async function buildSite() { } // Set up styles/scripts for specific pages - const indexStylesheets = [ { - url: copyAssetToBuild( 'companies-table.css' ), - } ]; const indexScripts = [ { url: '//cdnjs.cloudflare.com/ajax/libs/list.js/1.5.0/list.min.js', }, { url: copyAssetToBuild( 'companies-table.js' ), } ]; - const profileStylesheets = [ { - url: copyAssetToBuild( 'company-profile.css' ), - } ]; // Generate the index.html file from the main README // TODO: Build this page and its table dynamically; more filters const readmeTemplate = swig.compileFile( path.join( sitePath, 'templates', 'index.html' ) ); + console.log( 'Writing main page' ); writePage( 'index.html', readmeTemplate( { - stylesheets: stylesheets.concat( indexStylesheets ), + stylesheets, scripts: scripts.concat( indexScripts ), pageContent: data.readmeContent, + editUrl: githubEditUrl( 'README.md' ), } ) ); // Generate the page for each company const companyTemplate = swig.compileFile( path.join( sitePath, 'templates', 'company.html' ) ); - data.companies.forEach( company => { + process.stdout.write( 'Writing company pages..' ); + data.companies.forEach( ( company, i ) => { const dirname = company.linkedFilename.replace( /\.md$/, '' ); const missingHeadings = Object.keys( headingPropertyNames ) .filter( h => ! company.profileContent[ h ] ); writePage( path.join( dirname, 'index.html' ), companyTemplate( { - stylesheets: stylesheets.concat( profileStylesheets ), + stylesheets, scripts, company, headingPropertyNames, missingHeadings, + editUrl: githubEditUrl( 'company-profiles/' + company.linkedFilename ), } ) ); + + if ( i % 10 === 0 ) { + process.stdout.write( '.' ); + } } ); + + console.log(); + console.log( 'Site files are ready in "site/build/"' ); } buildSite(); diff --git a/bin/serve-site.js b/bin/serve-site.js new file mode 100755 index 00000000..4750de2f --- /dev/null +++ b/bin/serve-site.js @@ -0,0 +1,19 @@ +#!/usr/bin/env node + +const { spawnSync } = require( 'child_process' ); +const path = require( 'path' ); + +// Build the static site +const result = spawnSync( process.execPath, [ + path.join( __dirname, 'build-site.js' ), +], { stdio: 'inherit' } ); +if ( result.error ) { + throw result.error; +} +if ( result.status > 0 ) { + process.exit( result.status ); +} + +// Serve the static site locally +process.argv.splice( 2, 0, path.join( __dirname, '..', 'site', 'build' ) ); +require( 'http-server/bin/http-server' ); diff --git a/company-profiles/the-wirecutter.md b/company-profiles/the-wirecutter.md index 16a4d11c..87d05ab0 100644 --- a/company-profiles/the-wirecutter.md +++ b/company-profiles/the-wirecutter.md @@ -8,10 +8,6 @@ need—tableware or TV or air purifier—we make shopping for it easy by telling you the best one to get. The site was founded in September 2011 and was acquired by The New York Times Company in October 2016. -## Company size - -(TODO) - ## Remote status Some employees work full-time from our office in New York City and some work @@ -21,10 +17,6 @@ remotely from other parts of the US. United States. -## Company technologies - -(TODO) - ## Office locations New York City diff --git a/lib/index.js b/lib/index.js index c1133715..97a8db80 100755 --- a/lib/index.js +++ b/lib/index.js @@ -224,6 +224,11 @@ exports.parseFromDirectory = contentPath => { ); } + // Set classes on table cells + $td.eq( 0 ).attr( 'class', 'company-name' ); + $td.eq( 1 ).attr( 'class', 'company-website' ); + $td.eq( 2 ).attr( 'class', 'company-region' ); + // Rewrite company profile link to the correct URL for the static site if ( $profileLink.length ) { $profileLink.attr( diff --git a/package.json b/package.json index 1578b32e..ca9bf324 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,14 @@ "validate": "bin/validate.js", "test": "mocha", "build": "bin/build-site.js", - "serve": "http-server site/build/" + "serve": "http-server site/build/", + "start": "bin/serve-site.js" + }, + "nodemonConfig": { + "ext": "js,md,html,css", + "ignore": [ + "site/build/" + ] }, "dependencies": { "cheerio": "^1.0.0-rc.2", diff --git a/site/README.md b/site/README.md index 54dbebcd..bd2695b3 100644 --- a/site/README.md +++ b/site/README.md @@ -1,5 +1,7 @@ # Static site generator +## Overview + This folder contains the template files needed to generate the static site for this repo ( https://remoteintech.company/ ). @@ -17,10 +19,26 @@ the site builder code uses [`swig`](https://github.com/node-swig/swig-templates) as an HTML templating engine. -To develop against the site locally, you can run this command: +## Development + +If you submit any changes as a pull request, GitHub and Netlify will +automatically validate, build, and deploy a preview of the site for you. + +For longer-running or more complicated changes, though, it can be useful to run +the site locally. To make this work, you should be using the version of +Node.js specified in the `.nvmrc` file. Other versions may work but have not +been tested. + +Run `npm install` to install dependencies. + +Then run `npm start` to build and serve the site locally. + +You can also use `nodemon` to automatically rebuild and reload the site when +you make changes: ```sh -npm run build && npm run server +npm install -g nodemon +nodemon bin/serve-site.js ``` If you just want the data structure used to build the site, you can do this: diff --git a/site/assets/companies-table.css b/site/assets/companies-table.css deleted file mode 100644 index 19a9e355..00000000 --- a/site/assets/companies-table.css +++ /dev/null @@ -1,76 +0,0 @@ -#company-filter { - margin: 0 16px; - padding: 8px; - font-family: "Source Sans Pro", sans-serif; - font-size: 15px; - font-weight: normal; - vertical-align: middle; -} - -#filters-explanation { - font-style: italic; - font-size: 15px; -} - -@media screen and (min-width: 50em) { - #filters-explanation { - font-size: 16px; - } -} - -table#companies-table.has-filter th { - padding: 0; -} - -table#companies-table button.sort { - width: 100%; - border-width: 0; - border-radius: 0; - padding: 7px 3px 4px; - text-align: left; - font-weight: 700; - color: #666; - outline: none; -} -table#companies-table button.sort:hover, -table#companies-table button.sort:focus { - color: #c61610; -} -table#companies-table button.sort:hover { - background: #f4f4f4; -} - -/* Sort indicators adapted from http://listjs.com/examples/table/ */ - -table#companies-table .sort.asc:after, -table#companies-table .sort.desc:after { - width: 0; - height: 0; - border-left: 6px solid transparent; - border-right: 6px solid transparent; - content:""; - display: inline-block; - position: relative; - left: 3px; - top: -2px; -} - -table#companies-table .sort.asc:after { - border-bottom: 6px solid; -} - -table#companies-table .sort.desc:after { - border-top: 6px solid; -} - -/* Keep table columns the same width after filtering */ - -table#companies-table td.company-name { - width: 40%; -} -table#companies-table td.company-website { - width: 35%; -} -table#companies-table td.company-region { - width: 25%; -} diff --git a/site/assets/companies-table.js b/site/assets/companies-table.js index 3149269a..21b44cdf 100644 --- a/site/assets/companies-table.js +++ b/site/assets/companies-table.js @@ -12,15 +12,6 @@ function setupFilters() { var tbody = table.querySelector( 'tbody' ); tbody.setAttribute( 'class', 'list' ); - var bodyRows = Array.prototype.slice.call( tbody.querySelectorAll( 'tr' ) ); - - bodyRows.forEach( function( tr ) { - var tds = tr.querySelectorAll( 'td' ); - tds[ 0 ].setAttribute( 'class', 'company-name' ); - tds[ 1 ].setAttribute( 'class', 'company-website' ); - tds[ 2 ].setAttribute( 'class', 'company-region' ); - } ); - var filterInput = document.createElement( 'input' ); filterInput.type = 'text'; filterInput.placeholder = 'Filter Companies'; @@ -50,7 +41,10 @@ function setupFilters() { } ); - table.setAttribute( 'class', 'has-filter' ); + document.body.setAttribute( + 'class', + document.body.getAttribute( 'class' ) + ' filters-enabled' + ); } document.addEventListener( 'DOMContentLoaded', function( event ) { diff --git a/site/assets/company-profile.css b/site/assets/company-profile.css deleted file mode 100644 index a94c9151..00000000 --- a/site/assets/company-profile.css +++ /dev/null @@ -1,9 +0,0 @@ -h1.company-name { - margin-bottom: 8px; -} - -.section-atAGlance { - font-size: 15px; - color: #999; - font-size: 85%; -} diff --git a/site/assets/site.css b/site/assets/site.css new file mode 100644 index 00000000..d30f1e40 --- /dev/null +++ b/site/assets/site.css @@ -0,0 +1,216 @@ +/** + * Global styles + */ + +footer span[role=separator] { + padding: 0 0.2em; +} + +footer span[role=separator]::before { + content: '\2022'; + font-weight: 700; +} + +@media screen and (max-width: 600px) { + footer span[role=separator]::before { + content: '\A'; + white-space: pre; + } +} + +.site-info a { + color: #c61610; +} + +a:hover, +a:visited:hover { + color: #999; +} + +/** + * Styles for company profile pages + */ + +h1.company-name { + margin-bottom: 8px; +} + +.section-atAGlance { + font-size: 15px; + color: #999; + font-size: 85%; +} + +/** + * Styles for the companies table and filters on the main page + */ + +#company-filter { + margin: 0 0 0 16px; + padding: 8px; + font-family: "Source Sans Pro", sans-serif; + font-size: 15px; + font-weight: 300; + vertical-align: middle; +} + +#filters-explanation { + font-style: italic; + font-size: 15px; +} + +@media screen and (min-width: 50em) { + #filters-explanation { + font-size: 16px; + } +} + +body.filters-enabled table#companies-table th { + padding: 0; +} + +table#companies-table button.sort { + width: 100%; + border-width: 0; + border-radius: 0; + padding: 7px 3px 4px; + text-align: left; + font-weight: 700; + color: #666; + outline: none; +} +table#companies-table button.sort:hover, +table#companies-table button.sort:focus { + color: #c61610; +} +table#companies-table button.sort:hover { + background: #f4f4f4; +} + +/* Sort indicators adapted from http://listjs.com/examples/table/ */ + +table#companies-table .sort.asc:after, +table#companies-table .sort.desc:after { + width: 0; + height: 0; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + content: ''; + display: inline-block; + position: relative; + left: 3px; + top: -2px; +} + +table#companies-table .sort.asc:after { + border-bottom: 6px solid; +} + +table#companies-table .sort.desc:after { + border-top: 6px solid; +} + +/* Column-specific styles */ + +table#companies-table td.company-name { + font-weight: 700; + width: 40%; +} + +table#companies-table td.company-website { + width: 35%; +} + +table#companies-table td.company-region { + width: 25%; +} + +/* Mobile-friendly display */ + +@media screen and (max-width: 600px) { + body.filters-enabled h2#companies { + margin-bottom: 18px; + } + + #company-filter { + display: block; + width: 100%; + margin: 27px 0 0 0; + } + + table#companies-table, + table#companies-table thead, + table#companies-table tbody, + table#companies-table tr { + display: block; + } + + table#companies-table tr { + border-bottom: 1px solid #eee; + padding: 0 0 8px 12px; + } + + table#companies-table button.sort { + width: auto; + padding-left: 6px; + padding-right: 6px; + } + + table#companies-table .sort.asc:after, + table#companies-table .sort.desc:after { + margin-right: 2px; + } + + table#companies-table thead tr { + border-bottom-width: 3px; + padding: 0; + } + + table#companies-table th, + table#companies-table td { + width: auto !important; + padding-left: 0; + padding-right: 0; + border-bottom-width: 0; + } + + table#companies-table th { + display: inline-block; + } + + table#companies-table th::after { + padding: 0 3px 0 6px; + content: '/'; + } + + table#companies-table th:last-child::after { + display: none; + } + + table#companies-table td.company-name { + display: flex; + font-size: 16px; + font-weight: 700; + padding-bottom: 0; + margin-left: -12px; + } + + table#companies-table td.company-name a { + flex: 100%; + } + + table#companies-table td.company-website, + table#companies-table td.company-region { + display: inline; + padding: 0; + } + + table#companies-table td.company-region::before { + padding: 0 6px 0 3px; + content: '/'; + } + + table#companies-table td.company-region:empty::before { + display: none; + } +} diff --git a/site/templates/base.html b/site/templates/base.html index 1ca8a759..c77a8188 100644 --- a/site/templates/base.html +++ b/site/templates/base.html @@ -51,8 +51,6 @@
Want to help? - + Send us a pull request on GitHub with your changes to this file! diff --git a/test/fixtures/valid-incomplete/parsed-content/readme.html b/test/fixtures/valid-incomplete/parsed-content/readme.html index 77a70b55..24b094bc 100644 --- a/test/fixtures/valid-incomplete/parsed-content/readme.html +++ b/test/fixtures/valid-incomplete/parsed-content/readme.html @@ -14,39 +14,39 @@ website links.