diff --git a/.bowerrc b/.bowerrc deleted file mode 100644 index 69fad35..0000000 --- a/.bowerrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "directory": "bower_components" -} diff --git a/.editorconfig b/.editorconfig index cf8d7fa..8fcbf50 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,3 +9,9 @@ end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true + +[*.php] +indent_size = 4 + +[templates/**.php] +indent_size = 2 diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..56260bd --- /dev/null +++ b/.eslintrc @@ -0,0 +1,17 @@ +{ + "root": true, + "extends": "eslint:recommended", + "globals": { + "wp": true + }, + "env": { + "browser": true, + "jquery": true, + "node": true, + "amd": true + }, + "parser": "babel-eslint", + "rules": { + "no-console": 0 + } +} diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..b3f9170 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +/.github export-ignore +/.gitattributes export-ignore +/.travis.yml export-ignore diff --git a/.jscsrc b/.jscsrc deleted file mode 100644 index 824aeb1..0000000 --- a/.jscsrc +++ /dev/null @@ -1,95 +0,0 @@ -{ - "requireCurlyBraces": [ - "if", - "else", - "for", - "while", - "do", - "try", - "catch" - ], - "requireOperatorBeforeLineBreak": true, - "requireCamelCaseOrUpperCaseIdentifiers": true, - "maximumLineLength": { - "value": 80, - "allowComments": true, - "allowRegex": true - }, - "validateIndentation": 2, - "validateQuoteMarks": "'", - "disallowMultipleLineStrings": true, - "disallowMixedSpacesAndTabs": true, - "disallowTrailingWhitespace": true, - "disallowSpaceAfterPrefixUnaryOperators": true, - "disallowMultipleVarDecl": true, - "disallowKeywordsOnNewLine": [ - "else" - ], - "requireSpaceAfterKeywords": [ - "if", - "else", - "for", - "while", - "do", - "switch", - "return", - "try", - "catch" - ], - "requireSpaceBeforeBinaryOperators": [ - "=", - "+=", - "-=", - "*=", - "/=", - "%=", - "<<=", - ">>=", - ">>>=", - "&=", - "|=", - "^=", - "+=", - "+", - "-", - "*", - "/", - "%", - "<<", - ">>", - ">>>", - "&", - "|", - "^", - "&&", - "||", - "===", - "==", - ">=", - "<=", - "<", - ">", - "!=", - "!==" - ], - "requireSpaceAfterBinaryOperators": true, - "requireSpacesInConditionalExpression": true, - "requireSpaceBeforeBlockStatements": true, - "requireSpacesInForStatement": true, - "requireLineFeedAtFileEnd": true, - "requireSpacesInFunctionExpression": { - "beforeOpeningCurlyBrace": true - }, - "disallowSpacesInAnonymousFunctionExpression": { - "beforeOpeningRoundBrace": true - }, - "disallowSpacesInsideObjectBrackets": "all", - "disallowSpacesInsideArrayBrackets": "all", - "disallowSpacesInsideParentheses": true, - "jsDoc": { - "checkParamNames": true, - "requireParamTypes": true - }, - "disallowMultipleLineBreaks": true, - "disallowNewlineBeforeBlockStatements": true -} diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index 02b1ec4..0000000 --- a/.jshintrc +++ /dev/null @@ -1,15 +0,0 @@ -{ - "bitwise": true, - "browser": true, - "curly": true, - "eqeqeq": true, - "eqnull": true, - "esnext": true, - "immed": true, - "jquery": true, - "latedef": true, - "newcap": true, - "noarg": true, - "node": true, - "strict": false -} diff --git a/.travis.yml b/.travis.yml index fa38f36..d992245 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,31 +1,47 @@ sudo: false language: php php: - - nightly + - 7.0 - 5.6 - 5.5 - - 5.4 - - hhvm + - nightly + +env: + - TRAVIS_NODE_VERSION="4.2" CXX="g++-4.8" + - TRAVIS_NODE_VERSION="5.3" CXX="g++-4.8" matrix: + fast_finish: true allow_failures: - php: nightly +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-4.8 + cache: + apt: true directories: - - bower_components + - $HOME/.composer/cache - node_modules + - vendor + +before_install: + - composer self-update install: - - npm install -g npm@latest - - npm install -g bower gulp jscs - - npm install - - composer self-update && composer --version - - export PATH="$HOME/.composer/vendor/bin:$PATH" - - composer global require squizlabs/php_codesniffer + - source ~/.nvm/nvm.sh && nvm install $TRAVIS_NODE_VERSION + - travis_retry npm install -g npm@latest + - travis_retry npm install -g eslint + - node -v && npm -v + - npm rebuild + - travis_retry npm install + - npm prune + - composer install -o --prefer-dist --no-interaction script: - npm run build - - npm run jshint - - npm run jscs - - phpcs --standard=ruleset.xml --extensions=php -n -s . + - composer test diff --git a/README.md b/README.md index 6bae46d..3afc0fd 100644 --- a/README.md +++ b/README.md @@ -2,121 +2,118 @@ [![Build Status](https://travis-ci.org/roots/sage.svg)](https://travis-ci.org/roots/sage) [![devDependency Status](https://david-dm.org/roots/sage/dev-status.svg)](https://david-dm.org/roots/sage#info=devDependencies) -Sage is a WordPress starter theme based on HTML5 Boilerplate, gulp, Bower, and Bootstrap Sass, that will help you make better themes. +Sage is a WordPress starter theme with a modern development workflow. -* Source: [https://github.com/roots/sage](https://github.com/roots/sage) -* Homepage: [https://roots.io/sage/](https://roots.io/sage/) -* Documentation: [https://roots.io/sage/docs/](https://roots.io/sage/docs/) -* Twitter: [@rootswp](https://twitter.com/rootswp) -* Newsletter: [Subscribe](http://roots.io/subscribe/) -* Forum: [https://discourse.roots.io/](https://discourse.roots.io/) - -## Requirements - -| Prerequisite | How to check | How to install -| --------------- | ------------ | ------------- | -| PHP >= 5.4.x | `php -v` | [php.net](http://php.net/manual/en/install.php) | -| Node.js 0.12.x | `node -v` | [nodejs.org](http://nodejs.org/) | -| gulp >= 3.8.10 | `gulp -v` | `npm install -g gulp` | -| Bower >= 1.3.12 | `bower -v` | `npm install -g bower` | - -For more installation notes, refer to the [Install gulp and Bower](#install-gulp-and-bower) section in this document. +Write stylesheets with Sass, automatically check your JavaScript for errors, optimize images, enable synchronized browser testing, and more. ## Features -* [gulp](http://gulpjs.com/) build script that compiles both Sass and Less, checks for JavaScript errors, optimizes images, and concatenates and minifies files +* [Webpack](https://webpack.github.io/) is used as a build tool for compiling stylesheets, checking for JavaScript errors, optimizing images, and concatenating and minifying files * [BrowserSync](http://www.browsersync.io/) for keeping multiple browsers and devices synchronized while testing, along with injecting updated CSS and JS into your browser while you're developing -* [Bower](http://bower.io/) for front-end package management -* [asset-builder](https://github.com/austinpray/asset-builder) for the JSON file based asset pipeline * [Bootstrap](http://getbootstrap.com/) -* [Theme wrapper](https://roots.io/sage/docs/theme-wrapper/) +* Template inheritance with the [theme wrapper](https://roots.io/sage/docs/theme-wrapper/) * ARIA roles and microformats * Posts use the [hNews](http://microformats.org/wiki/hnews) microformat * [Multilingual ready](https://roots.io/wpml/) and over 30 available [community translations](https://github.com/roots/sage-translations) -Install the [Soil](https://github.com/roots/soil) plugin to enable additional features: +Install the [Soil](https://roots.io/plugins/soil/) plugin to enable additional recommended features: -* Cleaner output of `wp_head` and enqueued assets +* Load jQuery from the jQuery CDN +* Cleaner WordPress markup * Cleaner HTML output of navigation menus * Root relative URLs -* Nice search (`/search/query/`) -* Google CDN jQuery snippet from [HTML5 Boilerplate](http://html5boilerplate.com/) +* Nice search * Google Analytics snippet from [HTML5 Boilerplate](http://html5boilerplate.com/) +* Move all JS to the footer +* Disable trackbacks and pingbacks See a complete working example in the [roots-example-project.com repo](https://github.com/roots/roots-example-project.com). +## Requirements + +Make sure all dependencies have been installed before moving on: + +* [PHP](http://php.net/manual/en/install.php) >= 5.5.x +* [Composer](https://getcomposer.org/download/) +* [Node.js](http://nodejs.org/) >= 0.12.x + ## Theme installation -Bottom line is you want to get the files in this repo into your local development environment. There are many ways to do this, two of which we will cover here. +From the command line, run the following commands from the root of your WordPress site (where `composer.json` exists). These instructions assume you're using a [Bedrock](https://roots.io/bedrock/)-based WordPress setup. If you're using Vagrant, make sure to run these commands from the Vagrant box (`vagrant ssh`). Create a new theme based on Sage by using Composer's [`create-project`](https://getcomposer.org/doc/03-cli.md#create-project): -### via Command-line - -If you're already [using Composer to manage WordPress](https://roots.io/using-composer-with-wordpress/), then you might consider using composer's `create-project` command to download Sage. - -The example below assumes you're using Bedrock. If you're not, simply change the target path accordingly. - -```sh -composer create-project roots/sage web/app/themes/your-theme-name-here +```shell +# @ example.com/site +$ composer create-project roots/sage web/app/themes/your-theme-name dev-sage-9 ``` -Then activate the theme via [wp-cli](http://wp-cli.org/commands/theme/activate/). +Then activate the theme via [wp-cli](http://wp-cli.org/commands/theme/activate/): -```sh -wp theme activate your-theme-name-here +```shell +# @ example.com/site +$ wp theme activate your-theme-name ``` -### via WordPress Admin Panel +## Theme structure -1. [Download the latest release](https://github.com/roots/sage/releases/latest) of Sage. -2. In your WordPress admin panel, navigate to Appearance->Themes -3. Click Add New -4. Click Upload Theme -5. Upload the zip file that you downloaded. +```shell +themes/theme-name/ # → Root of your Sage based theme +├── assets # → Front-end assets +│   ├── config.json # → Settings for compiled assets +│   ├── fonts/ # → Theme fonts +│   ├── images/ # → Theme images +│   ├── scripts/ # → Theme JS +│   └── styles/ # → Theme stylesheets +├── composer.json # → Autoloading for `src/` files +├── composer.lock # → Composer lock file (never manually edit) +├── dist/ # → Built theme assets (never manually edit) +├── functions.php # → Never manually edit +├── index.php # → Never manually edit +├── node_modules/ # → Node.js packages (never manually edit) +├── package.json # → Node.js dependencies and scripts +├── screenshot.png # → Theme screenshot for WP admin +├── src/ # → Theme PHP +├── style.css # → Theme meta information +├── templates/ # → Theme templates +│   ├── layouts/ # → Base templates +│   └── partials/ # → Partial templates +├── vendor/ # → Composer packages (never manually edit) +├── watch.js # → Webpack/BrowserSync watch config +└── webpack.config.js # → Webpack config +``` ## Theme setup -Edit `lib/setup.php` to enable or disable theme features, setup navigation menus, post thumbnail sizes, post formats, and sidebars. +Edit `src/lib/setup.php` to enable or disable theme features, setup navigation menus, post thumbnail sizes, post formats, and sidebars. ## Theme development -Sage uses [gulp](http://gulpjs.com/) as its build system and [Bower](http://bower.io/) to manage front-end packages. +Sage uses [Webpack](https://webpack.github.io/) as a build tool and [npm](https://www.npmjs.com/) to manage front-end packages. -### Install gulp and Bower +### Install dependencies -Building the theme requires [node.js](http://nodejs.org/download/). We recommend you update to the latest version of npm: `npm install -g npm@latest`. +From the command line on your host machine (not on your Vagrant development box), navigate to the theme directory then run `npm install`: -From the command line: - -1. Install [gulp](http://gulpjs.com) and [Bower](http://bower.io/) globally with `npm install -g gulp bower` -2. Navigate to the theme directory, then run `npm install` -3. Run `bower install` +```shell +# @ example.com/site/web/app/themes/your-theme-name +$ npm install +``` You now have all the necessary dependencies to run the build process. -### Available gulp commands +### Available build commands -* `gulp` — Compile and optimize the files in your assets directory -* `gulp watch` — Compile assets when file changes are made -* `gulp --production` — Compile assets for production (no source maps). +* `npm run build` — Compile and optimize the files in your assets directory +* `npm run watch` — Compile assets when file changes are made, start BrowerSync session +* `npm run build:production` — Compile assets for production ### Using BrowserSync -To use BrowserSync during `gulp watch` you need to update `devUrl` at the bottom of `assets/manifest.json` to reflect your local development hostname. +To use BrowserSync during `npm watch` you need to update `devUrl` at the bottom of `assets/config.json` to reflect your local development hostname. -For example, if your local development URL is `http://project-name.dev` you would update the file to read: +For example, if your local development URL is `https://project-name.dev` you would update the file to read: ```json ... - "config": { - "devUrl": "http://project-name.dev" - } -... -``` -If your local development URL looks like `http://localhost:8888/project-name/` you would update the file to read: -```json -... - "config": { - "devUrl": "http://localhost:8888/project-name/" - } + "devUrl": "https://project-name.dev", ... ``` diff --git a/assets/config.json b/assets/config.json new file mode 100644 index 0000000..a6edc97 --- /dev/null +++ b/assets/config.json @@ -0,0 +1,14 @@ +{ + "entry": { + "main": [ + "./scripts/util/public-path.js", + "./scripts/main.js", + "./styles/main.scss" + ], + "customizer": [ + "./scripts/customizer.js" + ] + }, + "publicPath": "/app/themes/sage", + "devUrl": "http://example.dev" +} diff --git a/assets/manifest.json b/assets/manifest.json deleted file mode 100644 index aca495c..0000000 --- a/assets/manifest.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "dependencies": { - "main.js": { - "files": [ - "scripts/main.js" - ], - "main": true - }, - "main.css": { - "files": [ - "styles/main.scss" - ], - "main": true - }, - "customizer.js": { - "files": [ - "scripts/customizer.js" - ] - }, - "jquery.js": { - "bower": ["jquery"] - } - }, - "config": { - "devUrl": "http://example.dev" - } -} diff --git a/assets/scripts/customizer.js b/assets/scripts/customizer.js index 76e3b56..5f97349 100644 --- a/assets/scripts/customizer.js +++ b/assets/scripts/customizer.js @@ -1,8 +1,5 @@ -(function($) { - // Site title - wp.customize('blogname', function(value) { - value.bind(function(to) { - $('.brand').text(to); - }); - }); -})(jQuery); +import $ from 'jquery'; + +wp.customize('blogname', (value) => { + value.bind((to) => $('.brand').text(to)) +}); diff --git a/assets/scripts/main.js b/assets/scripts/main.js index 53062de..48e9a3f 100644 --- a/assets/scripts/main.js +++ b/assets/scripts/main.js @@ -1,77 +1,23 @@ -/* ======================================================================== - * DOM-based Routing - * Based on http://goo.gl/EUTi53 by Paul Irish - * - * Only fires on body classes that match. If a body class contains a dash, - * replace the dash with an underscore when adding it to the object below. - * - * .noConflict() - * The routing is enclosed within an anonymous function so that you can - * always reference jQuery with $, even when in .noConflict() mode. - * ======================================================================== */ +// import external dependencies +import 'jquery' +import 'bootstrap/dist/js/bootstrap' -(function($) { +// import local dependencies +import Router from './util/router'; +import common from './routes/Common'; +import home from './routes/Home'; +import about_us from './routes/About'; - // Use this variable to set up the common and page specific functions. If you - // rename this variable, you will also need to rename the namespace below. - var Sage = { - // All pages - 'common': { - init: function() { - // JavaScript to be fired on all pages - }, - finalize: function() { - // JavaScript to be fired on all pages, after page specific JS is fired - } - }, - // Home page - 'home': { - init: function() { - // JavaScript to be fired on the home page - }, - finalize: function() { - // JavaScript to be fired on the home page, after the init JS - } - }, - // About us page, note the change from about-us to about_us. - 'about_us': { - init: function() { - // JavaScript to be fired on the about us page - } - } - }; +// Use this variable to set up the common and page specific functions. If you +// rename this variable, you will also need to rename the namespace below. +const routes = { + // All pages + common, + // Home page + home, + // About us page, note the change from about-us to about_us. + about_us +}; - // The routing fires all common scripts, followed by the page specific scripts. - // Add additional events for more control over timing e.g. a finalize event - var UTIL = { - fire: function(func, funcname, args) { - var fire; - var namespace = Sage; - funcname = (funcname === undefined) ? 'init' : funcname; - fire = func !== ''; - fire = fire && namespace[func]; - fire = fire && typeof namespace[func][funcname] === 'function'; - - if (fire) { - namespace[func][funcname](args); - } - }, - loadEvents: function() { - // Fire common init JS - UTIL.fire('common'); - - // Fire page-specific init JS, and then finalize JS - $.each(document.body.className.replace(/-/g, '_').split(/\s+/), function(i, classnm) { - UTIL.fire(classnm); - UTIL.fire(classnm, 'finalize'); - }); - - // Fire common finalize JS - UTIL.fire('common', 'finalize'); - } - }; - - // Load Events - $(document).ready(UTIL.loadEvents); - -})(jQuery); // Fully reference jQuery after this point. +// Load Events +$(document).ready(() => new Router(routes).loadEvents()); diff --git a/assets/scripts/routes/About.js b/assets/scripts/routes/About.js new file mode 100644 index 0000000..d9ab68a --- /dev/null +++ b/assets/scripts/routes/About.js @@ -0,0 +1,5 @@ +export default { + init() { + // JavaScript to be fired on the about us page + } +}; diff --git a/assets/scripts/routes/Common.js b/assets/scripts/routes/Common.js new file mode 100644 index 0000000..bc13db8 --- /dev/null +++ b/assets/scripts/routes/Common.js @@ -0,0 +1,8 @@ +export default { + init() { + // JavaScript to be fired on all pages + }, + finalize() { + // JavaScript to be fired on all pages, after page specific JS is fired + } +}; diff --git a/assets/scripts/routes/Home.js b/assets/scripts/routes/Home.js new file mode 100644 index 0000000..766017b --- /dev/null +++ b/assets/scripts/routes/Home.js @@ -0,0 +1,8 @@ +export default { + init() { + // JavaScript to be fired on the home page + }, + finalize() { + // JavaScript to be fired on the home page, after the init JS + } +}; diff --git a/assets/scripts/util/public-path.js b/assets/scripts/util/public-path.js new file mode 100644 index 0000000..af588c2 --- /dev/null +++ b/assets/scripts/util/public-path.js @@ -0,0 +1,8 @@ +/* globals WEBPACK_PUBLIC_PATH */ + +// Dynamically set absolute public path from current protocol and host +if (WEBPACK_PUBLIC_PATH !== false) { + /* eslint-disable no-undef */ + __webpack_public_path__ = location.protocol + '//' + location.host + WEBPACK_PUBLIC_PATH; + /*eslint-enable no-undef*/ +} diff --git a/assets/scripts/util/router.js b/assets/scripts/util/router.js new file mode 100644 index 0000000..bfb444c --- /dev/null +++ b/assets/scripts/util/router.js @@ -0,0 +1,36 @@ +/* ======================================================================== + * DOM-based Routing + * Based on http://goo.gl/EUTi53 by Paul Irish + * + * Only fires on body classes that match. If a body class contains a dash, + * replace the dash with an underscore when adding it to the object below. + * ======================================================================== */ + +// The routing fires all common scripts, followed by the page specific scripts. +// Add additional events for more control over timing e.g. a finalize event +export default class Router { + constructor(routes) { + this.routes = routes; + } + + fire(route, fn = 'init', args) { + const fire = route !== '' && this.routes[route] && typeof this.routes[route][fn] === 'function'; + if (fire) { + this.routes[route][fn](args); + } + } + + loadEvents() { + // Fire common init JS + this.fire('common'); + + // Fire page-specific init JS, and then finalize JS + document.body.className.replace(/-/g, '_').split(/\s+/).forEach((className) => { + this.fire(className); + this.fire(className, 'finalize'); + }); + + // Fire common finalize JS + this.fire('common', 'finalize'); + } +} diff --git a/assets/styles/common/_variables.scss b/assets/styles/common/_variables.scss index 7a0eb40..72048e1 100644 --- a/assets/styles/common/_variables.scss +++ b/assets/styles/common/_variables.scss @@ -1,9 +1,10 @@ -// Glyphicons font path -$icon-font-path: "../fonts/"; - // Grid settings +$enable-flex: true; $main-sm-columns: 12; $sidebar-sm-columns: 4; // Colors $brand-primary: #27ae60; + +// Font Awesome | see: http://fontawesome.io/get-started/ +$fa-font-path: '~font-awesome/fonts'; diff --git a/assets/styles/components/_comments.scss b/assets/styles/components/_comments.scss index 29ec32c..e007fe6 100644 --- a/assets/styles/components/_comments.scss +++ b/assets/styles/components/_comments.scss @@ -1,5 +1,5 @@ .comment-list { - @include list-unstyled; + @extend .list-unstyled; } .comment-list ol { list-style: none; @@ -15,5 +15,5 @@ } .comment-form input[type="submit"] { @extend .btn; - @extend .btn-primary; + @extend .btn-secondary; } diff --git a/assets/styles/components/_forms.scss b/assets/styles/components/_forms.scss index 19dc33e..0d619bf 100644 --- a/assets/styles/components/_forms.scss +++ b/assets/styles/components/_forms.scss @@ -11,5 +11,5 @@ } .search-form .search-submit { @extend .btn; - @extend .btn-default; + @extend .btn-secondary; } diff --git a/assets/styles/components/_grid.scss b/assets/styles/components/_grid.scss index b6e5199..f5d1687 100644 --- a/assets/styles/components/_grid.scss +++ b/assets/styles/components/_grid.scss @@ -1,10 +1,16 @@ // Grid system .main { - @include make-sm-column($main-sm-columns); - .sidebar-primary & { - @include make-sm-column($main-sm-columns - $sidebar-sm-columns); + @extend %grid-column; + @include media-breakpoint-up(sm) { + @include make-col($main-sm-columns); + .sidebar-primary & { + @include make-col($main-sm-columns - $sidebar-sm-columns); + } } } .sidebar { - @include make-sm-column($sidebar-sm-columns); + @extend %grid-column; + @include media-breakpoint-up(sm) { + @include make-col($sidebar-sm-columns); + } } diff --git a/assets/styles/components/_wp-classes.scss b/assets/styles/components/_wp-classes.scss index edbb835..0cbbcaa 100644 --- a/assets/styles/components/_wp-classes.scss +++ b/assets/styles/components/_wp-classes.scss @@ -10,32 +10,33 @@ } .aligncenter { display: block; - margin: ($line-height-computed / 2) auto; + margin: ($spacer / 2) auto; height: auto; } .alignleft, .alignright { - margin-bottom: ($line-height-computed / 2); + margin-bottom: ($spacer / 2); height: auto; } -@media (min-width: $screen-sm-min) { +@include media-breakpoint-up(sm) { // Only float if not on an extra small device .alignleft { float: left; - margin-right: ($line-height-computed / 2); + margin-right: ($spacer / 2); } .alignright { float: right; - margin-left: ($line-height-computed / 2); + margin-left: ($spacer / 2); } } // Captions .wp-caption { - @extend .thumbnail; + @extend .figure-img; + @extend .img-fluid; } .wp-caption-text { - padding: $thumbnail-caption-padding; + @extend .figure-caption; } // Text meant only for screen readers diff --git a/assets/styles/layouts/_header.scss b/assets/styles/layouts/_header.scss index e69de29..2ad1956 100644 --- a/assets/styles/layouts/_header.scss +++ b/assets/styles/layouts/_header.scss @@ -0,0 +1,6 @@ +.banner .nav li { + @extend .nav-item; +} +.banner .nav a { + @extend .nav-link; +} diff --git a/assets/styles/main.scss b/assets/styles/main.scss index cecbd4b..d2e5cbc 100644 --- a/assets/styles/main.scss +++ b/assets/styles/main.scss @@ -1,9 +1,8 @@ @import "common/variables"; -// Automatically injected Bower dependencies via wiredep (never manually edit this block) -// bower:scss -@import "../../bower_components/bootstrap-sass/assets/stylesheets/_bootstrap.scss"; -// endbower +// Import npm dependencies +@import "~bootstrap/scss/bootstrap"; +@import "~font-awesome/scss/font-awesome"; @import "common/global"; @import "components/buttons"; diff --git a/bower.json b/bower.json deleted file mode 100644 index 72132a8..0000000 --- a/bower.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "sage", - "homepage": "https://roots.io/sage/", - "authors": [ - "Ben Word " - ], - "license": "MIT", - "private": true, - "dependencies": { - "bootstrap-sass": "3.3.6" - }, - "overrides": { - "bootstrap-sass": { - "main": [ - "./assets/stylesheets/_bootstrap.scss", - "./assets/javascripts/bootstrap/transition.js", - "./assets/javascripts/bootstrap/alert.js", - "./assets/javascripts/bootstrap/button.js", - "./assets/javascripts/bootstrap/carousel.js", - "./assets/javascripts/bootstrap/collapse.js", - "./assets/javascripts/bootstrap/dropdown.js", - "./assets/javascripts/bootstrap/modal.js", - "./assets/javascripts/bootstrap/tooltip.js", - "./assets/javascripts/bootstrap/popover.js", - "./assets/javascripts/bootstrap/scrollspy.js", - "./assets/javascripts/bootstrap/tab.js", - "./assets/javascripts/bootstrap/affix.js", - "./assets/fonts/bootstrap/glyphicons-halflings-regular.eot", - "./assets/fonts/bootstrap/glyphicons-halflings-regular.svg", - "./assets/fonts/bootstrap/glyphicons-halflings-regular.ttf", - "./assets/fonts/bootstrap/glyphicons-halflings-regular.woff", - "./assets/fonts/bootstrap/glyphicons-halflings-regular.woff2" - ] - } - } -} diff --git a/composer.json b/composer.json index d9e6d58..83cf336 100644 --- a/composer.json +++ b/composer.json @@ -23,8 +23,23 @@ "issues": "https://github.com/roots/sage/issues", "forum": "https://discourse.roots.io/" }, + "autoload": { + "psr-4": { + "Roots\\Sage\\": "src/lib/Sage/" + } + }, "require": { - "php": ">=5.4.0", + "php": ">=5.5.0", "composer/installers": "~1.0" + }, + "require-dev": { + "squizlabs/php_codesniffer": "^2.5.1", + "phpmd/phpmd": "^2.4.2" + }, + "scripts": { + "test": [ + "vendor/bin/phpcs", + "vendor/bin/phpmd src text cleancode,codesize,controversial,design,naming,unusedcode" + ] } -} \ No newline at end of file +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..6fae444 --- /dev/null +++ b/composer.lock @@ -0,0 +1,463 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "5f4d419852a5551e2b54ef851cab83b4", + "content-hash": "1ee82adf8a4565a48214e5686e6b3293", + "packages": [ + { + "name": "composer/installers", + "version": "v1.0.23", + "source": { + "type": "git", + "url": "https://github.com/composer/installers.git", + "reference": "6213d900e92647831f7a406d5c530ea1f3d4360e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/installers/zipball/6213d900e92647831f7a406d5c530ea1f3d4360e", + "reference": "6213d900e92647831f7a406d5c530ea1f3d4360e", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0" + }, + "replace": { + "roundcube/plugin-installer": "*", + "shama/baton": "*" + }, + "require-dev": { + "composer/composer": "1.0.*@dev", + "phpunit/phpunit": "4.1.*" + }, + "type": "composer-plugin", + "extra": { + "class": "Composer\\Installers\\Plugin", + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-0": { + "Composer\\Installers\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kyle Robinson Young", + "email": "kyle@dontkry.com", + "homepage": "https://github.com/shama" + } + ], + "description": "A multi-framework Composer library installer", + "homepage": "http://composer.github.com/installers/", + "keywords": [ + "Craft", + "Dolibarr", + "Hurad", + "MODX Evo", + "OXID", + "SMF", + "Thelia", + "WolfCMS", + "agl", + "aimeos", + "annotatecms", + "bitrix", + "cakephp", + "chef", + "codeigniter", + "concrete5", + "croogo", + "dokuwiki", + "drupal", + "elgg", + "fuelphp", + "grav", + "installer", + "joomla", + "kohana", + "laravel", + "lithium", + "magento", + "mako", + "mediawiki", + "modulework", + "moodle", + "phpbb", + "piwik", + "ppi", + "puppet", + "roundcube", + "shopware", + "silverstripe", + "symfony", + "typo3", + "wordpress", + "zend", + "zikula" + ], + "time": "2016-01-27 12:54:22" + } + ], + "packages-dev": [ + { + "name": "pdepend/pdepend", + "version": "2.2.4", + "source": { + "type": "git", + "url": "https://github.com/pdepend/pdepend.git", + "reference": "b086687f3a01dc6bb92d633aef071d2c5dd0db06" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pdepend/pdepend/zipball/b086687f3a01dc6bb92d633aef071d2c5dd0db06", + "reference": "b086687f3a01dc6bb92d633aef071d2c5dd0db06", + "shasum": "" + }, + "require": { + "php": ">=5.3.7", + "symfony/config": "^2.3.0|^3", + "symfony/dependency-injection": "^2.3.0|^3", + "symfony/filesystem": "^2.3.0|^3" + }, + "require-dev": { + "phpunit/phpunit": "^4.4.0,<4.8", + "squizlabs/php_codesniffer": "^2.0.0" + }, + "bin": [ + "src/bin/pdepend" + ], + "type": "library", + "autoload": { + "psr-4": { + "PDepend\\": "src/main/php/PDepend" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Official version of pdepend to be handled with Composer", + "time": "2016-03-10 15:15:04" + }, + { + "name": "phpmd/phpmd", + "version": "2.4.2", + "source": { + "type": "git", + "url": "https://github.com/phpmd/phpmd.git", + "reference": "fccbdb6b222f6d7a6d35af1c396ba5435cec76a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpmd/phpmd/zipball/fccbdb6b222f6d7a6d35af1c396ba5435cec76a9", + "reference": "fccbdb6b222f6d7a6d35af1c396ba5435cec76a9", + "shasum": "" + }, + "require": { + "pdepend/pdepend": "~2.0", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0", + "squizlabs/php_codesniffer": "^2.0" + }, + "bin": [ + "src/bin/phpmd" + ], + "type": "project", + "autoload": { + "psr-0": { + "PHPMD\\": "src/main/php" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Manuel Pichler", + "email": "github@manuel-pichler.de", + "homepage": "https://github.com/manuelpichler", + "role": "Project Founder" + }, + { + "name": "Other contributors", + "homepage": "https://github.com/phpmd/phpmd/graphs/contributors", + "role": "Contributors" + }, + { + "name": "Marc Würth", + "email": "ravage@bluewin.ch", + "homepage": "https://github.com/ravage84", + "role": "Project Maintainer" + } + ], + "description": "PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD.", + "homepage": "http://phpmd.org/", + "keywords": [ + "mess detection", + "mess detector", + "pdepend", + "phpmd", + "pmd" + ], + "time": "2016-03-10 17:17:44" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "2.5.1", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "6731851d6aaf1d0d6c58feff1065227b7fda3ba8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/6731851d6aaf1d0d6c58feff1065227b7fda3ba8", + "reference": "6731851d6aaf1d0d6c58feff1065227b7fda3ba8", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "bin": [ + "scripts/phpcs", + "scripts/phpcbf" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "classmap": [ + "CodeSniffer.php", + "CodeSniffer/CLI.php", + "CodeSniffer/Exception.php", + "CodeSniffer/File.php", + "CodeSniffer/Fixer.php", + "CodeSniffer/Report.php", + "CodeSniffer/Reporting.php", + "CodeSniffer/Sniff.php", + "CodeSniffer/Tokens.php", + "CodeSniffer/Reports/", + "CodeSniffer/Tokenizers/", + "CodeSniffer/DocGenerators/", + "CodeSniffer/Standards/AbstractPatternSniff.php", + "CodeSniffer/Standards/AbstractScopeSniff.php", + "CodeSniffer/Standards/AbstractVariableSniff.php", + "CodeSniffer/Standards/IncorrectPatternException.php", + "CodeSniffer/Standards/Generic/Sniffs/", + "CodeSniffer/Standards/MySource/Sniffs/", + "CodeSniffer/Standards/PEAR/Sniffs/", + "CodeSniffer/Standards/PSR1/Sniffs/", + "CodeSniffer/Standards/PSR2/Sniffs/", + "CodeSniffer/Standards/Squiz/Sniffs/", + "CodeSniffer/Standards/Zend/Sniffs/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "http://www.squizlabs.com/php-codesniffer", + "keywords": [ + "phpcs", + "standards" + ], + "time": "2016-01-19 23:39:10" + }, + { + "name": "symfony/config", + "version": "v3.0.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/config.git", + "reference": "980ee40c28f00acff8906c11b778aab5f0db74c2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/config/zipball/980ee40c28f00acff8906c11b778aab5f0db74c2", + "reference": "980ee40c28f00acff8906c11b778aab5f0db74c2", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "symfony/filesystem": "~2.8|~3.0" + }, + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Config\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Config Component", + "homepage": "https://symfony.com", + "time": "2016-03-04 07:55:57" + }, + { + "name": "symfony/dependency-injection", + "version": "v3.0.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/dependency-injection.git", + "reference": "6a9058101b591edced21ca3c83c80a3978f5c6b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/6a9058101b591edced21ca3c83c80a3978f5c6b0", + "reference": "6a9058101b591edced21ca3c83c80a3978f5c6b0", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "require-dev": { + "symfony/config": "~2.8|~3.0", + "symfony/expression-language": "~2.8|~3.0", + "symfony/yaml": "~2.8|~3.0" + }, + "suggest": { + "symfony/config": "", + "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\DependencyInjection\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DependencyInjection Component", + "homepage": "https://symfony.com", + "time": "2016-03-30 10:41:14" + }, + { + "name": "symfony/filesystem", + "version": "v3.0.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "f82499a459dcade2ea56df94cc58b19c8bde3d20" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/f82499a459dcade2ea56df94cc58b19c8bde3d20", + "reference": "f82499a459dcade2ea56df94cc58b19c8bde3d20", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Filesystem Component", + "homepage": "https://symfony.com", + "time": "2016-03-27 10:24:39" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=5.5.0" + }, + "platform-dev": [] +} diff --git a/functions.php b/functions.php index 35df8db..1504906 100644 --- a/functions.php +++ b/functions.php @@ -1,4 +1,42 @@ type === 'themes') { + $section->title = wp_get_theme(basename(__DIR__))->display('Name'); + } +}, 10, 2); + /** * Sage includes * @@ -6,23 +44,15 @@ * Add or remove files to the array as needed. Supports child theme overrides. * * Please note that missing files will produce a fatal error. - * - * @link https://github.com/roots/sage/pull/1042 */ $sage_includes = [ - 'lib/assets.php', // Scripts and stylesheets - 'lib/extras.php', // Custom functions - 'lib/setup.php', // Theme setup - 'lib/titles.php', // Page titles - 'lib/wrapper.php', // Theme wrapper class - 'lib/customizer.php' // Theme customizer + 'src/helpers.php', // Helper functions + 'src/setup.php', // Theme setup + 'src/filters.php', // Filters + 'src/admin.php' // Admin ]; - -foreach ($sage_includes as $file) { - if (!$filepath = locate_template($file)) { - trigger_error(sprintf(__('Error locating %s for inclusion', 'sage'), $file), E_USER_ERROR); - } - - require_once $filepath; -} -unset($file, $filepath); +array_walk($sage_includes, function ($file) { + if (!locate_template($file, true, true)) { + trigger_error(sprintf(__('Error locating %s for inclusion', 'sage'), $file), E_USER_ERROR); + } +}); diff --git a/gulpfile.js b/gulpfile.js deleted file mode 100644 index 3556bdd..0000000 --- a/gulpfile.js +++ /dev/null @@ -1,288 +0,0 @@ -// ## Globals -var argv = require('minimist')(process.argv.slice(2)); -var autoprefixer = require('gulp-autoprefixer'); -var browserSync = require('browser-sync').create(); -var changed = require('gulp-changed'); -var concat = require('gulp-concat'); -var flatten = require('gulp-flatten'); -var gulp = require('gulp'); -var gulpif = require('gulp-if'); -var imagemin = require('gulp-imagemin'); -var jshint = require('gulp-jshint'); -var lazypipe = require('lazypipe'); -var less = require('gulp-less'); -var merge = require('merge-stream'); -var cssNano = require('gulp-cssnano'); -var plumber = require('gulp-plumber'); -var rev = require('gulp-rev'); -var runSequence = require('run-sequence'); -var sass = require('gulp-sass'); -var sourcemaps = require('gulp-sourcemaps'); -var uglify = require('gulp-uglify'); - -// See https://github.com/austinpray/asset-builder -var manifest = require('asset-builder')('./assets/manifest.json'); - -// `path` - Paths to base asset directories. With trailing slashes. -// - `path.source` - Path to the source files. Default: `assets/` -// - `path.dist` - Path to the build directory. Default: `dist/` -var path = manifest.paths; - -// `config` - Store arbitrary configuration values here. -var config = manifest.config || {}; - -// `globs` - These ultimately end up in their respective `gulp.src`. -// - `globs.js` - Array of asset-builder JS dependency objects. Example: -// ``` -// {type: 'js', name: 'main.js', globs: []} -// ``` -// - `globs.css` - Array of asset-builder CSS dependency objects. Example: -// ``` -// {type: 'css', name: 'main.css', globs: []} -// ``` -// - `globs.fonts` - Array of font path globs. -// - `globs.images` - Array of image path globs. -// - `globs.bower` - Array of all the main Bower files. -var globs = manifest.globs; - -// `project` - paths to first-party assets. -// - `project.js` - Array of first-party JS assets. -// - `project.css` - Array of first-party CSS assets. -var project = manifest.getProjectGlobs(); - -// CLI options -var enabled = { - // Enable static asset revisioning when `--production` - rev: argv.production, - // Disable source maps when `--production` - maps: !argv.production, - // Fail styles task on error when `--production` - failStyleTask: argv.production, - // Fail due to JSHint warnings only when `--production` - failJSHint: argv.production, - // Strip debug statments from javascript when `--production` - stripJSDebug: argv.production -}; - -// Path to the compiled assets manifest in the dist directory -var revManifest = path.dist + 'assets.json'; - -// ## Reusable Pipelines -// See https://github.com/OverZealous/lazypipe - -// ### CSS processing pipeline -// Example -// ``` -// gulp.src(cssFiles) -// .pipe(cssTasks('main.css') -// .pipe(gulp.dest(path.dist + 'styles')) -// ``` -var cssTasks = function(filename) { - return lazypipe() - .pipe(function() { - return gulpif(!enabled.failStyleTask, plumber()); - }) - .pipe(function() { - return gulpif(enabled.maps, sourcemaps.init()); - }) - .pipe(function() { - return gulpif('*.less', less()); - }) - .pipe(function() { - return gulpif('*.scss', sass({ - outputStyle: 'nested', // libsass doesn't support expanded yet - precision: 10, - includePaths: ['.'], - errLogToConsole: !enabled.failStyleTask - })); - }) - .pipe(concat, filename) - .pipe(autoprefixer, { - browsers: [ - 'last 2 versions', - 'android 4', - 'opera 12' - ] - }) - .pipe(cssNano, { - safe: true - }) - .pipe(function() { - return gulpif(enabled.rev, rev()); - }) - .pipe(function() { - return gulpif(enabled.maps, sourcemaps.write('.', { - sourceRoot: 'assets/styles/' - })); - })(); -}; - -// ### JS processing pipeline -// Example -// ``` -// gulp.src(jsFiles) -// .pipe(jsTasks('main.js') -// .pipe(gulp.dest(path.dist + 'scripts')) -// ``` -var jsTasks = function(filename) { - return lazypipe() - .pipe(function() { - return gulpif(enabled.maps, sourcemaps.init()); - }) - .pipe(concat, filename) - .pipe(uglify, { - compress: { - 'drop_debugger': enabled.stripJSDebug - } - }) - .pipe(function() { - return gulpif(enabled.rev, rev()); - }) - .pipe(function() { - return gulpif(enabled.maps, sourcemaps.write('.', { - sourceRoot: 'assets/scripts/' - })); - })(); -}; - -// ### Write to rev manifest -// If there are any revved files then write them to the rev manifest. -// See https://github.com/sindresorhus/gulp-rev -var writeToManifest = function(directory) { - return lazypipe() - .pipe(gulp.dest, path.dist + directory) - .pipe(browserSync.stream, {match: '**/*.{js,css}'}) - .pipe(rev.manifest, revManifest, { - base: path.dist, - merge: true - }) - .pipe(gulp.dest, path.dist)(); -}; - -// ## Gulp tasks -// Run `gulp -T` for a task summary - -// ### Styles -// `gulp styles` - Compiles, combines, and optimizes Bower CSS and project CSS. -// By default this task will only log a warning if a precompiler error is -// raised. If the `--production` flag is set: this task will fail outright. -gulp.task('styles', ['wiredep'], function() { - var merged = merge(); - manifest.forEachDependency('css', function(dep) { - var cssTasksInstance = cssTasks(dep.name); - if (!enabled.failStyleTask) { - cssTasksInstance.on('error', function(err) { - console.error(err.message); - this.emit('end'); - }); - } - merged.add(gulp.src(dep.globs, {base: 'styles'}) - .pipe(cssTasksInstance)); - }); - return merged - .pipe(writeToManifest('styles')); -}); - -// ### Scripts -// `gulp scripts` - Runs JSHint then compiles, combines, and optimizes Bower JS -// and project JS. -gulp.task('scripts', ['jshint'], function() { - var merged = merge(); - manifest.forEachDependency('js', function(dep) { - merged.add( - gulp.src(dep.globs, {base: 'scripts'}) - .pipe(jsTasks(dep.name)) - ); - }); - return merged - .pipe(writeToManifest('scripts')); -}); - -// ### Fonts -// `gulp fonts` - Grabs all the fonts and outputs them in a flattened directory -// structure. See: https://github.com/armed/gulp-flatten -gulp.task('fonts', function() { - return gulp.src(globs.fonts) - .pipe(flatten()) - .pipe(gulp.dest(path.dist + 'fonts')) - .pipe(browserSync.stream()); -}); - -// ### Images -// `gulp images` - Run lossless compression on all the images. -gulp.task('images', function() { - return gulp.src(globs.images) - .pipe(imagemin({ - progressive: true, - interlaced: true, - svgoPlugins: [{removeUnknownsAndDefaults: false}, {cleanupIDs: false}] - })) - .pipe(gulp.dest(path.dist + 'images')) - .pipe(browserSync.stream()); -}); - -// ### JSHint -// `gulp jshint` - Lints configuration JSON and project JS. -gulp.task('jshint', function() { - return gulp.src([ - 'bower.json', 'gulpfile.js' - ].concat(project.js)) - .pipe(jshint()) - .pipe(jshint.reporter('jshint-stylish')) - .pipe(gulpif(enabled.failJSHint, jshint.reporter('fail'))); -}); - -// ### Clean -// `gulp clean` - Deletes the build folder entirely. -gulp.task('clean', require('del').bind(null, [path.dist])); - -// ### Watch -// `gulp watch` - Use BrowserSync to proxy your dev server and synchronize code -// changes across devices. Specify the hostname of your dev server at -// `manifest.config.devUrl`. When a modification is made to an asset, run the -// build step for that asset and inject the changes into the page. -// See: http://www.browsersync.io -gulp.task('watch', function() { - browserSync.init({ - files: ['{lib,templates}/**/*.php', '*.php'], - proxy: config.devUrl, - snippetOptions: { - whitelist: ['/wp-admin/admin-ajax.php'], - blacklist: ['/wp-admin/**'] - } - }); - gulp.watch([path.source + 'styles/**/*'], ['styles']); - gulp.watch([path.source + 'scripts/**/*'], ['jshint', 'scripts']); - gulp.watch([path.source + 'fonts/**/*'], ['fonts']); - gulp.watch([path.source + 'images/**/*'], ['images']); - gulp.watch(['bower.json', 'assets/manifest.json'], ['build']); -}); - -// ### Build -// `gulp build` - Run all the build tasks but don't clean up beforehand. -// Generally you should be running `gulp` instead of `gulp build`. -gulp.task('build', function(callback) { - runSequence('styles', - 'scripts', - ['fonts', 'images'], - callback); -}); - -// ### Wiredep -// `gulp wiredep` - Automatically inject Less and Sass Bower dependencies. See -// https://github.com/taptapship/wiredep -gulp.task('wiredep', function() { - var wiredep = require('wiredep').stream; - return gulp.src(project.css) - .pipe(wiredep()) - .pipe(changed(path.source + 'styles', { - hasChanged: changed.compareSha1Digest - })) - .pipe(gulp.dest(path.source + 'styles')); -}); - -// ### Gulp -// `gulp` - Run a complete build. To compile for production run `gulp --production`. -gulp.task('default', ['clean'], function() { - gulp.start('build'); -}); diff --git a/index.php b/index.php index 710ac42..452d62d 100644 --- a/index.php +++ b/index.php @@ -1,14 +1,6 @@ - + -
- -
- - - - - - - - +if (defined('ABSPATH')) { + update_option('template', get_option('template') . '/templates'); +} +die("Kind Regards,\nRoots"); diff --git a/lang/sage.pot b/lang/sage.pot deleted file mode 100644 index 1ee2a85..0000000 --- a/lang/sage.pot +++ /dev/null @@ -1,103 +0,0 @@ -msgid "" -msgstr "" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: 404.php:4 -msgid "Sorry, but the page you were trying to view does not exist." -msgstr "" - -#: base.php:14 -msgid "" -"You are using an outdated browser. Please upgrade your browser to improve your experience." -msgstr "" - -#: functions.php:22 -msgid "Error locating %s for inclusion" -msgstr "" - -#: index.php:5 search.php:5 -msgid "Sorry, no results were found." -msgstr "" - -#: lib/extras.php:31 -msgid "Continued" -msgstr "" - -#: lib/setup.php:30 -msgid "Primary Navigation" -msgstr "" - -#: lib/setup.php:57 -msgid "Primary" -msgstr "" - -#: lib/setup.php:66 -msgid "Footer" -msgstr "" - -#: lib/titles.php:13 -msgid "Latest Posts" -msgstr "" - -#: lib/titles.php:18 -msgid "Search Results for %s" -msgstr "" - -#: lib/titles.php:20 -msgid "Not Found" -msgstr "" - -#: templates/comments.php:9 -msgctxt "comments title" -msgid "One response to “%2$s”" -msgid_plural "%1$s responses to “%2$s”" -msgstr[0] "" -msgstr[1] "" - -#: templates/comments.php:19 -msgid "← Older comments" -msgstr "" - -#: templates/comments.php:22 -msgid "Newer comments →" -msgstr "" - -#: templates/comments.php:31 -msgid "Comments are closed." -msgstr "" - -#: templates/content-page.php:2 templates/content-single.php:11 -msgid "Pages:" -msgstr "" - -#: templates/entry-meta.php:2 -msgid "By" -msgstr "" - -#. Theme Name of the plugin/theme -msgid "Sage Starter Theme" -msgstr "" - -#. Theme URI of the plugin/theme -msgid "https://roots.io/sage/" -msgstr "" - -#. Description of the plugin/theme -msgid "" -"Sage is a WordPress starter theme. Contribute on GitHub" -msgstr "" - -#. Author of the plugin/theme -msgid "Roots" -msgstr "" - -#. Author URI of the plugin/theme -msgid "https://roots.io/" -msgstr "" - -#. Template Name of the plugin/theme -msgid "Custom Template" -msgstr "" diff --git a/lib/assets.php b/lib/assets.php deleted file mode 100644 index fba751c..0000000 --- a/lib/assets.php +++ /dev/null @@ -1,58 +0,0 @@ -manifest = json_decode(file_get_contents($manifest_path), true); - } else { - $this->manifest = []; - } - } - - public function get() { - return $this->manifest; - } - - public function getPath($key = '', $default = null) { - $collection = $this->manifest; - if (is_null($key)) { - return $collection; - } - if (isset($collection[$key])) { - return $collection[$key]; - } - foreach (explode('.', $key) as $segment) { - if (!isset($collection[$segment])) { - return $default; - } else { - $collection = $collection[$segment]; - } - } - return $collection; - } -} - -function asset_path($filename) { - $dist_path = get_template_directory_uri() . '/dist/'; - $directory = dirname($filename) . '/'; - $file = basename($filename); - static $manifest; - - if (empty($manifest)) { - $manifest_path = get_template_directory() . '/dist/' . 'assets.json'; - $manifest = new JsonManifest($manifest_path); - } - - if (array_key_exists($file, $manifest->get())) { - return $dist_path . $directory . $manifest->get()[$file]; - } else { - return $dist_path . $directory . $file; - } -} diff --git a/lib/customizer.php b/lib/customizer.php deleted file mode 100644 index d0253f9..0000000 --- a/lib/customizer.php +++ /dev/null @@ -1,21 +0,0 @@ -get_setting('blogname')->transport = 'postMessage'; -} -add_action('customize_register', __NAMESPACE__ . '\\customize_register'); - -/** - * Customizer JS - */ -function customize_preview_js() { - wp_enqueue_script('sage/customizer', Assets\asset_path('scripts/customizer.js'), ['customize-preview'], null, true); -} -add_action('customize_preview_init', __NAMESPACE__ . '\\customize_preview_js'); diff --git a/lib/extras.php b/lib/extras.php deleted file mode 100644 index dc55156..0000000 --- a/lib/extras.php +++ /dev/null @@ -1,33 +0,0 @@ - classes - */ -function body_class($classes) { - // Add page slug if it doesn't exist - if (is_single() || is_page() && !is_front_page()) { - if (!in_array(basename(get_permalink()), $classes)) { - $classes[] = basename(get_permalink()); - } - } - - // Add class if sidebar is active - if (Setup\display_sidebar()) { - $classes[] = 'sidebar-primary'; - } - - return $classes; -} -add_filter('body_class', __NAMESPACE__ . '\\body_class'); - -/** - * Clean up the_excerpt() - */ -function excerpt_more() { - return ' … ' . __('Continued', 'sage') . ''; -} -add_filter('excerpt_more', __NAMESPACE__ . '\\excerpt_more'); diff --git a/lib/setup.php b/lib/setup.php deleted file mode 100644 index b9f962d..0000000 --- a/lib/setup.php +++ /dev/null @@ -1,106 +0,0 @@ - __('Primary Navigation', 'sage') - ]); - - // Enable post thumbnails - // http://codex.wordpress.org/Post_Thumbnails - // http://codex.wordpress.org/Function_Reference/set_post_thumbnail_size - // http://codex.wordpress.org/Function_Reference/add_image_size - add_theme_support('post-thumbnails'); - - // Enable post formats - // http://codex.wordpress.org/Post_Formats - add_theme_support('post-formats', ['aside', 'gallery', 'link', 'image', 'quote', 'video', 'audio']); - - // Enable HTML5 markup support - // http://codex.wordpress.org/Function_Reference/add_theme_support#HTML5 - add_theme_support('html5', ['caption', 'comment-form', 'comment-list', 'gallery', 'search-form']); - - // Use main stylesheet for visual editor - // To add custom styles edit /assets/styles/layouts/_tinymce.scss - add_editor_style(Assets\asset_path('styles/main.css')); -} -add_action('after_setup_theme', __NAMESPACE__ . '\\setup'); - -/** - * Register sidebars - */ -function widgets_init() { - register_sidebar([ - 'name' => __('Primary', 'sage'), - 'id' => 'sidebar-primary', - 'before_widget' => '
', - 'after_widget' => '
', - 'before_title' => '

', - 'after_title' => '

' - ]); - - register_sidebar([ - 'name' => __('Footer', 'sage'), - 'id' => 'sidebar-footer', - 'before_widget' => '
', - 'after_widget' => '
', - 'before_title' => '

', - 'after_title' => '

' - ]); -} -add_action('widgets_init', __NAMESPACE__ . '\\widgets_init'); - -/** - * Determine which pages should NOT display the sidebar - */ -function display_sidebar() { - static $display; - - isset($display) || $display = !in_array(true, [ - // The sidebar will NOT be displayed if ANY of the following return true. - // @link https://codex.wordpress.org/Conditional_Tags - is_404(), - is_front_page(), - is_page_template('template-custom.php'), - ]); - - return apply_filters('sage/display_sidebar', $display); -} - -/** - * Theme assets - */ -function assets() { - wp_enqueue_style('sage/css', Assets\asset_path('styles/main.css'), false, null); - - if (is_single() && comments_open() && get_option('thread_comments')) { - wp_enqueue_script('comment-reply'); - } - - wp_enqueue_script('sage/js', Assets\asset_path('scripts/main.js'), ['jquery'], null, true); -} -add_action('wp_enqueue_scripts', __NAMESPACE__ . '\\assets', 100); diff --git a/lib/titles.php b/lib/titles.php deleted file mode 100644 index cdabacd..0000000 --- a/lib/titles.php +++ /dev/null @@ -1,24 +0,0 @@ -slug = basename($template, '.php'); - $this->templates = [$template]; - - if (self::$base) { - $str = substr($template, 0, -4); - array_unshift($this->templates, sprintf($str . '-%s.php', self::$base)); - } - } - - public function __toString() { - $this->templates = apply_filters('sage/wrap_' . $this->slug, $this->templates); - return locate_template($this->templates); - } - - public static function wrap($main) { - // Check for other filters returning null - if (!is_string($main)) { - return $main; - } - - self::$main_template = $main; - self::$base = basename(self::$main_template, '.php'); - - if (self::$base === 'index') { - self::$base = false; - } - - return new SageWrapping(); - } -} -add_filter('template_include', [__NAMESPACE__ . '\\SageWrapping', 'wrap'], 109); diff --git a/package.json b/package.json index 9c38b10..adaf988 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,9 @@ + + { "name": "sage", - "version": "8.4.2", - "author": "Ben Word ", + "version": "9.0.0", + "author": "Roots ", "homepage": "https://roots.io/sage/", "private": true, "repository": { @@ -18,41 +20,55 @@ } ], "scripts": { - "build": "bower install && gulp", - "jshint": "gulp jshint", - "jscs": "jscs gulpfile.js assets/scripts/*.js" + "build:production": "webpack -p --progress --release", + "build": "webpack -d --progress", + "watch": "node watch.js --watch", + "lint": "eslint -c .eslintrc assets/scripts watch.js webpack.config.js" }, "engines": { - "node": ">= 0.12.0", - "npm": ">=2.1.5" + "node": ">=4" }, "devDependencies": { - "asset-builder": "^1.1.0", - "browser-sync": "^2.8.2", - "del": "^1.2.1", - "gulp": "^3.9.0", - "gulp-autoprefixer": "^2.3.1", - "gulp-changed": "^1.3.0", - "gulp-concat": "^2.6.0", - "gulp-cssnano": "^2.1.0", - "gulp-flatten": "0.1.1", - "gulp-if": "^2.0.1", - "gulp-imagemin": "^2.3.0", - "gulp-jshint": "^1.11.2", - "gulp-less": "^3.0.3", - "gulp-plumber": "^1.0.1", - "gulp-rename": "^1.2.2", - "gulp-rev": "^6.0.0", - "gulp-sass": "^2.0.1", - "gulp-sourcemaps": "^1.5.2", - "gulp-uglify": "^1.2.0", - "imagemin-pngcrush": "^4.1.0", - "jshint-stylish": "^2.0.1", - "lazypipe": "^1.0.1", - "merge-stream": "^1.0.0", - "minimist": "^1.1.3", - "run-sequence": "^1.1.2", - "traverse": "^0.6.6", - "wiredep": "^2.2.2" + "assets-webpack-plugin": "^3.4.0", + "autoprefixer": "^6.1.0", + "babel-cli": "^6.6.5", + "babel-core": "^6.7.4", + "babel-eslint": "^6.0.0", + "babel-loader": "^6.2.4", + "babel-preset-es2015": "^6.13.2", + "babel-register": "^6.5.2", + "babel-runtime": "^6.5.0", + "body-parser": "^1.14.1", + "browser-sync": "^2.11.2", + "clean-webpack-plugin": "^0.1.8", + "css-loader": "^0.23.1", + "cssnano": "^3.5.2", + "eslint": "^3.2.2", + "eslint-loader": "^1.3.0", + "eslint-plugin-react": "^6.0.0", + "extract-text-webpack-plugin": "^1.0.1", + "file-loader": "^0.9.0", + "image-webpack-loader": "^2.0.0", + "imagemin-pngcrush": "^5.0.0", + "imports-loader": "^0.6.5", + "minimist": "^1.2.0", + "monkey-hot-loader": "0.0.3", + "node-sass": "^3.4.2", + "optimize-css-assets-webpack-plugin": "^1.3.0", + "postcss": "^5.0.18", + "postcss-loader": "^0.9.1", + "qs": "^6.1.0", + "resolve-url-loader": "^1.4.3", + "sass-loader": "^4.0.0", + "style-loader": "^0.13.0", + "url-loader": "^0.5.7", + "webpack": "^1.12.14", + "webpack-dev-middleware": "^1.6", + "webpack-hot-middleware": "^2.10.0" + }, + "dependencies": { + "bootstrap": "github:twbs/bootstrap#v4-dev", + "font-awesome": "^4.6.3", + "jquery": "^1.12.4" } } diff --git a/page.php b/page.php deleted file mode 100644 index 6e55a0d..0000000 --- a/page.php +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/phpcs.xml b/phpcs.xml new file mode 100644 index 0000000..4b4b390 --- /dev/null +++ b/phpcs.xml @@ -0,0 +1,71 @@ + + + Roots Coding Standards + + + functions.php + index.php + src + templates + + + + + + + + + + + + + + + templates + + + + + templates + + + + + templates + + + + + templates + + + + + templates + + + + + templates + + + + + templates + + + + + templates + + + + + templates + + + + + templates + + diff --git a/ruleset.xml b/ruleset.xml deleted file mode 100644 index f0b7c0a..0000000 --- a/ruleset.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - Roots Coding Standards - - - - - - - - - - - - - - - - - - - - - - templates/* - - - - - templates/* - 404.php - index.php - page.php - single.php - template-custom.php - - - - - - - - - - - - - diff --git a/single.php b/single.php deleted file mode 100644 index 71b1840..0000000 --- a/single.php +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/admin.php b/src/admin.php new file mode 100644 index 0000000..863a6ce --- /dev/null +++ b/src/admin.php @@ -0,0 +1,16 @@ +get_setting('blogname')->transport = 'postMessage'; +}); + +/** + * Customizer JS + */ +add_action('customize_preview_init', function () { + wp_enqueue_script('sage/customizer.js', asset_path('scripts/customizer.js'), ['customize-preview'], null, true); +}); diff --git a/src/filters.php b/src/filters.php new file mode 100644 index 0000000..b5f1bf5 --- /dev/null +++ b/src/filters.php @@ -0,0 +1,53 @@ + classes + */ +add_filter('body_class', function (array $classes) { + // Add page slug if it doesn't exist + if (is_single() || is_page() && !is_front_page()) { + if (!in_array(basename(get_permalink()), $classes)) { + $classes[] = basename(get_permalink()); + } + } + + // Add class if sidebar is active + if (display_sidebar()) { + $classes[] = 'sidebar-primary'; + } + + return $classes; +}); + +/** + * Add "… Continued" to the excerpt + */ +add_filter('excerpt_more', function () { + return ' … ' . __('Continued', 'sage') . ''; +}); + +/** + * Use theme wrapper + */ +add_filter('template_include', function ($main) { + if (!is_string($main) && !(is_object($main) && method_exists($main, '__toString'))) { + return $main; + } + return ((new Template(new Wrapper($main)))->layout()); +}, 109); diff --git a/src/helpers.php b/src/helpers.php new file mode 100644 index 0000000..27461b8 --- /dev/null +++ b/src/helpers.php @@ -0,0 +1,62 @@ +partial($template); +} + +/** + * @param $filename + * @return string + */ +function asset_path($filename) +{ + static $manifest; + isset($manifest) || $manifest = new JsonManifest(get_template_directory() . '/' . Asset::$dist . '/assets.json'); + return (string) new Asset($filename, $manifest); +} + +/** + * Determine whether to show the sidebar + * @return bool + */ +function display_sidebar() +{ + static $display; + isset($display) || $display = apply_filters('sage/display_sidebar', true); + return $display; +} + +/** + * Page titles + * @return string + */ +function title() +{ + if (is_home()) { + if ($home = get_option('page_for_posts', true)) { + return get_the_title($home); + } + return __('Latest Posts', 'sage'); + } + if (is_archive()) { + return get_the_archive_title(); + } + if (is_search()) { + return sprintf(__('Search Results for %s', 'sage'), get_search_query()); + } + if (is_404()) { + return __('Not Found', 'sage'); + } + return get_the_title(); +} diff --git a/src/lib/Sage/Asset.php b/src/lib/Sage/Asset.php new file mode 100644 index 0000000..143fd7e --- /dev/null +++ b/src/lib/Sage/Asset.php @@ -0,0 +1,38 @@ +manifest = $manifest; + $this->asset = basename($file); + $this->dir = dirname($file) != '.' ? dirname($file) : ''; + } + + public function __toString() + { + return $this->getUri(); + } + + public function getUri() + { + $file = ($this->manifest ? $this->manifest->get($this->asset) : $this->asset); + return get_template_directory_uri() . self::$dist . '/' . $this->dir . '/' . $file; + } +} diff --git a/src/lib/Sage/Assets/JsonManifest.php b/src/lib/Sage/Assets/JsonManifest.php new file mode 100644 index 0000000..1ce3377 --- /dev/null +++ b/src/lib/Sage/Assets/JsonManifest.php @@ -0,0 +1,33 @@ +manifest = file_exists($manifestPath) ? json_decode(file_get_contents($manifestPath), true) : []; + } + + /** @inheritdoc */ + public function get($file) + { + return isset($this->manifest[$file]) ? $this->manifest[$file] : $file; + } + + /** @inheritdoc */ + public function getAll() + { + return $this->manifest; + } +} diff --git a/src/lib/Sage/Assets/ManifestInterface.php b/src/lib/Sage/Assets/ManifestInterface.php new file mode 100644 index 0000000..5af92e7 --- /dev/null +++ b/src/lib/Sage/Assets/ManifestInterface.php @@ -0,0 +1,26 @@ +wrapper = $wrapper; + self::$instances[$wrapper->slug()] = $this; + } + + /** + * @return string Layout (FQPN of, e.g., `base-page.php`, `base.php`) + */ + public function layout() + { + return $this->wrapper->wrap(); + } + + /** + * @return string Main template (FQPN of, e.g., `page.php`, `single.php`, `singular.php`) + */ + public function main() + { + return $this->wrapper->unwrap(); + } + + /** + * @param string $template Delimited template path + * @return string Partial template (FQPN of, e.g., `content.php`, `page-header.php` + */ + public function partial($template) + { + return (new Partial($template, $this->main()))->path(); + } +} diff --git a/src/lib/Sage/Template/Partial.php b/src/lib/Sage/Template/Partial.php new file mode 100644 index 0000000..97b8646 --- /dev/null +++ b/src/lib/Sage/Template/Partial.php @@ -0,0 +1,70 @@ +template = $template; + $this->main = $main; + } + + public function __toString() + { + return (string) $this->path(); + } + + /** + * Converts template into array of parts to be passed to locate_template() + * + * Here's an example of what happens: + * (new Template('partials/content-single-audio'))->parts(); + * // => ['partials/content-single-audio.php', 'partials/content-single.php', 'partials/content.php'] + * @return array Array of parts to pass to locate_template() + */ + public function parts() + { + if ($parts = $this->cache('parts')) { + return $parts; + } + $parts = explode($this->delimiter, str_replace('.php', '', $this->template)); + $templates[] = array_shift($parts); + foreach ($parts as $i => $part) { + $templates[] = $templates[$i] . $this->delimiter . $part; + } + if ($this->main) { + $templates = array_merge($templates, array_map(function ($template) { + return $template . $this->delimiter . basename($this->main, '.php'); + }, $templates)); + } + $templates = array_map(function ($template) { + return $template . '.php'; + }, $templates); + return $this->cache('parts', array_reverse($templates)); + } + + /** + * Passes $this->parts() to locate_template() to retrieve template location + * @return string Location of template + */ + public function path() + { + if (!$path = $this->cache('path')) { + $path = $this->cache('path', locate_template($this->parts())); + } + return apply_filters('sage/partial_' . basename($path, '.php'), $path, $this->parts()) ?: $path; + } + + protected function cache($key, $value = null) + { + if ($value !== null) { + self::$cache[$this->template][$key] = $value; + } + return isset(self::$cache[$this->template][$key]) ? self::$cache[$this->template][$key] : null; + } +} diff --git a/src/lib/Sage/Template/Wrapper.php b/src/lib/Sage/Template/Wrapper.php new file mode 100644 index 0000000..58d6399 --- /dev/null +++ b/src/lib/Sage/Template/Wrapper.php @@ -0,0 +1,62 @@ +slug = sanitize_title(basename($base, '.php')); + $this->wrapper = [$base]; + $this->template = $template; + $str = substr($base, 0, -4); + array_unshift($this->wrapper, sprintf($str . '-%s.php', basename($template, '.php'))); + } + + /** + * @return string + * @see getTemplate + */ + public function __toString() + { + return $this->unwrap(); + } + + /** {@inheritdoc} */ + public function wrap() + { + $wrappers = apply_filters('sage/wrap_' . $this->slug, $this->wrapper) ?: $this->wrapper; + return locate_template($wrappers); + } + + /** {@inheritdoc} */ + public function slug() + { + return $this->slug; + } + + /** {@inheritdoc} */ + public function unwrap() + { + $template = apply_filters('sage/unwrap_' . $this->slug, $this->template) ?: $this->template; + return locate_template($template) ?: $template; + } +} diff --git a/src/lib/Sage/Template/WrapperInterface.php b/src/lib/Sage/Template/WrapperInterface.php new file mode 100644 index 0000000..eaf4e1a --- /dev/null +++ b/src/lib/Sage/Template/WrapperInterface.php @@ -0,0 +1,27 @@ + __('Primary Navigation', 'sage') + ]); + + /** + * Enable post thumbnails + * @link http://codex.wordpress.org/Post_Thumbnails + * @link http://codex.wordpress.org/Function_Reference/set_post_thumbnail_size + * @link http://codex.wordpress.org/Function_Reference/add_image_size + */ + add_theme_support('post-thumbnails'); + + /** + * Enable post formats + * @link http://codex.wordpress.org/Post_Formats + */ + add_theme_support('post-formats', ['aside', 'gallery', 'link', 'image', 'quote', 'video', 'audio']); + + /** + * Enable HTML5 markup support + * @link http://codex.wordpress.org/Function_Reference/add_theme_support#HTML5 + */ + add_theme_support('html5', ['caption', 'comment-form', 'comment-list', 'gallery', 'search-form']); + + /** + * Use main stylesheet for visual editor + * @see assets/styles/layouts/_tinymce.scss + */ + add_editor_style(asset_path('styles/main.css')); +}); + +/** + * Register sidebars + */ +add_action('widgets_init', function () { + $config = [ + 'before_widget' => '
', + 'after_widget' => '
', + 'before_title' => '

', + 'after_title' => '

' + ]; + register_sidebar([ + 'name' => __('Primary', 'sage'), + 'id' => 'sidebar-primary' + ] + $config); + register_sidebar([ + 'name' => __('Footer', 'sage'), + 'id' => 'sidebar-footer' + ] + $config); +}); diff --git a/style.css b/style.css index 3b2edc8..c03c6f3 100644 --- a/style.css +++ b/style.css @@ -2,7 +2,7 @@ Theme Name: Sage Starter Theme Theme URI: https://roots.io/sage/ Description: Sage is a WordPress starter theme. Contribute on GitHub -Version: 8.4.2 +Version: 9.0.0 Author: Roots Author URI: https://roots.io/ Text Domain: sage diff --git a/template-custom.php b/template-custom.php deleted file mode 100644 index 3becaba..0000000 --- a/template-custom.php +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - diff --git a/404.php b/templates/404.php similarity index 73% rename from 404.php rename to templates/404.php index 8d228d5..5ef0100 100644 --- a/404.php +++ b/templates/404.php @@ -1,4 +1,4 @@ - +
diff --git a/templates/content-single.php b/templates/content-single.php deleted file mode 100644 index 2750794..0000000 --- a/templates/content-single.php +++ /dev/null @@ -1,15 +0,0 @@ - -
> -
-

- -
-
- -
-
- '']); ?> -
- -
- diff --git a/templates/index.php b/templates/index.php new file mode 100644 index 0000000..bb39ccc --- /dev/null +++ b/templates/index.php @@ -0,0 +1,14 @@ + + + +
+ +
+ + + + + + + + diff --git a/base.php b/templates/layouts/base.php similarity index 57% rename from base.php rename to templates/layouts/base.php index f5a0cfd..0e37279 100644 --- a/base.php +++ b/templates/layouts/base.php @@ -1,13 +1,6 @@ - - > - + >
- -
- + main(); ?> + + + + -
-
+
+ diff --git a/templates/page-header.php b/templates/page-header.php deleted file mode 100644 index 55a27ca..0000000 --- a/templates/page-header.php +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/templates/page.php b/templates/page.php new file mode 100644 index 0000000..dc2adff --- /dev/null +++ b/templates/page.php @@ -0,0 +1,4 @@ + + + + diff --git a/templates/comments.php b/templates/partials/comments.php similarity index 100% rename from templates/comments.php rename to templates/partials/comments.php diff --git a/templates/content-page.php b/templates/partials/content-page.php similarity index 100% rename from templates/content-page.php rename to templates/partials/content-page.php diff --git a/templates/content-search.php b/templates/partials/content-search.php similarity index 71% rename from templates/content-search.php rename to templates/partials/content-search.php index 79339c8..2eac1e4 100644 --- a/templates/content-search.php +++ b/templates/partials/content-search.php @@ -1,7 +1,7 @@
>

- +
diff --git a/templates/partials/content-single.php b/templates/partials/content-single.php new file mode 100644 index 0000000..0dda4e1 --- /dev/null +++ b/templates/partials/content-single.php @@ -0,0 +1,13 @@ +
> +
+

+ +
+
+ +
+
+ '']); ?> +
+ +
diff --git a/templates/content.php b/templates/partials/content.php similarity index 80% rename from templates/content.php rename to templates/partials/content.php index 0904a5e..2246a63 100644 --- a/templates/content.php +++ b/templates/partials/content.php @@ -1,7 +1,7 @@
>

- +
diff --git a/templates/entry-meta.php b/templates/partials/entry-meta.php similarity index 100% rename from templates/entry-meta.php rename to templates/partials/entry-meta.php diff --git a/templates/footer.php b/templates/partials/footer.php similarity index 100% rename from templates/footer.php rename to templates/partials/footer.php diff --git a/templates/head.php b/templates/partials/head.php similarity index 87% rename from templates/head.php rename to templates/partials/head.php index d62cb8a..9028b7d 100644 --- a/templates/head.php +++ b/templates/partials/head.php @@ -1,6 +1,6 @@ - + diff --git a/templates/header.php b/templates/partials/header.php similarity index 100% rename from templates/header.php rename to templates/partials/header.php diff --git a/templates/partials/page-header.php b/templates/partials/page-header.php new file mode 100644 index 0000000..b488560 --- /dev/null +++ b/templates/partials/page-header.php @@ -0,0 +1,3 @@ + diff --git a/templates/sidebar.php b/templates/partials/sidebar.php similarity index 100% rename from templates/sidebar.php rename to templates/partials/sidebar.php diff --git a/search.php b/templates/search.php similarity index 70% rename from search.php rename to templates/search.php index 63d867c..8786fa1 100644 --- a/search.php +++ b/templates/search.php @@ -1,4 +1,4 @@ - +
@@ -8,7 +8,7 @@ - + diff --git a/templates/single.php b/templates/single.php new file mode 100644 index 0000000..5e65d2e --- /dev/null +++ b/templates/single.php @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/templates/template-custom.php b/templates/template-custom.php new file mode 100644 index 0000000..d0bcd12 --- /dev/null +++ b/templates/template-custom.php @@ -0,0 +1,10 @@ + + + + + + diff --git a/watch.js b/watch.js new file mode 100644 index 0000000..0a867bf --- /dev/null +++ b/watch.js @@ -0,0 +1,33 @@ +// External dependencies +var webpack = require('webpack'), + webpackDevMiddleware = require('webpack-dev-middleware'), + webpackHotMiddleware = require('webpack-hot-middleware'), + browserSync = require('browser-sync'); + +// Internal dependencies +var webpackConfig = require('./webpack.config'), + config = require('./assets/config'); + +// Internal variables +var compiler = webpack(webpackConfig); + +browserSync.init({ + proxy: { + target: config.devUrl, + middleware: [ + webpackDevMiddleware(compiler, { + publicPath: webpackConfig.output.publicPath, + stats: { + colors: true + } + }), + webpackHotMiddleware(compiler, { + log: browserSync.notify + }) + ] + }, + files: [ + 'templates/**/*.php', + 'src/**/*.php' + ] +}); diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..ba5de4e --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,248 @@ +// External dependencies +var webpack = require('webpack'), + path = require('path'), + argv = require('minimist')(process.argv.slice(2)), + qs = require('qs'), + autoprefixer = require('autoprefixer'), + Clean = require("clean-webpack-plugin"), + AssetsPlugin = require('assets-webpack-plugin'), + ExtractTextPlugin = require('extract-text-webpack-plugin'), + OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin'), + cssnano = require('cssnano'); + +// Internal dependencies +var config = require('./assets/config'); + +// Internal variables +var scriptsFilename = (argv.release) ? 'scripts/[name]_[hash].js' : 'scripts/[name].js', + stylesFilename = (argv.release) ? 'styles/[name]_[hash].css' : 'styles/[name].css', + sourceMapQueryStr = (argv.release) ? '-sourceMap' : '+sourceMap', + assets = 'assets/', + dist = 'dist/', + jsLoader, + webpackConfig; + +jsLoader = { + test: /\.js$/, + exclude: [ /(node_modules|bower_components)(?![/|\\](bootstrap|foundation-sites))/ ], + loaders: [ 'babel?presets[]='+path.resolve('./node_modules/babel-preset-es2015')+'&cacheDirectory' ] +}; + +if (argv.watch) { // '--watch' to add monkey-hot + jsLoader.loaders.unshift('monkey-hot'); +} + +/** + * Process AssetsPlugin output and format it + * for Sage: {"[name].[ext]":"[name]_[hash].[ext]"} + * @param {Object} assets passed by processOutput + * @return {String} JSON + */ +var assetsPluginProcessOutput = function (assets) { + var name, + ext, + filename, + results = {}; + + for (name in assets) { + if (assets.hasOwnProperty(name)) { + for (ext in assets[name]) { + if (assets[name].hasOwnProperty(ext)) { + filename = name + '.' + ext; + results[filename] = path.basename(assets[name][ext]); + } + } + } + } + return JSON.stringify(results); +}; + +/** + * Loop through webpack entry + * and add the hot middleware + * @param {Object} entry webpack entry + * @return {Object} entry with hot middleware + */ +var addHotMiddleware = function (entry) { + var name, + results = {}, + hotMiddlewareScript = 'webpack-hot-middleware/client?' + qs.stringify({ + timeout: 20000, + reload: true + }); + + for (name in entry) { + if (entry.hasOwnProperty(name)) { + if (entry[name] instanceof Array !== true) { + results[name] = [entry[name]]; + } else { + results[name] = entry[name].slice(0); + } + results[name].push(hotMiddlewareScript); + } + } + return results; +}; + +webpackConfig = { + context: path.resolve(assets), + entry: config.entry, + output: { + path: path.join(__dirname, dist), + publicPath: path.join(config.publicPath, dist), + filename: scriptsFilename + }, + module: { + preLoaders: [ + { + test: /\.js?$/, + include: path.resolve(assets), + loader: 'eslint' + } + ], + loaders: [ + jsLoader, + { + test: /\.css$/, + include: path.resolve(assets), + loader: ExtractTextPlugin.extract('style', [ + 'css?' + sourceMapQueryStr, + 'postcss' + ]) + }, + { + test: /\.scss$/, + include: path.resolve(assets), + loader: ExtractTextPlugin.extract('style', [ + 'css?' + sourceMapQueryStr, + 'postcss', + 'resolve-url?' + sourceMapQueryStr, + 'sass?' + sourceMapQueryStr + ]) + }, + { + test: /\.(png|jpg|jpeg|gif|svg)(\?.*)?$/, + include: path.resolve(assets), + loaders: [ + 'file?' + qs.stringify({ + name: '[path][name].[ext]' + }), + 'image-webpack?' + JSON.stringify({ + bypassOnDebug: true, + progressive: true, + optimizationLevel: 7, + interlaced: true, + pngquant: { + quality: "65-90", + speed: 4 + }, + svgo: { + removeUnknownsAndDefaults: false, + cleanupIDs: false + } + }) + ] + }, + { + test: /\.(ttf|eot)(\?.*)?$/, + include: path.resolve(assets), + loader: 'file?' + qs.stringify({ + name: '[path][name]_[md5:hash:hex:8].[ext]' + }) + }, + { + test: /\.woff(2)?(\?.*)?$/, + include: path.resolve(assets), + loader: 'url?' + qs.stringify({ + limit: 10000, + mimetype: "application/font-woff", + name: "[path][name]_[md5:hash:hex:8].[ext]" + }) + }, + // Use file-loader for node_modules/ assets + { + test: /\.(ttf|eot|woff(2)?|png|jpg|jpeg|gif|svg)(\?.*)?$/, + include: /node_modules/, + loader: 'file?' + qs.stringify({ + name: 'vendor/[name]_[md5:hash:hex:8].[ext]' + }) + } + ] + }, + resolve: { + extensions: [ '', '.js', '.json' ], + modulesDirectories: [ + 'node_modules', + 'bower_components' + ] + }, + externals: { + jquery: 'jQuery' + }, + plugins: [ + new Clean([dist]), + new ExtractTextPlugin(stylesFilename, { + allChunks: true, + disable: (argv.watch === true) // '--watch' disable ExtractTextPlugin + }), + new webpack.ProvidePlugin({ + $: 'jquery', + jQuery: 'jquery', + 'window.jQuery': 'jquery', + 'Tether': 'tether', + 'window.Tether': 'tether' + }), + new webpack.DefinePlugin({ + WEBPACK_PUBLIC_PATH: (argv.watch === true) ? JSON.stringify(path.join(config.publicPath, dist)) : false + }) + ], + postcss: [ + autoprefixer({ + browsers: [ + 'last 2 versions', + 'android 4', + 'opera 12' + ] + }) + ], + eslint: { + failOnWarning: false, + failOnError: true + }, + stats: { + colors: true + } +}; + +// '--watch' to push additional plugins to webpackConfig +if (argv.watch) { + webpackConfig.entry = addHotMiddleware(webpackConfig.entry); + webpackConfig.output.pathinfo = true; + webpackConfig.debug = true; + webpackConfig.devtool = '#cheap-module-source-map'; + webpackConfig.plugins.push(new webpack.optimize.OccurenceOrderPlugin()); + webpackConfig.plugins.push(new webpack.HotModuleReplacementPlugin()); + webpackConfig.plugins.push(new webpack.NoErrorsPlugin()); +} + +// '--release' to push additional plugins to webpackConfig +if (argv.release) { + webpackConfig.plugins.push(new AssetsPlugin({ + path: path.join(__dirname, dist), + filename: 'assets.json', + fullPath: false, + processOutput: assetsPluginProcessOutput + })); + webpackConfig.plugins.push(new webpack.optimize.UglifyJsPlugin({ + compress: { + 'drop_debugger': true + } + })); + webpackConfig.plugins.push(new OptimizeCssAssetsPlugin({ + cssProcessor: cssnano, + cssProcessorOptions: { discardComments: { removeAll: true } }, + canPrint: true + })); +} + +module.exports = webpackConfig;