Browse Source

Initial commit.

pull/3/merge
Ned Zimmerman 8 years ago
commit
b842642289
No known key found for this signature in database
GPG Key ID: FF56334A013120CA
  1. 17
      .editorconfig
  2. 3
      .gitattributes
  3. 1
      .github/CONTRIBUTING.md
  4. 62
      .github/ISSUE_TEMPLATE.md
  5. 10
      .gitignore
  6. 41
      .travis.yml
  7. 556
      CHANGELOG.md
  8. 19
      LICENSE.md
  9. 124
      README.md
  10. 24
      app/admin.php
  11. 70
      app/filters.php
  12. 147
      app/helpers.php
  13. 128
      app/setup.php
  14. 50
      composer.json
  15. 1489
      composer.lock
  16. 31
      config/assets.php
  17. 32
      config/theme.php
  18. 51
      config/view.php
  19. 131
      package.json
  20. 71
      phpcs.xml
  21. 14
      resources/assets/build/.eslintrc
  22. 60
      resources/assets/build/config.js
  23. 7
      resources/assets/build/helpers/hmr-client.js
  24. 7
      resources/assets/build/helpers/public-path.js
  25. 15
      resources/assets/build/postcss.config.js
  26. 15
      resources/assets/build/util/addHotMiddleware.js
  27. 34
      resources/assets/build/util/assetManifestsFormatter.js
  28. 14
      resources/assets/build/util/desire.js
  29. 211
      resources/assets/build/webpack.config.js
  30. 19
      resources/assets/build/webpack.config.optimize.js
  31. 35
      resources/assets/build/webpack.config.watch.js
  32. 21
      resources/assets/config.json
  33. 0
      resources/assets/fonts/.gitkeep
  34. 0
      resources/assets/images/.gitkeep
  35. 5
      resources/assets/scripts/customizer.js
  36. 24
      resources/assets/scripts/main.js
  37. 5
      resources/assets/scripts/routes/about.js
  38. 8
      resources/assets/scripts/routes/common.js
  39. 8
      resources/assets/scripts/routes/home.js
  40. 63
      resources/assets/scripts/util/Router.js
  41. 9
      resources/assets/scripts/util/camelCase.js
  42. 0
      resources/assets/styles/common/_global.scss
  43. 5
      resources/assets/styles/common/_variables.scss
  44. 0
      resources/assets/styles/components/_buttons.scss
  45. 5
      resources/assets/styles/components/_comments.scss
  46. 5
      resources/assets/styles/components/_forms.scss
  47. 56
      resources/assets/styles/components/_wp-classes.scss
  48. 0
      resources/assets/styles/layouts/_footer.scss
  49. 2
      resources/assets/styles/layouts/_header.scss
  50. 0
      resources/assets/styles/layouts/_pages.scss
  51. 0
      resources/assets/styles/layouts/_posts.scss
  52. 0
      resources/assets/styles/layouts/_sidebar.scss
  53. 3
      resources/assets/styles/layouts/_tinymce.scss
  54. 25
      resources/assets/styles/main.scss
  55. 10
      resources/controllers/About.php
  56. 13
      resources/controllers/App.php
  57. 10
      resources/controllers/Home.php
  58. 92
      resources/functions.php
  59. 3
      resources/index.php
  60. BIN
      resources/screenshot.png
  61. 12
      resources/style.css
  62. 14
      resources/views/404.blade.php
  63. 18
      resources/views/index.blade.php
  64. 23
      resources/views/layouts/app.blade.php
  65. 8
      resources/views/page.blade.php
  66. 38
      resources/views/partials/comments.blade.php
  67. 2
      resources/views/partials/content-page.blade.php
  68. 11
      resources/views/partials/content-search.blade.php
  69. 13
      resources/views/partials/content-single.blade.php
  70. 9
      resources/views/partials/content.blade.php
  71. 6
      resources/views/partials/entry-meta.blade.php
  72. 5
      resources/views/partials/footer.blade.php
  73. 6
      resources/views/partials/head.blade.php
  74. 10
      resources/views/partials/header.blade.php
  75. 3
      resources/views/partials/page-header.blade.php
  76. 1
      resources/views/partials/sidebar.blade.php
  77. 18
      resources/views/search.blade.php
  78. 7
      resources/views/single.blade.php
  79. 12
      resources/views/template-custom.blade.php
  80. 6773
      yarn.lock

17
.editorconfig

@ -0,0 +1,17 @@
# editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.php]
indent_size = 4
[resources/views/**.php]
indent_size = 2

3
.gitattributes vendored

@ -0,0 +1,3 @@
/.github export-ignore
/.gitattributes export-ignore
/.travis.yml export-ignore

1
.github/CONTRIBUTING.md

@ -0,0 +1 @@
Please read [Contributing to Roots Projects](https://github.com/roots/guidelines/blob/master/CONTRIBUTING.md)

62
.github/ISSUE_TEMPLATE.md

@ -0,0 +1,62 @@
## Submit a feature request or bug report
- [ ] I've read the [guidelines for Contributing to Roots Projects](https://github.com/roots/guidelines/blob/master/CONTRIBUTING.md)
- [ ] This is a feature request
- [ ] This is a bug report
- [ ] This request isn't a duplicate of an [existing issue](https://github.com/roots/sage/issues)
- [ ] I've read the [docs](https://roots.io/sage/docs) and [NPM Debugging Guidelines post](https://discourse.roots.io/t/npm-debugging-guidelines-failed-npm-install-bower-install-or-gulp-build-read-this/3060) and followed them (if applicable)
- [ ] This is not a personal support request that should be posted on the [Roots Discourse](https://discourse.roots.io/c/sage) forums
<!-- Replace any `X` with your information. -->
---
**What is the current behavior?**
X
**What is the expected or desired behavior?**
X
---
## Bug report
<!-- (delete this section if not applicable) -->
**Please provide steps to reproduce, including full log output:**
X
**Please describe your local environment:**
WordPress version: X
OS: X
NPM/Node version: X
**Where did the bug happen? Development or remote servers?**
X
**Is there a related [Discourse](https://discourse.roots.io/) thread or were any utilized (please link them)?**
X
---
## Feature Request
<!-- (delete this section if not applicable) -->
**Please provide use cases for changing the current behavior:**
X
**Other relevant information:**
X

10
.gitignore vendored

@ -0,0 +1,10 @@
# Include your project-specific ignores in this file
# Read about how to use .gitignore: https://help.github.com/articles/ignoring-files
.cache-loader
dist
bower_components
node_modules
npm-debug.log
yarn-error.log
vendor
resources/assets/config-local.json

41
.travis.yml

@ -0,0 +1,41 @@
language: php
sudo: false
dist: trusty
php:
- 7.1
- 7.0
- 5.6
- nightly
env:
- TRAVIS_NODE_VERSION="6"
- TRAVIS_NODE_VERSION="7"
matrix:
fast_finish: true
allow_failures:
- php: nightly
cache:
apt: true
directories:
- $HOME/.composer/cache
- $HOME/.yarn-cache
- vendor
before_install:
- composer self-update
- source ~/.nvm/nvm.sh && nvm install $TRAVIS_NODE_VERSION && nvm use $TRAVIS_NODE_VERSION
- export PATH=$HOME/.yarn/bin:$PATH && travis_retry curl -o- -L https://yarnpkg.com/install.sh | bash
install:
- node -v && yarn -V
- travis_retry yarn
- composer install -o --prefer-dist --no-interaction
script:
- yarn run test
- yarn run build
- yarn run rmdist
- yarn run "build:production"
- composer test

556
CHANGELOG.md

@ -0,0 +1,556 @@
### 9.0.0-beta.3: April 21st, 2017
* Move required theme files to `sage/resources` ([#1877](https://github.com/roots/sage/pull/1877))
* Move `src/` to `app/` ([#1868](https://github.com/roots/sage/pull/1868))
* Move `templates/` to `resources/views/`, move `assets/` to `resources/assets/`, rename `base.blade.php` to `app.blade.php` ([#1864](https://github.com/roots/sage/pull/1864))
* Add option to configure build settings ([#1822](https://github.com/roots/sage/pull/1822))
* Add support for HTML injection ([#1817](https://github.com/roots/sage/pull/1817))
* Add Tachyons as a CSS framework option ([#1867](https://github.com/roots/sage/pull/1867))
### 9.0.0-beta.2: January 19th, 2017
* Fix Browersync ([#1815](https://github.com/roots/sage/pull/1815))
* Add option to select CSS framework, add Foundation as an option ([#1813](https://github.com/roots/sage/pull/1813))
* Add option to add Font Awesome ([#1812](https://github.com/roots/sage/pull/1812))
* Add option to change theme file headers ([#1811](https://github.com/roots/sage/pull/1811))
* Add option to remove Bootstrap ([#1810](https://github.com/roots/sage/pull/1810))
* Remove Font Awesome ([#1809](https://github.com/roots/sage/pull/1809))
* Remove grid defaults ([#1808](https://github.com/roots/sage/pull/1808))
* Fix for `publicPath` ([#1806](https://github.com/roots/sage/pull/1806))
* Update clean task name ([#1800](https://github.com/roots/sage/pull/1800))
* Allow browser versions to be configured in `config.json` ([#1798](https://github.com/roots/sage/pull/1798))
* Use stock ESLint ([#1796](https://github.com/roots/sage/pull/1796))
### 9.0.0-beta.1: January 10th, 2017
* Update to Bootstrap 4 Alpha 6 ([#1792](https://github.com/roots/sage/pull/1792))
* Add Blade ([#1765](https://github.com/roots/sage/pull/1765) and [#1777](https://github.com/roots/sage/pull/1777))
* Remove sidebar defaults ([#1760](https://github.com/roots/sage/pull/1760))
* Remove post formats ([#1759](https://github.com/roots/sage/pull/1759))
### 9.0.0-alpha.4: November 16th, 2016
* Use new webpack api schema ([8ac5f15](https://github.com/roots/sage/commit/e6e60aa))
* Update dependencies ([70ebba7](https://github.com/roots/sage/commit/70ebba7))
* Variables organization ([8ac5f15](https://github.com/roots/sage/commit/8ac5f15))
* Use `$.fn.ready()` (reverts [724d550](https://github.com/roots/sage/commit/724d550)) ([e7fccbe](https://github.com/roots/sage/commit/e7fccbe))
* Theme activation updates 'stylesheet' option instead of 'template' ([fb19145](https://github.com/roots/sage/commit/fb19145))
* Reorganize and refactor build routine ([8c9ba05](https://github.com/roots/sage/commit/8c9ba05))
* Switch assets manifest plugin ([c1bb2b3](https://github.com/roots/sage/commit/c1bb2b3))
* Add images to assets manifest ([c49793c](https://github.com/roots/sage/commit/c49793c))
* Switch from babel to buble ([0d38ab8](https://github.com/roots/sage/commit/0d38ab8))
* Update dependencies & webpack compatibility ([eae52fd](https://github.com/roots/sage/commit/eae52fd))
* Use http by default (not https) to be consistent with Trellis ([e6f2f49](https://github.com/roots/sage/commit/e6f2f49))
### 9.0.0-alpha.3: September 11th, 2016
* Fix webpack HMR ([#1713](https://github.com/roots/sage/issues/1713))
* Remove minor edits from CHANGELOG.md ([3516629](https://github.com/roots/sage/commit/3516629))
### 9.0.0-alpha.2: September 4th, 2016
* Refactor build routine ([#1703](https://github.com/roots/sage/pull/1703))
* Update `_grid.scss` to use `@include make-col-ready()` mixin ([#1706](https://github.com/roots/sage/pull/1706))
### 9.0.0-alpha.1: August 30th, 2016
* Move assets found in `node_modules/` to `dist/vendor`, simpler `assets/config.json` ([#1697](https://github.com/roots/sage/pull/1697))
* Set dynamically absolute public path ([#1696](https://github.com/roots/sage/pull/1696))
* Load Tether ([#1686](https://github.com/roots/sage/pull/1686))
* Squash asset pipeline bugs ([4d58f88](https://github.com/roots/sage/commit/4d58f88))
* Update dependencies, incl Bootstrap 4 alpha 3 ([447c24d](https://github.com/roots/sage/commit/447c24d))
* Fix path to stylesheet in `add_editor_style` ([#1684](https://github.com/roots/sage/pull/1684))
* Update required Node.js version ([72b2d89](https://github.com/roots/sage/commit/72b2d89))
* Router doesn't require jQuery, use default params ([339cc8e](https://github.com/roots/sage/commit/339cc8e))
* Fix display of theme name in Customizer ([3425386](https://github.com/roots/sage/commit/3425386))
* Convert scripts to ES6 ([f34af48](https://github.com/roots/sage/commit/f34af48))
* Refactor functions.php ([eae36be](https://github.com/roots/sage/commit/eae36be))
* Rework template wrapper, bring back template_part() ([#1678](https://github.com/roots/sage/pull/1678))
* Remove unused static variable in Wrapper ([9bfdd5a](https://github.com/roots/sage/commit/9bfdd5a))
* Remove `path.extname()` check ([#1673](https://github.com/roots/sage/pull/1673))
* Updated to align with the Bootstrap 4 docs ([#1667](https://github.com/roots/sage/pull/1667))
* Add `npm prune` to Travis CI ([#1663](https://github.com/roots/sage/pull/1663))
* Bootstrap NPM ^4.0.0-alpha.2 ([#1650](https://github.com/roots/sage/pull/1650))
* Fix Bootstrap 4 styles ([#1642](https://github.com/roots/sage/pull/1642))
* Fix autoloader load order issue when including Sage 9 via composer.json in Bedrock ([#1628](https://github.com/roots/sage/pull/1628))
* `is_page_template()` requires the name of the subfolder ([#1626](https://github.com/roots/sage/pull/1626))
* Webpack config improvements ([#1629](https://github.com/roots/sage/pull/1629))
* Webpack implementation improvements ([#1627](https://github.com/roots/sage/pull/1627))
* Webpack implementation ([#1625](https://github.com/roots/sage/pull/1625))
* Fix BS4 grid after their grid updates ([5551dde](https://github.com/roots/sage/commit/5551dde))
* Pass the correct template ([856a482](https://github.com/roots/sage/commit/856a482))
* Optimize travis a bit ([b42c425](https://github.com/roots/sage/commit/b42c425))
* Move single-post loop to single.php, closes #1582 ([6efa099](https://github.com/roots/sage/commit/6efa099))
* All function braces need to be on new line ([b491f76](https://github.com/roots/sage/commit/b491f76))
* Fix issue with WP loading wrong index.php ([9e2917e](https://github.com/roots/sage/commit/9e2917e))
* Use 4 spaces for `src/*.php` ([fe659f4](https://github.com/roots/sage/commit/fe659f4))
* Use phpcs.xml for all rules ([246955c](https://github.com/roots/sage/commit/246955c))
* Conform to new rules ([6a4d3bd](https://github.com/roots/sage/commit/6a4d3bd))
* Create new phpcs rules ([2d02544](https://github.com/roots/sage/commit/2d02544))
* Remove Template class ([1df3fee](https://github.com/roots/sage/commit/1df3fee))
* Remove closure from sidebar registration ([12d6ac3](https://github.com/roots/sage/commit/12d6ac3))
* Remove sage.pot ([d4461fa](https://github.com/roots/sage/commit/d4461fa))
* Remove template_part, template_sidebar, temp sidebar fix ([abeea0f](https://github.com/roots/sage/commit/abeea0f))
* Update asset handles ([fa0e51f](https://github.com/roots/sage/commit/fa0e51f))
* Remove comment-reply JS ([d217ba6](https://github.com/roots/sage/commit/d217ba6))
* Update node in travis, remove unsupported php ([8712dc8](https://github.com/roots/sage/commit/8712dc8))
* Update dependencies, switch to eslint ([e51e41e](https://github.com/roots/sage/commit/e51e41e))
* Bootstrap 4 ([c9ef232](https://github.com/roots/sage/commit/c9ef232))
* Fix: page title not displaying ([9283bbb](https://github.com/roots/sage/commit/9283bbb))
* Rename interfaces, unset after unwrapping ([97906e9](https://github.com/roots/sage/commit/97906e9))
* Restructure theme, use autoloader ([9eaffa3](https://github.com/roots/sage/commit/9eaffa3a2d4df462dd8020a10551334208bd32a3))
### 8.5.0: September 20th, 2016
* Update installation instructions
* Update dependencies
* Update to Bootstrap 4.0.0-alpha.4 ([5eb01fd](https://github.com/roots/sage/commit/5eb01fd0319a7b6576e31579dc50e16b023abb74))
### 8.4.2: February 19th, 2016
* Add Composer vendor directory to gitignore ([#1618](https://github.com/roots/sage/issues/1618))
* Fix build test by removing trailing space ([#1617](https://github.com/roots/sage/issues/1617))
* Replace deprecated gulp-minify-css with gulp-cssnano ([#1610](https://github.com/roots/sage/issues/1610))
### 8.4.1: January 27th, 2016
* Add `composer.json` and update installation instructions ([#1583](https://github.com/roots/sage/issues/1583))
### 8.4.0: December 1st, 2015
* Update to Bootstrap 3.3.6 ([#1578](https://github.com/roots/sage/pull/1578))
* Remove unnecessary underscore ([#1577](https://github.com/roots/sage/pull/1577))
* Drop support for older browsers ([#1571](https://github.com/roots/sage/pull/1571))
* Add support for theme customizer ([#1573](https://github.com/roots/sage/pull/1573))
* Remove extraneous no-js ([#1562](https://github.com/roots/sage/pull/1562))
* Simplify/speed up editor style process ([#1560](https://github.com/roots/sage/pull/1560))
### 8.3.0: October 13th, 2015
* Setup organization ([#1558](https://github.com/roots/sage/pull/1558))
* Remove redundancy with WAI-ARIA in HTML ([#1557](https://github.com/roots/sage/pull/1557))
* Rename config.php to setup.php ([#1556](https://github.com/roots/sage/pull/1556))
* Move init.php to config.php ([#1555](https://github.com/roots/sage/pull/1555))
* Use Sass to style search form, remove search template ([#1545](https://github.com/roots/sage/pull/1545))
* Remove Modernizr ([#1541](https://github.com/roots/sage/pull/1541))
* Remove references to WP_ENV ([#1554](https://github.com/roots/sage/pull/1554))
* Use WP core's HTML5 gallery markup ([#1546](https://github.com/roots/sage/pull/1546))
* Use slash in handle names for theme CSS and JS ([#1537](https://github.com/roots/sage/pull/1537))
* Add compatibility with WooCommerce Multilingual plugin ([#1530](https://github.com/roots/sage/pull/1530))
* Remove ConditionalTagCheck class ([#1494](https://github.com/roots/sage/pull/1494))
* Add search templates ([#1459](https://github.com/roots/sage/issues/1459))
* Allow `debugger` statements in development JavaScript ([#1487](https://github.com/roots/sage/issues/1487))
### 8.2.1: May 7th, 2015
* Update BrowserSync ([#1457](https://github.com/roots/sage/issues/1457))
* Bump dependencies ([#1448](https://github.com/roots/sage/issues/1448))
* Allow revved files to resolve in development if they exist ([#1456](https://github.com/roots/sage/issues/1456))
* Disable advanced minification features to fix incorrect file path in compiled CSS ([#1452](https://github.com/roots/sage/issues/1452))
* Fix Glyphicon font path ([#1455](https://github.com/roots/sage/issues/1455))
### 8.2.0: April 29th, 2015
* Use Sass Bootstrap by default ([#1437](https://github.com/roots/sage/issues/1437))
* Remove nav walker and Bootstrap navbar ([#1427](https://github.com/roots/sage/issues/1427))
* Remove Bootstrap gallery ([#1421](https://github.com/roots/sage/issues/1421))
* Remove hardcoded feed link ([#1426](https://github.com/roots/sage/issues/1426))
* Move jQuery CDN feature to Soil ([#1422](https://github.com/roots/sage/issues/1422))
* Bump `gulp-load-plugins` to 0.10.0 ([#1419](https://github.com/roots/sage/issues/1419))
* Switch from [yargs](https://github.com/bcoe/yargs) to [minimist](https://github.com/substack/minimist) ([#1418](https://github.com/roots/sage/issues/1418))
* Remove `$content_width` ([#1417](https://github.com/roots/sage/issues/1417))
* Lowercase `X-UA-Compatible` ([#1409](https://github.com/roots/sage/issues/1409))
* Remove mention of Google Analytics from the config ([#1384](https://github.com/roots/sage/issues/1384))
### 8.1.1: March 31st, 2015
* Remove pleeease dependency in favor of vanilla gulp-autoprefixer and gulp-minify-css ([#1402](https://github.com/roots/sage/issues/1402))
* Fix `gulp --production` race condition ([#1398](https://github.com/roots/sage/issues/1398))
* Update to Bootstrap 3.3.4 ([#1387](https://github.com/roots/sage/issues/1387))
### 8.1.0: March 13th, 2015
* Move HTML5 Boilerplate's Google Analytics snippet to Soil ([#1382](https://github.com/roots/sage/issues/1382))
* Run `gulp build` if `bower.json` is changed ([#1378](https://github.com/roots/sage/issues/1378))
* Remove namespace from base.php ([#1372](https://github.com/roots/sage/issues/1372))
* Allow build directory to be customized ([#1352](https://github.com/roots/sage/issues/1352), [#1366](https://github.com/roots/sage/issues/1366))
* Update ConditionalTagCheck and usage docs ([#1365](https://github.com/roots/sage/issues/1365))
* Change default gallery columns to 3 ([#1364](https://github.com/roots/sage/issues/1364))
* Apply `script_loader_src` filter to jQuery fallback ([#1363](https://github.com/roots/sage/issues/1363))
### 8.0.1: February 26th, 2015
* Update asset-builder version to fix Windows compatibility ([#1351](https://github.com/roots/sage/issues/1351))
* Fix broken wiredep imports with main.scss.example ([Discussion](https://discourse.roots.io/t/issue-with-sage-sass-version/2962))
### 8.0.0: February 25th, 2015
* Change theme name from Roots to Sage
* Bump required PHP version to >=5.4
* Add coding standards based on PSR-2
* Add Travis CI
* Add namespace
* Use short array syntax
* Use short echo syntax
* Switch from Grunt to gulp, new front-end development workflow
* Switch from Livereload to [BrowserSync](http://www.browsersync.io/)
* Use wiredep for Sass and Less injection
* Implement JSON file based asset pipeline with [asset-builder](https://github.com/austinpray/asset-builder)
* Re-organize asset file structure
* Re-organize stylesheet file structure
* Add main.scss.example and instructions for using Sass
* Use the primary theme stylesheet for the editor stylesheet
* Remove theme activation, move to [wp-cli-theme-activation](https://github.com/roots/wp-cli-theme-activation)
* Simplify 404 page
* Convert Sidebar to ConditionalTagCheck
* Update to jQuery 1.11.2
* Use new core navigation template tag
* Update sidebar to fix default template check
* Update nav walker to correctly assign `active` classes for custom post types
* Better support for CPT templates
### 7.0.3: December 18th, 2014
* Use `get_the_archive_title`
* Remove `wp_title`, add title-tag theme support
* Remove `Roots_Nav_Walker` as default for all menus
* Update to Bootstrap 3.3.1
* Add some base comment styling
* Make search term `required` in search form
### 7.0.2: October 24th, 2014
* Simplify comments, use core comment form and list
* Remove HTML5 shiv from Modernizr build
* Move JavaScript to footer
* Update hEntry schema to use `updated` instead of `published`
* Move variables into `main.less`
* Add `roots_body_class` function that checks for page slug in `body_class`
* Move `wp_footer` from footer template into `base.php`
### 7.0.1: August 15th, 2014
* Move `<main>` and `.sidebar` markup out of PHP and into LESS
* Define `WP_ENV` if it is not already defined
* Only load Google Analytics in production environment
### 7.0.0: July 3rd, 2014
* Updated Grunt workflow
* Use grunt-modernizr to make a lean Modernizr build
* Use Bower for front-end package management
* Update to Bootstrap 3.2.0
* Update to Modernizr 2.8.2
* Update to jQuery 1.11.1
* Move clean up, relative URLs, and nice search to [Soil](https://github.com/roots/soil)
* Update LESS organization
* Move [community translations](https://github.com/roots/roots-translations) to separate repository
### 6.5.2: February 4th, 2014
* Update to Bootstrap 3.1.0
* Move DOM routing into an anonymous function to support jQuery noConflict
* Update to jQuery 1.11.0
* Add notice to theme activation, tidy activation table markup
* Remove changing media folder from theme activation (use [Bedrock](https://github.com/roots/bedrock) for clean URLs out of the box)
* Switch `div.main` to `main` element now that Modernizr uses the latest HTML5 Shiv
* Update to Modernizr 2.7.0
* Don't run JSHint on plugins (`assets/js/plugins/`)
* Disable warnings about undefined variables (JSHint)
* Merge in updates from HTML5 Boilerplate
* Add JS source map (disabled by default)
* Replace `grunt-recess` with `grunt-contrib-less`, add LESS source map support
### 6.5.1: November 5th, 2013
* Move clean URLs to a [plugin](https://github.com/roots/roots-rewrites)
* Update to Bootstrap 3.0.1
### 6.5.0: August 23rd, 2013
* Reference new site, [http://roots.io/](http://roots.io/)
* Remove bundled docs, reference [http://roots.io/docs/](http://roots.io/docs/)
* Use Bootstrap variables for media queries
* Update to Bootstrap 3.0.0
* Update to jQuery 1.10.2
* Change media directory from `/assets/` to `/media/`
* Update to Google Universal Analytics
* Show author display name for author archives
* Add Serbian translation
* Remove post tags from templates
* Remove TinyMCE valid elements tweaks (no longer necessary)
* Remove additional widget classes
* Move `/assets/css/less/` to `/assets/less/`
* Add wrapper templates filter
* Fix relative external URLs issue
### 6.4.0: May 1st, 2013
* Fix Theme Activation page issues
* Fix issues with root relative URLs and rewrites on non-standard setups
* Make sure rewrites are added to `.htaccess` immediately after activation
* Move HTML5 Boilerplate's `.htaccess` to a [plugin](https://github.com/roots/wp-h5bp-htaccess)
* Rename `page-custom.php` to `template-custom.php`
* Don't warn about unwritable htaccess if that option is disabled
* Add missing collapse class for top navbar
* Add comment template
* Update is_dropdown evaluation in nav walker
* Re-organize archives template
* Add missing comment ID
* hNews consistency with entry-title class
* Add `wp_title()` filter
* Fix missing closing div in comments
* Fix for navbar dropdowns
* Add option for using jQuery on Google CDN
* Correct logic in `roots_enable_root_relative_urls`
* Add Greek translation, update Brazilian Portuguese translation
* Update to Bootstrap 2.3.1
* Simplify alerts
* Remove disabled post nav links
* Use Bootstrap media object for listing comments
* Move Google Analytics to `lib/scripts.php`
* Static top navbar instead of fixed
### 6.3.0: February 8th, 2013
* Update to Bootstrap 2.3.0
* Update to jQuery 1.9.1
* Output author title with `get_the_author()`
* Add EditorConfig
* Update 404 template based on H5BP
* Update H5BP's included .htaccess
* Don't show comments on passworded posts
* Add `do_action('get_header')` for WooSidebars compatibility
* Simplify entry meta
* Allow `get_search_form()` to be called more than once per request
* Move plugins.js and main.js to footer
* JavaScript clean up (everything is now enqueued)
* Remove conditional feed
* Introduce `add_theme_support('bootstrap-gallery')`
* Rewrites organization (introduce `lib/rewrites.php`)
* Fix `add_editor_style` path
* Updated translations: French, Bulgarian, Turkish, Korean
* Enable `add_theme_support` for Nice Search
* Replace ID's with classes
* Add support for dynamic sidebar templates
* Fix PHP notice on search with no results
* Update to jQuery 1.9.0
### 6.2.0: January 13th, 2013
* Implement latest Nice Search
* Update [gallery] shortcode
* Add Simplified Chinese, Indonesian, Korean translations
* Move template title to `lib/utils.php`
* Update to Bootstrap 2.2.2
* Update to jQuery 1.8.3
* Use `entry-summary` class for excerpts per Readability's Article Publishing Guidelines
* Cleanup/refactor `lib/activation.php`
* Remove `lib/post-types.php` and `lib/metaboxes.php`
* Make sure Primary Navigation menu always gets created and has the location set upon activation, update activation permalink method
* Update to Bootstrap 2.2.1
* Update conditional feed method
* Update to Bootstrap 2.2.0
* Return instead of echo class names in `roots_main_class` and `roots_sidebar_class`
* Move nav customizations into `lib/nav.php`
### 6.1.0: October 2nd, 2012
* Change roots_sidebar into a more explicit configuration array
* Re-organize configuration/setup files
* Update to jQuery 1.8.2
* Refactor/simplify Roots vCard Widget
* Move custom entry_meta code into template
* Move Google Analytics code into footer template
* Add CONTRIBUTING.md to assist with the new GitHub UI
* Add nav walker support for CSS dividers and nav-header
### 6.0.0: September 16th, 2012
* Simplify nav walker and support 3rd level dropdowns
* Update to Bootstrap 2.1.1, jQuery 1.8.1, Modernizr 2.6.2
* Add bundled docs
* Update all templates to use [PHP Alternative Syntax](http://php.net/manual/en/control-structures.alternative-syntax.php)
* Add MIT License
* Implement scribu's [Theme Wrapper](http://scribu.net/wordpress/theme-wrappers.html) (see `base.php`)
* Move `css/`, `img/`, and `js/` folders within a new `assets/` folder
* Move templates, `comments.php`, and `searchform.php` to `templates/` folder
* Rename `inc/` to `lib/`
* Add placeholder `lib/post-types.php` and `lib/metaboxes.php` files
* Rename `loop-` files to `content-`
* Remove all hooks
* Use `templates/page-header.php` for page titles
* Use `head.php` for everything in `<head>`
### 5.2.0: August 18th, 2012
* Update to jQuery 1.8.0 and Modernizr 2.6.1
* Fix duplicate active class in `wp_nav_menu` items
* Merge `Roots_Navbar_Nav_Walker` into `Roots_Nav_Walker`
* Add and update code documentation
* Use `wp_get_theme()` to get the theme name on activation
* Use `<figure>` & `<figcaption>` for captions
* Wrap embedded media as suggested by Readability
* Remove unnecessary `remove_action`'s on `wp_head` as of WordPress 3.2.1
* Add updates from HTML5 Boilerplate
* Remove well class from sidebar
* Flush permalinks on activation to avoid 404s with clean URLs
* Show proper classes on additional `wp_nav_menu()`'s
* Clean up `inc/cleanup.php`
* Remove old admin notice for tagline
* Remove default tagline admin notice, hide from feed
* Fix for duplicated classes in widget markup
* Show title on custom post type archive template
* Fix for theme preview in WordPress 3.3.2
* Introduce `inc/config.php` with options for clean URLs, H5BP's `.htaccess`, root relative URLs, and Bootstrap features
* Allow custom CSS classes in menus, walker cleanup
* Remove WordPress version numbers from stylesheets
* Don't include HTML5 Boilerplate's `style.css` by default
* Allow `inc/htaccess.php` to work with Litespeed
* Update to Bootstrap 2.0.4
* Update Bulgarian translation
* Don't use clean URLs with default permalink structure
* Add translations for Catalan, Polish, Hungarian, Norwegian, Russian
### 5.1.0: April 14th, 2012
* Various bugfixes for scripts, stylesheets, root relative URLs, clean URLs, and htaccess issues
* Add a conditional feed link
* Temporarily remove Gravity Forms customizations
* Update to Bootstrap 2.0.2
* Update `roots.pot` for translations
* Add/update languages: Vietnamese, Swedish, Bulgarian, Turkish, Norwegian, Brazilian Portugese
* Change widgets to use `<section>` instead of `<article>`
* Add comment-reply.js
* Remove optimized robots.txt
* HTML5 Boilerplate, Modernizr, and jQuery updates
### 5.0.0: February 5th, 2012
* Remove all frameworks except Bootstrap
* Update to Bootstrap 2.0
* Remove `roots-options.php` and replaced with a more simple `roots-config.php`
* Now using Bootstrap markup on forms, page titles, image galleries, alerts and errors, post and comment navigation
* Remove Roots styles from `style.css` and introduced `app.css` for site-specific CSS
* Remove almost all previous default Roots styling
* Latest updates from HTML5 Boilerplate
### 4.1.0: February 1st, 2012
* Update translations
* HTML5 Boilerplate updates
* Fix for Server 500 errors
* Add `roots-scripts.php`, now using `wp_enqueue_script`
* Re-organize `roots-actions.php`
* Allow `<script>` tags in TinyMCE
* Add full width class and search form to 404 template
* Remove Blueprint CSS specific markup
* Use Roots Nav Walker as default
* Add author name and taxonomy name to archive template title
* Add Full Width CSS class options
### 4.0.0: January 4th, 2012
* Add theme activation options
* HTML5 Boilerplate updates
* Add CSS frameworks: Bootstrap, Foundation
* Add translations: Dutch, Italian, Macedonian, German, Finnish, Danish, Spanish, and Turkish
* Update jQuery
* Remove included jQuery plugins
* Clean up whitespace, switched to two spaces for tabs
* Clean up `body_class()` some more with `roots_body_class()`
* Post meta information is now displayed using a function (similar to Twenty Eleven)
* Bugfixes for 1140 options
* Add first and last classes to widgets
* Fix bug with initial options save
* Remove sitemap and listing subpages templates
* Child themes can now unregister sidebars
* Add fix for empty search query
* Update README
* Blocking access to readme.html and license.txt to hide WordPress version information
### 3.6.0: August 12th, 2011
* HTML5 Boilerplate 2.0 updates
* Cleaner output of enqueued styles and scripts
* Adde option for root relative URLs
* Small fixes to root relative URLs and clean assets
* Update included jQuery plugins
* Add French translation (thanks @johnraz)
* Add Brazilian Portuguese translation (thanks @weslly)
* Switch the logo to use `add_custom_image_header`
* Add a function that strips unnecessary self-closing tags
* Code cleanup and re-organization
### 3.5.0: July 30th, 2011
* Complete rewrite of theme options based on Twenty Eleven
* CSS frameworks: refactor code and add default classes for each framework
* CSS frameworks: add support for Adapt.js and LESS
* CSS frameworks: add option for None
* Add support for WPML and theme translation
* Add option for cleaner nav menu output
* Add option for FOUT-B-Gone
* Add authorship rel attribute to post author link
* Activation bugfix for pages being added multiple times
* Bugfixes to the root relative URL function
* Child themes will now load their CSS automatically and properly
* HTML5 Boilerplate updates (including Normalize.css, Modernizr 2.0, and Respond.js)
* Introduce cleaner way of including HTML5 Boilerplate's `.htaccess`
* Add hooks &amp; actions
* Rename `includes/` directory to `inc/`
* Add a blank `inc/roots-custom.php` file
### 3.2.4: May 19th, 2011
* Bugfixes
* Match latest changes to HTML5 Boilerplate and Blueprint CSS
* Update jQuery to 1.6.1
### 3.2.3: May 10th, 2011
* Bugfixes
* Add `language_attributes()` to `<html>`
* Match latest changes to HTML5 Boilerplate and Blueprint CSS
* Update jQuery to 1.6
### 3.2.2: April 24th, 2011
* Bugfixes
### 3.2.1: April 20th, 2011
* Add support for child themes
### 3.2.0: April 15th, 2011
* Add support for the 1140px Grid
* Update the conditional comment code to match latest changes to HTML5 Boilerplate
### 3.1.1: April 7th, 2011
* Fix relative path function to work correctly when WordPress is installed in a subdirectory
* Update jQuery to 1.5.2
* Fix comments to show avatars correctly
### 3.1.0: April 1st, 2011
* Add support for 960.gs thanks to John Liuti
* Add more onto the `.htaccess` from HTML5 Boilerplate
* Allow the theme directory and name to be renamable
### 3.0.0: March 28th, 2011
* Change name from BB to Roots and release to the public
* Update various areas to match the latest changes to HTML5 Boilerplate
* Change the theme markup based on hCard/Readability Guidelines and work by Jonathan Neal
* Create the navigation menus and automatically set their locations during theme activation
* Set permalink structure to `/%year%/%postname%/`
* Set uploads folder to `/assets/`
* Rewrite static folders in `/wp-content/themes/roots/` (`css/`, `js/`, `img/`) to the root (`/css/`, `/js/`, `/img/`)
* Rewrite `/wp-content/plugins/` to `/plugins/`
* Add more root relative URLs on WordPress functions
* Search results (`/?s=query`) rewrite to `/search/query/`
* `l10n.js` is deregistered
* Change [gallery] to output `<figure>` and `<figcaption>` and link to file by default
* Add more `loop.php` templates
* Made the HTML editor have a monospaced font
* Add `front-page.php`
* Update CSS for Gravity Forms 1.5
* Add `searchform.php template`
### 2.4.0: January 25th, 2011
* Add a notification when saving the theme settings
* Add support for navigation menus
* Create function that makes sure there is a Home page on theme activation
* Update various areas to match the latest changes to HTML5 Boilerplate
### 2.3.0: December 8th, 2010
* Logo is no longer an `<h1>`
* Add ARIA roles again
* Change `ul#nav` to `nav#nav-main`
* Add vCard to footer
* Made all URL's root relative
* Add Twitter and Facebook widgets to footer
* Add SEO optimized `robots.txt` from WordPress codex
### 2.2.0: September 20th, 2010
* Add asynchronous Google Analytics
* Update `.htaccess` with latest changes from HTML5 Boilerplate
### 2.1.0: August 19th, 2010
* Remove optimizeLegibility from headings
* Update jQuery to latest version
* Implement HTML5 Boilerplate `.htaccess`
### 2.0.1: August 2nd, 2010
* Add some presentational CSS classes
* Add footer widget
* Add more Gravity Forms default styling
### 2.0.0: July 19th, 2010
* Add HTML5 Boilerplate changes
* Implement `loop.php`
* wp_head cleanup
* Add `page-subpages.php` template
### 1.5.0: April 15th, 2010
* Integrate Paul Irish's frontend-pro-template (the original HTML5 Boilerplate)
### 1.0.0: December 18th, 2009
* Add Blueprint CSS to Starkers

19
LICENSE.md

@ -0,0 +1,19 @@
Copyright (c) Ben Word and Scott Walkinshaw
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

124
README.md

@ -0,0 +1,124 @@
# [Sage](https://roots.io/sage/)
[![Packagist](https://img.shields.io/packagist/vpre/roots/sage.svg?style=flat-square)](https://packagist.org/packages/roots/sage)
[![devDependency Status](https://img.shields.io/david/dev/roots/sage.svg?style=flat-square)](https://david-dm.org/roots/sage#info=devDependencies)
[![Build Status](https://img.shields.io/travis/roots/sage.svg?style=flat-square)](https://travis-ci.org/roots/sage)
Sage is a WordPress starter theme with a modern development workflow.
**Sage 9 is in active development and is currently in beta. The `master` branch tracks Sage 9 development. If you want a stable version, use the [latest Sage 8 release](https://github.com/roots/sage/releases/latest).**
## Features
* Sass for stylesheets
* ES6 for JavaScript
* [Webpack](https://webpack.github.io/) for compiling assets, optimizing images, and concatenating and minifying files
* [Browsersync](http://www.browsersync.io/) for synchronized browser testing
* [Laravel Blade](https://laravel.com/docs/5.3/blade) as a templating engine
* [Controller](https://github.com/soberwp/controller) for passing data to Blade templates
* CSS framework options:
* [Bootstrap 4](http://getbootstrap.com/)
* [Foundation](http://foundation.zurb.com/)
* [Tachyons](http://tachyons.io/)
* None (blank slate)
* Font Awesome (optional)
See a working example at [roots-example-project.com](https://roots-example-project.com/).
## Requirements
Make sure all dependencies have been installed before moving on:
* [WordPress](https://wordpress.org/) >= 4.7
* [PHP](http://php.net/manual/en/install.php) >= 5.6.4
* [Composer](https://getcomposer.org/download/)
* [Node.js](http://nodejs.org/) >= 6.9.x
* [Yarn](https://yarnpkg.com/en/docs/install)
## Theme installation
Install Sage using Composer from your WordPress themes directory (replace `your-theme-name` below with the name of your theme):
```shell
# @ app/themes/ or wp-content/themes/
$ composer create-project roots/sage your-theme-name dev-master
```
During theme installation you will have the options to:
* Update theme headers (theme name, description, author, etc.)
* Select a CSS framework (Bootstrap, Foundation, Tachyons, none)
* Add Font Awesome
* Configure Browsersync (path to theme, local development URL)
## Theme structure
```shell
themes/your-theme-name/ # → Root of your Sage based theme
├── app/ # → Theme PHP
│ ├── lib/Sage/ # → Blade implementation, asset manifest
│ ├── admin.php # → Theme customizer setup
│ ├── filters.php # → Theme filters
│ ├── helpers.php # → Helper functions
│ └── setup.php # → Theme setup
├── composer.json # → Autoloading for `app/` files
├── composer.lock # → Composer lock file (never edit)
├── dist/ # → Built theme assets (never edit)
├── node_modules/ # → Node.js packages (never edit)
├── package.json # → Node.js dependencies and scripts
├── resources/ # → Theme assets and templates
│ ├── assets/ # → Front-end assets
│ │ ├── config.json # → Settings for compiled assets
│ │ ├── build/ # → Webpack and ESLint config
│ │ ├── fonts/ # → Theme fonts
│ │ ├── images/ # → Theme images
│ │ ├── scripts/ # → Theme JS
│ │ └── styles/ # → Theme stylesheets
│ ├── controllers/ # → Controller files
│ ├── functions.php # → Composer autoloader, theme includes
│ ├── index.php # → Never manually edit
│ ├── screenshot.png # → Theme screenshot for WP admin
│ ├── style.css # → Theme meta information
│ └── views/ # → Theme templates
│ ├── layouts/ # → Base templates
│ └── partials/ # → Partial templates
└── vendor/ # → Composer packages (never edit)
```
## Theme setup
Edit `app/setup.php` to enable or disable theme features, setup navigation menus, post thumbnail sizes, and sidebars.
## Theme development
* Run `yarn` from the theme directory to install dependencies
* Update `resources/assets/config.json` settings:
* `devUrl` should reflect your local development hostname
* `publicPath` should reflect your WordPress folder structure (`/wp-content/themes/sage` for non-[Bedrock](https://roots.io/bedrock/) installs)
### Build commands
* `yarn run start` — Compile assets when file changes are made, start Browsersync session
* `yarn run build` — Compile and optimize the files in your assets directory
* `yarn run build:production` — Compile assets for production
## Documentation
Sage 8 documentation is available at [https://roots.io/sage/docs/](https://roots.io/sage/docs/).
Sage 9 documentation is currently in progress and can be viewed at [https://github.com/roots/docs/tree/sage-9/sage](https://github.com/roots/docs/tree/sage-9/sage).
Controller documentation is available at [https://github.com/soberwp/controller#usage](https://github.com/soberwp/controller#usage).
## Contributing
Contributions are welcome from everyone. We have [contributing guidelines](https://github.com/roots/guidelines/blob/master/CONTRIBUTING.md) to help you get started.
## Community
Keep track of development and community news.
* Participate on the [Roots Discourse](https://discourse.roots.io/)
* Follow [@rootswp on Twitter](https://twitter.com/rootswp)
* Read and subscribe to the [Roots Blog](https://roots.io/blog/)
* Subscribe to the [Roots Newsletter](https://roots.io/subscribe/)
* Listen to the [Roots Radio podcast](https://roots.io/podcast/)

24
app/admin.php

@ -0,0 +1,24 @@
<?php
namespace App;
/**
* Theme customizer
*/
add_action('customize_register', function (\WP_Customize_Manager $wp_customize) {
// Add postMessage support
$wp_customize->get_setting('blogname')->transport = 'postMessage';
$wp_customize->selective_refresh->add_partial('blogname', [
'selector' => '.brand',
'render_callback' => function () {
bloginfo('name');
}
]);
});
/**
* Customizer JS
*/
add_action('customize_preview_init', function () {
wp_enqueue_script('sage/customizer.js', asset_path('scripts/customizer.js'), ['customize-preview'], null, true);
});

70
app/filters.php

@ -0,0 +1,70 @@
<?php
namespace App;
/**
* Add <body> 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';
}
/** Clean up class names for custom templates */
$classes = array_map(function ($class) {
return preg_replace(['/-blade(-php)?$/', '/^page-template-views/'], '', $class);
}, $classes);
return array_filter($classes);
});
/**
* Add "… Continued" to the excerpt
*/
add_filter('excerpt_more', function () {
return ' &hellip; <a href="' . get_permalink() . '">' . __('Continued', 'sage') . '</a>';
});
/**
* Template Hierarchy should search for .blade.php files
*/
collect([
'index', '404', 'archive', 'author', 'category', 'tag', 'taxonomy', 'date', 'home',
'frontpage', 'page', 'paged', 'search', 'single', 'singular', 'attachment'
])->map(function ($type) {
add_filter("{$type}_template_hierarchy", __NAMESPACE__.'\\filter_templates');
});
/**
* Render page using Blade
*/
add_filter('template_include', function ($template) {
$data = collect(get_body_class())->reduce(function ($data, $class) use ($template) {
return apply_filters("sage/template/{$class}/data", $data, $template);
}, []);
if ($template) {
echo template($template, $data);
return get_stylesheet_directory().'/index.php';
}
return $template;
}, PHP_INT_MAX);
/**
* Tell WordPress how to find the compiled path of comments.blade.php
*/
add_filter('comments_template', function ($comments_template) {
$comments_template = str_replace(
[get_stylesheet_directory(), get_template_directory()],
'',
$comments_template
);
return template_path(locate_template(["views/{$comments_template}", $comments_template]) ?: $comments_template);
});

147
app/helpers.php

@ -0,0 +1,147 @@
<?php
namespace App;
use Roots\Sage\Container;
/**
* Get the sage container.
*
* @param string $abstract
* @param array $parameters
* @param Container $container
* @return Container|mixed
*/
function sage($abstract = null, $parameters = [], Container $container = null)
{
$container = $container ?: Container::getInstance();
if (!$abstract) {
return $container;
}
return $container->bound($abstract)
? $container->makeWith($abstract, $parameters)
: $container->makeWith("sage.{$abstract}", $parameters);
}
/**
* Get / set the specified configuration value.
*
* If an array is passed as the key, we will assume you want to set an array of values.
*
* @param array|string $key
* @param mixed $default
* @return mixed|\Roots\Sage\Config
* @copyright Taylor Otwell
* @link https://github.com/laravel/framework/blob/c0970285/src/Illuminate/Foundation/helpers.php#L254-L265
*/
function config($key = null, $default = null)
{
if (is_null($key)) {
return sage('config');
}
if (is_array($key)) {
return sage('config')->set($key);
}
return sage('config')->get($key, $default);
}
/**
* @param string $file
* @param array $data
* @return string
*/
function template($file, $data = [])
{
return sage('blade')->render($file, $data);
}
/**
* Retrieve path to a compiled blade view
* @param $file
* @param array $data
* @return string
*/
function template_path($file, $data = [])
{
return sage('blade')->compiledPath($file, $data);
}
/**
* @param $asset
* @return string
*/
function asset_path($asset)
{
return sage('assets')->getUri($asset);
}
/**
* @param string|string[] $templates Possible template files
* @return array
*/
function filter_templates($templates)
{
return collect($templates)
->map(function ($template) {
return preg_replace('#\.(blade\.)?php$#', '', ltrim($template));
})
->flatMap(function ($template) {
$paths = apply_filters('sage/filter_templates/paths', ['views', 'resources/views']);
return collect($paths)
->flatMap(function ($path) use ($template) {
return [
"{$path}/{$template}.blade.php",
"{$path}/{$template}.php",
"{$template}.blade.php",
"{$template}.php",
];
});
})
->filter()
->unique()
->all();
}
/**
* @param string|string[] $templates Relative path to possible template files
* @return string Location of the template
*/
function locate_template($templates)
{
return \locate_template(filter_templates($templates));
}
/**
* Determine whether to show the sidebar
* @return bool
*/
function display_sidebar()
{
static $display;
isset($display) || $display = apply_filters('sage/display_sidebar', false);
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();
}

128
app/setup.php

@ -0,0 +1,128 @@
<?php
namespace App;
use Roots\Sage\Container;
use Roots\Sage\Assets\JsonManifest;
use Roots\Sage\Template\Blade;
use Roots\Sage\Template\BladeProvider;
/**
* Theme assets
*/
add_action('wp_enqueue_scripts', function () {
wp_enqueue_style('sage/main.css', asset_path('styles/main.css'), false, null);
wp_enqueue_script('sage/main.js', asset_path('scripts/main.js'), ['jquery'], null, true);
}, 100);
/**
* Theme setup
*/
add_action('after_setup_theme', function () {
/**
* Enable features from Soil when plugin is activated
* @link https://roots.io/plugins/soil/
*/
add_theme_support('soil-clean-up');
add_theme_support('soil-jquery-cdn');
add_theme_support('soil-nav-walker');
add_theme_support('soil-nice-search');
add_theme_support('soil-relative-urls');
/**
* Enable plugins to manage the document title
* @link https://developer.wordpress.org/reference/functions/add_theme_support/#title-tag
*/
add_theme_support('title-tag');
/**
* Register navigation menus
* @link https://developer.wordpress.org/reference/functions/register_nav_menus/
*/
register_nav_menus([
'primary_navigation' => __('Primary Navigation', 'sage')
]);
/**
* Enable post thumbnails
* @link https://developer.wordpress.org/themes/functionality/featured-images-post-thumbnails/
*/
add_theme_support('post-thumbnails');
/**
* Enable HTML5 markup support
* @link https://developer.wordpress.org/reference/functions/add_theme_support/#html5
*/
add_theme_support('html5', ['caption', 'comment-form', 'comment-list', 'gallery', 'search-form']);
/**
* Enable selective refresh for widgets in customizer
* @link https://developer.wordpress.org/themes/advanced-topics/customizer-api/#theme-support-in-sidebars
*/
add_theme_support('customize-selective-refresh-widgets');
/**
* Use main stylesheet for visual editor
* @see resources/assets/styles/layouts/_tinymce.scss
*/
add_editor_style(asset_path('styles/main.css'));
}, 20);
/**
* Register sidebars
*/
add_action('widgets_init', function () {
$config = [
'before_widget' => '<section class="widget %1$s %2$s">',
'after_widget' => '</section>',
'before_title' => '<h3>',
'after_title' => '</h3>'
];
register_sidebar([
'name' => __('Primary', 'sage'),
'id' => 'sidebar-primary'
] + $config);
register_sidebar([
'name' => __('Footer', 'sage'),
'id' => 'sidebar-footer'
] + $config);
});
/**
* Updates the `$post` variable on each iteration of the loop.
* Note: updated value is only available for subsequently loaded views, such as partials
*/
add_action('the_post', function ($post) {
sage('blade')->share('post', $post);
});
/**
* Setup Sage options
*/
add_action('after_setup_theme', function () {
/**
* Add JsonManifest to Sage container
*/
sage()->singleton('sage.assets', function () {
return new JsonManifest(config('assets.manifest'), config('assets.uri'));
});
/**
* Add Blade to Sage container
*/
sage()->singleton('sage.blade', function (Container $app) {
$cachePath = config('view.compiled');
if (!file_exists($cachePath)) {
wp_mkdir_p($cachePath);
}
(new BladeProvider($app))->register();
return new Blade($app['view']);
});
/**
* Create @asset() Blade directive
*/
sage('blade')->compiler()->directive('asset', function ($asset) {
return "<?= " . __NAMESPACE__ . "\\asset_path({$asset}); ?>";
});
});

50
composer.json

@ -0,0 +1,50 @@
{
"name": "pressbooks/pressbooks-aldine",
"type": "wordpress-theme",
"license": "MIT",
"description": "WordPress starter theme with a modern development workflow",
"homepage": "https://roots.io/sage/",
"authors": [
{
"name": "Ben Word",
"email": "ben@benword.com",
"homepage": "https://github.com/retlehs"
},
{
"name": "Scott Walkinshaw",
"email": "scott.walkinshaw@gmail.com",
"homepage": "https://github.com/swalkinshaw"
}
],
"keywords": [
"wordpress"
],
"support": {
"issues": "https://github.com/roots/sage/issues",
"forum": "https://discourse.roots.io/"
},
"autoload": {
"psr-4": {
"App\\": "app/"
}
},
"require": {
"php": ">=5.6.4",
"composer/installers": "~1.0",
"illuminate/support": "~5.4",
"roots/sage-lib": "~9.0.0-beta.3",
"soberwp/controller": "dev-master"
},
"require-dev": {
"squizlabs/php_codesniffer": "^2.8.0",
"roots/sage-installer": "~1.1"
},
"scripts": {
"test": [
"phpcs"
],
"post-create-project-cmd": [
"Roots\\Sage\\Installer\\ComposerScript::postCreateProject"
]
}
}

1489
composer.lock generated

File diff suppressed because it is too large Load Diff

31
config/assets.php

@ -0,0 +1,31 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Assets Manifest
|--------------------------------------------------------------------------
|
| Your asset manifest is used by Sage to assist WordPress and your views
| with rendering the correct URLs for your assets. This is especially
| useful for statically referencing assets with dynamically changing names
| as in the case of cache-busting.
|
*/
'manifest' => get_theme_file_path().'/dist/assets.json',
/*
|--------------------------------------------------------------------------
| Assets Path URI
|--------------------------------------------------------------------------
|
| The asset manifest contains relative paths to your assets. This URI will
| be prepended when using Sage's asset management system. Change this if
| you are using a CDN.
|
*/
'uri' => get_theme_file_uri().'/dist',
];

32
config/theme.php

@ -0,0 +1,32 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Theme Directory
|--------------------------------------------------------------------------
|
| This is the absolute path to your theme directory.
|
| Example:
| /srv/www/example.com/current/web/app/themes/sage
|
*/
'dir' => get_theme_file_path(),
/*
|--------------------------------------------------------------------------
| Theme Directory URI
|--------------------------------------------------------------------------
|
| This is the web server URI to your theme directory.
|
| Example:
| https://example.com/app/themes/sage
|
*/
'uri' => get_theme_file_uri(),
];

51
config/view.php

@ -0,0 +1,51 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| View Storage Paths
|--------------------------------------------------------------------------
|
| Most template systems load templates from disk. Here you may specify
| an array of paths that should be checked for your views.
|
*/
'paths' => [
get_theme_file_path().'/resources/views',
get_parent_theme_file_path().'/resources/views',
],
/*
|--------------------------------------------------------------------------
| Compiled View Path
|--------------------------------------------------------------------------
|
| This option determines where all the compiled Blade templates will be
| stored for your application. Typically, this is within the uploads
| directory. However, as usual, you are free to change this value.
|
*/
'compiled' => wp_upload_dir()['basedir'].'/cache',
/*
|--------------------------------------------------------------------------
| View Namespaces
|--------------------------------------------------------------------------
|
| Blade has an underutilized feature that allows developers to add
| supplemental view paths that may contain conflictingly named views.
| These paths are prefixed with a namespace to get around the conflicts.
| A use case might be including views from within a plugin folder.
|
*/
'namespaces' => [
/* Given the below example, in your views use something like: @include('WC::some.view.or.partial.here') */
// 'WC' => WP_PLUGIN_DIR.'/woocommerce/templates/',
],
];

131
package.json

@ -0,0 +1,131 @@
{
"name": "sage",
"version": "9.0.0-beta.3",
"author": "Roots <team@roots.io>",
"homepage": "https://roots.io/sage/",
"private": true,
"repository": {
"type": "git",
"url": "git://github.com/roots/sage.git"
},
"bugs": {
"url": "https://github.com/roots/sage/issues"
},
"licenses": [
{
"type": "MIT",
"url": "http://opensource.org/licenses/MIT"
}
],
"browserslist": [
"last 2 versions",
"android 4",
"opera 12"
],
"eslintConfig": {
"root": true,
"extends": "eslint:recommended",
"globals": {
"wp": true
},
"env": {
"node": true,
"es6": true,
"amd": true,
"browser": true,
"jquery": true
},
"parserOptions": {
"ecmaFeatures": {
"globalReturn": true,
"generators": false,
"objectLiteralDuplicateProperties": false,
"experimentalObjectRestSpread": true
},
"ecmaVersion": 2017,
"sourceType": "module"
},
"plugins": [
"import"
],
"settings": {
"import/core-modules": [],
"import/ignore": [
"node_modules",
"\\.(coffee|scss|css|less|hbs|svg|json)$"
]
},
"rules": {
"comma-dangle": [
"error",
{
"arrays": "always-multiline",
"objects": "always-multiline",
"imports": "always-multiline",
"exports": "always-multiline",
"functions": "ignore"
}
]
}
},
"stylelint": {
"extends": "stylelint-config-standard",
"rules": {
"no-empty-source": null
}
},
"scripts": {
"build": "webpack --progress --config resources/assets/build/webpack.config.js",
"build:production": "webpack --progress -p --config resources/assets/build/webpack.config.js",
"build:profile": "webpack --progress --profile --json --config resources/assets/build/webpack.config.js",
"start": "webpack --hide-modules --watch --config resources/assets/build/webpack.config.js",
"rmdist": "rimraf dist",
"lint": "npm run -s lint:scripts && npm run -s lint:styles",
"lint:scripts": "eslint resources/assets/scripts resources/assets/build",
"lint:styles": "stylelint resources/assets/styles/**/*.{css,sass,scss,sss,less}",
"test": "npm run -s lint"
},
"engines": {
"node": ">= 6.9.4"
},
"devDependencies": {
"autoprefixer": "~7.1",
"browser-sync": "~2.18",
"browsersync-webpack-plugin": "^0.6.0",
"bs-html-injector": "~3.0",
"buble-loader": "^0.4.1",
"cache-loader": "~1.0",
"clean-webpack-plugin": "^0.1.16",
"copy-globs-webpack-plugin": "^0.2.0",
"css-loader": "^0.28.4",
"cssnano": "~4.0.0-rc.1",
"eslint": "~4.2",
"eslint-loader": "~1.9",
"eslint-plugin-import": "~2.7",
"extract-text-webpack-plugin": "~3.0",
"file-loader": "^0.11.2",
"imagemin-mozjpeg": "~6.0",
"imagemin-webpack-plugin": "~1.5.0-beta.0",
"import-glob": "~1.5",
"node-sass": "~4.5",
"postcss-loader": "~2.0",
"postcss-safe-parser": "~3.0",
"resolve-url-loader": "~2.1",
"rimraf": "~2.6",
"sass-loader": "~6.0",
"style-loader": "^0.18.2",
"stylelint": "~7.12",
"stylelint-config-standard": "~16.0",
"stylelint-webpack-plugin": "^0.8.0",
"url-loader": "^0.5.9",
"webpack": "~3.3",
"webpack-assets-manifest": "^0.7.0",
"webpack-dev-middleware": "~1.11",
"webpack-hot-middleware": "~2.18",
"webpack-merge": "~4.1",
"yargs": "~8.0"
},
"dependencies": {
"jquery": "1.12.4 - 3"
}
}

71
phpcs.xml

@ -0,0 +1,71 @@
<?xml version="1.0"?>
<ruleset name="Roots">
<description>Roots Coding Standards</description>
<!-- Scan these files -->
<file>resources/functions.php</file>
<file>resources/index.php</file>
<file>app</file>
<file>resources/views</file>
<!-- Show colors in console -->
<arg value="-colors"/>
<!-- Show sniff codes in all reports -->
<arg value="s"/>
<!-- Use PSR-2 as a base -->
<rule ref="PSR2"/>
<!-- Exclusions below are for resources/views/ folder -->
<!-- Allow php files without any PHP in them -->
<rule ref="Internal.NoCodeFound">
<exclude-pattern>resources/views</exclude-pattern>
</rule>
<!-- Allow braces on same line for named functions -->
<rule ref="Squiz.Functions.MultiLineFunctionDeclaration.BraceOnSameLine">
<exclude-pattern>resources/views</exclude-pattern>
</rule>
<!-- Allow closing braces to be on the same line -->
<rule ref="Squiz.WhiteSpace.ScopeClosingBrace">
<exclude-pattern>resources/views</exclude-pattern>
</rule>
<!-- Disable newline after opening brace -->
<rule ref="Squiz.ControlStructures.ControlSignature.NewlineAfterOpenBrace">
<exclude-pattern>resources/views</exclude-pattern>
</rule>
<!-- Allow multiple PHP statements in the same line -->
<rule ref="Generic.Formatting.DisallowMultipleStatements.SameLine">
<exclude-pattern>resources/views</exclude-pattern>
</rule>
<!-- Disable PSR-2 indentation rules that are buggy with 2 spaces -->
<rule ref="PSR2.ControlStructures.SwitchDeclaration.BreakIndent">
<exclude-pattern>resources/views</exclude-pattern>
</rule>
<!-- Don't require a blank line after the last `use` -->
<rule ref="PSR2.Namespaces.UseDeclaration.SpaceAfterLastUse">
<exclude-pattern>resources/views</exclude-pattern>
</rule>
<!-- Allow long lines -->
<rule ref="Generic.Files.LineLength.TooLong">
<exclude-pattern>resources/views</exclude-pattern>
</rule>
<!-- Ignore indentation rules -->
<rule ref="Generic.WhiteSpace.ScopeIndent">
<exclude-pattern>resources/views</exclude-pattern>
</rule>
<!-- Allow PHP closing tags -->
<rule ref="PSR2.Files.ClosingTag.NotAllowed">
<exclude-pattern>resources/views</exclude-pattern>
</rule>
</ruleset>

14
resources/assets/build/.eslintrc

@ -0,0 +1,14 @@
{
"root": false,
"rules": {
"import/no-extraneous-dependencies": 0,
"prefer-rest-params": 0,
"comma-dangle": ["error", {
"arrays": "always-multiline",
"objects": "always-multiline",
"imports": "always-multiline",
"exports": "always-multiline",
"functions": "ignore"
}]
}
}

60
resources/assets/build/config.js

@ -0,0 +1,60 @@
const path = require('path');
const { argv } = require('yargs');
const merge = require('webpack-merge');
const desire = require('./util/desire');
const userConfig = merge(desire(`${__dirname}/../config`), desire(`${__dirname}/../config-local`));
const isProduction = !!((argv.env && argv.env.production) || argv.p);
const rootPath = (userConfig.paths && userConfig.paths.root)
? userConfig.paths.root
: process.cwd();
const config = merge({
open: true,
copy: 'images/**/*',
proxyUrl: 'http://localhost:3000',
cacheBusting: '[name]_[hash]',
paths: {
root: rootPath,
assets: path.join(rootPath, 'resources/assets'),
dist: path.join(rootPath, 'dist'),
},
enabled: {
sourceMaps: !isProduction,
optimize: isProduction,
cacheBusting: isProduction,
watcher: !!argv.watch,
},
watch: [],
}, userConfig);
module.exports = merge(config, {
env: Object.assign({ production: isProduction, development: !isProduction }, argv.env),
publicPath: `${config.publicPath}/${path.basename(config.paths.dist)}/`,
manifest: {},
});
if (process.env.NODE_ENV === undefined) {
process.env.NODE_ENV = isProduction ? 'production' : 'development';
}
/**
* If your publicPath differs between environments, but you know it at compile time,
* then set SAGE_DIST_PATH as an environment variable before compiling.
* Example:
* SAGE_DIST_PATH=/wp-content/themes/sage/dist yarn build:production
*/
if (process.env.SAGE_DIST_PATH) {
module.exports.publicPath = process.env.SAGE_DIST_PATH;
}
/**
* If you don't know your publicPath at compile time, then uncomment the lines
* below and use WordPress's wp_localize_script() to set SAGE_DIST_PATH global.
* Example:
* wp_localize_script('sage/main.js', 'SAGE_DIST_PATH', get_theme_file_uri('dist/'))
*/
// Object.keys(module.exports.entry).forEach(id =>
// module.exports.entry[id].unshift(path.join(__dirname, 'helpers/public-path.js')));

7
resources/assets/build/helpers/hmr-client.js

@ -0,0 +1,7 @@
const hotMiddlewareScript = require('webpack-hot-middleware/client?noInfo=true&timeout=20000&reload=true');
hotMiddlewareScript.subscribe(event => {
if (event.action === 'reload') {
window.location.reload();
}
});

7
resources/assets/build/helpers/public-path.js

@ -0,0 +1,7 @@
/* eslint-env browser */
/* globals SAGE_DIST_PATH */
/** Dynamically set absolute public path from current protocol and host */
if (SAGE_DIST_PATH) {
__webpack_public_path__ = SAGE_DIST_PATH; // eslint-disable-line no-undef, camelcase
}

15
resources/assets/build/postcss.config.js

@ -0,0 +1,15 @@
/* eslint-disable */
const cssnanoConfig = {
preset: ['default', { discardComments: { removeAll: true } }]
};
module.exports = ({ file, options }) => {
return {
parser: options.enabled.optimize ? 'postcss-safe-parser' : undefined,
plugins: {
cssnano: options.enabled.optimize ? cssnanoConfig : false,
autoprefixer: true,
},
};
};

15
resources/assets/build/util/addHotMiddleware.js

@ -0,0 +1,15 @@
/**
* Loop through webpack entry
* and add the hot middleware
* @param {Object} entry webpack entry
* @return {Object} entry with hot middleware
*/
module.exports = (entry) => {
const results = {};
Object.keys(entry).forEach((name) => {
results[name] = Array.isArray(entry[name]) ? entry[name].slice(0) : [entry[name]];
results[name].unshift(`${__dirname}/../helpers/hmr-client.js`);
});
return results;
};

34
resources/assets/build/util/assetManifestsFormatter.js

@ -0,0 +1,34 @@
const path = require('path');
module.exports = (key, value) => {
if (typeof value === 'string') {
return value;
}
const manifest = value;
/**
* Hack to prepend scripts/ or styles/ to manifest keys
*
* This might need to be reworked at some point.
*
* Before:
* {
* "main.js": "scripts/main_abcdef.js"
* "main.css": "styles/main_abcdef.css"
* }
* After:
* {
* "scripts/main.js": "scripts/main_abcdef.js"
* "styles/main.css": "styles/main_abcdef.css"
* }
*/
Object.keys(manifest).forEach((src) => {
const sourcePath = path.basename(path.dirname(src));
const targetPath = path.basename(path.dirname(manifest[src]));
if (sourcePath === targetPath) {
return;
}
manifest[`${targetPath}/${src}`] = manifest[src];
delete manifest[src];
});
return manifest;
};

14
resources/assets/build/util/desire.js

@ -0,0 +1,14 @@
/**
* @export
* @param {string} dependency
* @param {any} [fallback]
* @return {any}
*/
module.exports = (dependency, fallback) => {
try {
require.resolve(dependency);
} catch (err) {
return fallback;
}
return require(dependency); // eslint-disable-line import/no-dynamic-require
};

211
resources/assets/build/webpack.config.js

@ -0,0 +1,211 @@
'use strict'; // eslint-disable-line
const webpack = require('webpack');
const merge = require('webpack-merge');
const CleanPlugin = require('clean-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const StyleLintPlugin = require('stylelint-webpack-plugin');
const CopyGlobsPlugin = require('copy-globs-webpack-plugin');
const config = require('./config');
const assetsFilenames = (config.enabled.cacheBusting) ? config.cacheBusting : '[name]';
let webpackConfig = {
context: config.paths.assets,
entry: config.entry,
devtool: (config.enabled.sourceMaps ? '#source-map' : undefined),
output: {
path: config.paths.dist,
publicPath: config.publicPath,
filename: `scripts/${assetsFilenames}.js`,
},
stats: {
hash: false,
version: false,
timings: false,
children: false,
errors: false,
errorDetails: false,
warnings: false,
chunks: false,
modules: false,
reasons: false,
source: false,
publicPath: false,
},
module: {
rules: [
{
enforce: 'pre',
test: /\.js$/,
include: config.paths.assets,
use: 'eslint',
},
{
enforce: 'pre',
test: /\.(js|s?[ca]ss)$/,
include: config.paths.assets,
loader: 'import-glob',
},
{
test: /\.js$/,
exclude: [/(node_modules|bower_components)(?![/|\\](bootstrap|foundation-sites))/],
use: [
{ loader: 'cache' },
{ loader: 'buble', options: { objectAssign: 'Object.assign' } },
],
},
{
test: /\.css$/,
include: config.paths.assets,
use: ExtractTextPlugin.extract({
fallback: 'style',
use: [
{ loader: 'cache' },
{ loader: 'css', options: { sourceMap: config.enabled.sourceMaps } },
{
loader: 'postcss', options: {
config: { path: __dirname, ctx: config },
sourceMap: config.enabled.sourceMaps,
},
},
],
}),
},
{
test: /\.scss$/,
include: config.paths.assets,
use: ExtractTextPlugin.extract({
fallback: 'style',
use: [
{ loader: 'cache' },
{ loader: 'css', options: { sourceMap: config.enabled.sourceMaps } },
{
loader: 'postcss', options: {
config: { path: __dirname, ctx: config },
sourceMap: config.enabled.sourceMaps,
},
},
{ loader: 'resolve-url', options: { sourceMap: config.enabled.sourceMaps } },
{ loader: 'sass', options: { sourceMap: config.enabled.sourceMaps } },
],
}),
},
{
test: /\.(ttf|eot|woff2?|png|jpe?g|gif|svg|ico)$/,
include: config.paths.assets,
loader: 'url',
options: {
limit: 4096,
name: `[path]${assetsFilenames}.[ext]`,
},
},
{
test: /\.(ttf|eot|woff2?|png|jpe?g|gif|svg|ico)$/,
include: /node_modules|bower_components/,
loader: 'url',
options: {
limit: 4096,
outputPath: 'vendor/',
name: `${config.cacheBusting}.[ext]`,
},
},
],
},
resolve: {
modules: [
config.paths.assets,
'node_modules',
'bower_components',
],
enforceExtension: false,
},
resolveLoader: {
moduleExtensions: ['-loader'],
},
externals: {
jquery: 'jQuery',
},
plugins: [
new CleanPlugin([config.paths.dist], {
root: config.paths.root,
verbose: false,
}),
/**
* It would be nice to switch to copy-webpack-plugin, but
* unfortunately it doesn't provide a reliable way of
* tracking the before/after file names
*/
new CopyGlobsPlugin({
pattern: config.copy,
output: `[path]${assetsFilenames}.[ext]`,
manifest: config.manifest,
}),
new ExtractTextPlugin({
filename: `styles/${assetsFilenames}.css`,
allChunks: true,
disable: (config.enabled.watcher),
}),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
Tether: 'tether',
'window.Tether': 'tether',
}),
new webpack.LoaderOptionsPlugin({
minimize: config.enabled.optimize,
debug: config.enabled.watcher,
stats: { colors: true },
}),
new webpack.LoaderOptionsPlugin({
test: /\.s?css$/,
options: {
output: { path: config.paths.dist },
context: config.paths.assets,
},
}),
new webpack.LoaderOptionsPlugin({
test: /\.js$/,
options: {
eslint: { failOnWarning: false, failOnError: true },
},
}),
new StyleLintPlugin({
failOnError: !config.enabled.watcher,
syntax: 'scss',
}),
],
};
/* eslint-disable global-require */ /** Let's only load dependencies as needed */
if (config.enabled.optimize) {
webpackConfig = merge(webpackConfig, require('./webpack.config.optimize'));
}
if (config.env.production) {
webpackConfig.plugins.push(new webpack.NoEmitOnErrorsPlugin());
}
if (config.enabled.cacheBusting) {
const WebpackAssetsManifest = require('webpack-assets-manifest');
webpackConfig.plugins.push(
new WebpackAssetsManifest({
output: 'assets.json',
space: 2,
writeToDisk: false,
assets: config.manifest,
replacer: require('./util/assetManifestsFormatter'),
})
);
}
if (config.enabled.watcher) {
webpackConfig.entry = require('./util/addHotMiddleware')(webpackConfig.entry);
webpackConfig = merge(webpackConfig, require('./webpack.config.watch'));
}
module.exports = webpackConfig;

19
resources/assets/build/webpack.config.optimize.js

@ -0,0 +1,19 @@
'use strict'; // eslint-disable-line
const { default: ImageminPlugin } = require('imagemin-webpack-plugin');
const imageminMozjpeg = require('imagemin-mozjpeg');
const config = require('./config');
module.exports = {
plugins: [
new ImageminPlugin({
optipng: { optimizationLevel: 7 },
gifsicle: { optimizationLevel: 3 },
pngquant: { quality: '65-90', speed: 4 },
svgo: { removeUnknownsAndDefaults: false, cleanupIDs: false },
plugins: [imageminMozjpeg({ quality: 75 })],
disable: (config.enabled.watcher),
}),
],
};

35
resources/assets/build/webpack.config.watch.js

@ -0,0 +1,35 @@
const url = require('url');
const webpack = require('webpack');
const BrowserSyncPlugin = require('browsersync-webpack-plugin');
const config = require('./config');
const target = process.env.DEVURL || config.devUrl;
/**
* We do this to enable injection over SSL.
*/
if (url.parse(target).protocol === 'https:') {
process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0;
}
module.exports = {
output: {
pathinfo: true,
publicPath: config.proxyUrl + config.publicPath,
},
devtool: '#cheap-module-source-map',
stats: false,
plugins: [
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new BrowserSyncPlugin({
target,
open: config.open,
proxyUrl: config.proxyUrl,
watch: config.watch,
delay: 500,
}),
],
};

21
resources/assets/config.json

@ -0,0 +1,21 @@
{
"entry": {
"main": [
"./scripts/main.js",
"./styles/main.scss"
],
"customizer": [
"./scripts/customizer.js"
]
},
"publicPath": "app/themes/pressbooks-aldine",
"devUrl": "https://pressbooks.dev",
"proxyUrl": "http://localhost:3000",
"cacheBusting": "[name]_[hash:8]",
"watch": [
"app/**/*.php",
"config/**/*.php",
"resources/controllers/**/*.php",
"resources/views/**/*.php"
]
}

0
resources/assets/fonts/.gitkeep

0
resources/assets/images/.gitkeep

5
resources/assets/scripts/customizer.js

@ -0,0 +1,5 @@
import $ from 'jquery';
wp.customize('blogname', (value) => {
value.bind(to => $('.brand').text(to));
});

24
resources/assets/scripts/main.js

@ -0,0 +1,24 @@
// import external dependencies
import 'jquery';
// Import everything from autoload
import "./autoload/**/*"
// import local dependencies
import Router from './util/Router';
import common from './routes/common';
import home from './routes/home';
import aboutUs from './routes/about';
/** Populate Router instance with DOM routes */
const routes = new Router({
// All pages
common,
// Home page
home,
// About Us page, note the change from about-us to aboutUs.
aboutUs,
});
// Load Events
jQuery(document).ready(() => routes.loadEvents());

5
resources/assets/scripts/routes/about.js

@ -0,0 +1,5 @@
export default {
init() {
// JavaScript to be fired on the about us page
},
};

8
resources/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
},
};

8
resources/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
},
};

63
resources/assets/scripts/util/Router.js

@ -0,0 +1,63 @@
import camelCase from './camelCase';
/**
* DOM-based Routing
*
* Based on {@link http://goo.gl/EUTi53|Markup-based Unobtrusive Comprehensive DOM-ready Execution} by Paul Irish
*
* 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
*/
class Router {
/**
* Create a new Router
* @param {Object} routes
*/
constructor(routes) {
this.routes = routes;
}
/**
* Fire Router events
* @param {string} route DOM-based route derived from body classes (`<body class="...">`)
* @param {string} [event] Events on the route. By default, `init` and `finalize` events are called.
* @param {string} [arg] Any custom argument to be passed to the event.
*/
fire(route, event = 'init', arg) {
const fire = route !== '' && this.routes[route] && typeof this.routes[route][event] === 'function';
if (fire) {
this.routes[route][event](arg);
}
}
/**
* Automatically load and fire Router events
*
* Events are fired in the following order:
* * common init
* * page-specific init
* * page-specific finalize
* * common finalize
*/
loadEvents() {
// Fire common init JS
this.fire('common');
// Fire page-specific init JS, and then finalize JS
document.body.className
.toLowerCase()
.replace(/-/g, '_')
.split(/\s+/)
.map(camelCase)
.forEach((className) => {
this.fire(className);
this.fire(className, 'finalize');
});
// Fire common finalize JS
this.fire('common', 'finalize');
}
}
export default Router

9
resources/assets/scripts/util/camelCase.js

@ -0,0 +1,9 @@
/**
* the most terrible camelizer on the internet, guaranteed!
* @param {string} str String that isn't camel-case, e.g., CAMeL_CaSEiS-harD
* @return {string} String converted to camel-case, e.g., camelCaseIsHard
*/
export default str => `${str.charAt(0).toLowerCase()}${str.replace(/[\W_]/g, '|').split('|')
.map(part => `${part.charAt(0).toUpperCase()}${part.slice(1)}`)
.join('')
.slice(1)}`;

0
resources/assets/styles/common/_global.scss

5
resources/assets/styles/common/_variables.scss

@ -0,0 +1,5 @@
/** Colors */
$brand-primary: #27ae60;
/** Box Model */
$spacer: 2rem;

0
resources/assets/styles/components/_buttons.scss

5
resources/assets/styles/components/_comments.scss

@ -0,0 +1,5 @@
// TODO: .comment-list {}
// TODO: .comment-list ol {}
// TODO: .comment-form p {}
// TODO: .comment-form input {}
// TODO: .comment-form textarea {}

5
resources/assets/styles/components/_forms.scss

@ -0,0 +1,5 @@
/** Search form */
// TODO: .search-form {}
// TODO: .search-form label {}
// TODO: .search-form .search-field {}
// TODO: .search-form .search-submit {}

56
resources/assets/styles/components/_wp-classes.scss

@ -0,0 +1,56 @@
/**
* WordPress Generated Classes
* @see http://codex.wordpress.org/CSS#WordPress_Generated_Classes
*/
/** Media alignment */
.alignnone {
margin-left: 0;
margin-right: 0;
max-width: 100%;
height: auto;
}
.aligncenter {
display: block;
margin: ($spacer / 2) auto;
height: auto;
}
.alignleft,
.alignright {
margin-bottom: ($spacer / 2);
height: auto;
}
@media (min-width: 30rem) {
.alignleft {
float: left;
margin-right: ($spacer / 2);
}
.alignright {
float: right;
margin-left: ($spacer / 2);
}
}
/** Captions */
// TODO: .wp-caption {}
// TODO: .wp-caption img {}
// TODO: .wp-caption-text {}
/** Text meant only for screen readers */
.screen-reader-text {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
color: #000;
background: #fff;
}

0
resources/assets/styles/layouts/_footer.scss

2
resources/assets/styles/layouts/_header.scss

@ -0,0 +1,2 @@
// TODO: .banner .nav li {}
// TODO: .banner .nav a {}

0
resources/assets/styles/layouts/_pages.scss

0
resources/assets/styles/layouts/_posts.scss

0
resources/assets/styles/layouts/_sidebar.scss

3
resources/assets/styles/layouts/_tinymce.scss

@ -0,0 +1,3 @@
body#tinymce {
margin: 12px !important;
}

25
resources/assets/styles/main.scss

@ -0,0 +1,25 @@
@import "common/variables";
/** Import everything from autoload */
@import "./autoload/**/*";
/**
* Import npm dependencies
*
* Prefix your imports with `~` to grab from node_modules/
* @see https://github.com/webpack-contrib/sass-loader#imports
*/
// @import "~some-node-module";
/** Import theme styles */
@import "common/global";
@import "components/buttons";
@import "components/comments";
@import "components/forms";
@import "components/wp-classes";
@import "layouts/header";
@import "layouts/sidebar";
@import "layouts/footer";
@import "layouts/pages";
@import "layouts/posts";
@import "layouts/tinymce";

10
resources/controllers/About.php

@ -0,0 +1,10 @@
<?php
namespace App;
use Sober\Controller\Controller;
class About extends Controller
{
}

13
resources/controllers/App.php

@ -0,0 +1,13 @@
<?php
namespace App;
use Sober\Controller\Controller;
class App extends Controller
{
public function siteName()
{
return get_bloginfo('name');
}
}

10
resources/controllers/Home.php

@ -0,0 +1,10 @@
<?php
namespace App;
use Sober\Controller\Controller;
class Home extends Controller
{
}

92
resources/functions.php

@ -0,0 +1,92 @@
<?php
/**
* Do not edit anything in this file unless you know what you're doing
*/
use Roots\Sage\Config;
use Roots\Sage\Container;
/**
* Helper function for prettying up errors
* @param string $message
* @param string $subtitle
* @param string $title
*/
$sage_error = function ($message, $subtitle = '', $title = '') {
$title = $title ?: __('Sage &rsaquo; Error', 'sage');
$footer = '<a href="https://roots.io/sage/docs/">roots.io/sage/docs/</a>';
$message = "<h1>{$title}<br><small>{$subtitle}</small></h1><p>{$message}</p><p>{$footer}</p>";
wp_die($message, $title);
};
/**
* Ensure compatible version of PHP is used
*/
if (version_compare('5.6.4', phpversion(), '>=')) {
$sage_error(__('You must be using PHP 5.6.4 or greater.', 'sage'), __('Invalid PHP version', 'sage'));
}
/**
* Ensure compatible version of WordPress is used
*/
if (version_compare('4.7.0', get_bloginfo('version'), '>=')) {
$sage_error(__('You must be using WordPress 4.7.0 or greater.', 'sage'), __('Invalid WordPress version', 'sage'));
}
/**
* Ensure dependencies are loaded
*/
if (!class_exists('Roots\\Sage\\Container')) {
if (!file_exists($composer = __DIR__.'/../vendor/autoload.php')) {
$sage_error(
__('You must run <code>composer install</code> from the Sage directory.', 'sage'),
__('Autoloader not found.', 'sage')
);
}
require_once $composer;
}
/**
* Sage required files
*
* The mapped array determines the code library included in your theme.
* Add or remove files to the array as needed. Supports child theme overrides.
*/
array_map(function ($file) use ($sage_error) {
$file = "../app/{$file}.php";
if (!locate_template($file, true, true)) {
$sage_error(sprintf(__('Error locating <code>%s</code> for inclusion.', 'sage'), $file), 'File not found');
}
}, ['helpers', 'setup', 'filters', 'admin']);
/**
* Here's what's happening with these hooks:
* 1. WordPress initially detects theme in themes/sage/resources
* 2. Upon activation, we tell WordPress that the theme is actually in themes/sage/resources/views
* 3. When we call get_template_directory() or get_template_directory_uri(), we point it back to themes/sage/resources
*
* We do this so that the Template Hierarchy will look in themes/sage/resources/views for core WordPress themes
* But functions.php, style.css, and index.php are all still located in themes/sage/resources
*
* This is not compatible with the WordPress Customizer theme preview prior to theme activation
*
* get_template_directory() -> /srv/www/example.com/current/web/app/themes/sage/resources
* get_stylesheet_directory() -> /srv/www/example.com/current/web/app/themes/sage/resources
* locate_template()
* ├── STYLESHEETPATH -> /srv/www/example.com/current/web/app/themes/sage/resources/views
* └── TEMPLATEPATH -> /srv/www/example.com/current/web/app/themes/sage/resources
*/
array_map(
'add_filter',
['theme_file_path', 'theme_file_uri', 'parent_theme_file_path', 'parent_theme_file_uri'],
array_fill(0, 4, 'dirname')
);
Container::getInstance()
->bindIf('config', function () {
return new Config([
'assets' => require dirname(__DIR__).'/config/assets.php',
'theme' => require dirname(__DIR__).'/config/theme.php',
'view' => require dirname(__DIR__).'/config/view.php',
]);
}, true);

3
resources/index.php

@ -0,0 +1,3 @@
<?php
// this file is deliberately blank

BIN
resources/screenshot.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 B

12
resources/style.css

@ -0,0 +1,12 @@
/*
Theme Name: Aldine
Theme URI: https://pressbooks.org/themes/aldine
Description: Aldine is the root theme for Pressbooks networks.
Version: 1.0.0-dev
Author: Pressbooks (Book Oven Inc.)
Author URI: https://pressbooks.org
Text Domain: sage
License: MIT License
License URI: http://opensource.org/licenses/MIT
*/

14
resources/views/404.blade.php

@ -0,0 +1,14 @@
@extends('layouts.app')
@section('content')
@include('partials.page-header')
@if (!have_posts())
<div class="alert alert-warning">
{{ __('Sorry, but the page you were trying to view does not exist.', 'sage') }}
</div>
{!! get_search_form(false) !!}
@endif
{!! get_the_posts_navigation() !!}
@endsection

18
resources/views/index.blade.php

@ -0,0 +1,18 @@
@extends('layouts.app')
@section('content')
@include('partials.page-header')
@if (!have_posts())
<div class="alert alert-warning">
{{ __('Sorry, no results were found.', 'sage') }}
</div>
{!! get_search_form(false) !!}
@endif
@while (have_posts()) @php(the_post())
@include('partials.content-'.get_post_type())
@endwhile
{!! get_the_posts_navigation() !!}
@endsection

23
resources/views/layouts/app.blade.php

@ -0,0 +1,23 @@
<!doctype html>
<html @php(language_attributes())>
@include('partials.head')
<body @php(body_class())>
@php(do_action('get_header'))
@include('partials.header')
<div class="wrap container" role="document">
<div class="content">
<main class="main">
@yield('content')
</main>
@if (App\display_sidebar())
<aside class="sidebar">
@include('partials.sidebar')
</aside>
@endif
</div>
</div>
@php(do_action('get_footer'))
@include('partials.footer')
@php(wp_footer())
</body>
</html>

8
resources/views/page.blade.php

@ -0,0 +1,8 @@
@extends('layouts.app')
@section('content')
@while(have_posts()) @php(the_post())
@include('partials.page-header')
@include('partials.content-page')
@endwhile
@endsection

38
resources/views/partials/comments.blade.php

@ -0,0 +1,38 @@
@php
if (post_password_required()) {
return;
}
@endphp
<section id="comments" class="comments">
@if (have_comments())
<h2>
{!! sprintf(_nx('One response to &ldquo;%2$s&rdquo;', '%1$s responses to &ldquo;%2$s&rdquo;', get_comments_number(), 'comments title', 'sage'), number_format_i18n(get_comments_number()), '<span>' . get_the_title() . '</span>') !!}
</h2>
<ol class="comment-list">
{!! wp_list_comments(['style' => 'ol', 'short_ping' => true]) !!}
</ol>
@if (get_comment_pages_count() > 1 && get_option('page_comments'))
<nav>
<ul class="pager">
@if (get_previous_comments_link())
<li class="previous">@php(previous_comments_link(__('&larr; Older comments', 'sage')))</li>
@endif
@if (get_next_comments_link())
<li class="next">@php(next_comments_link(__('Newer comments &rarr;', 'sage')))</li>
@endif
</ul>
</nav>
@endif
@endif
@if (!comments_open() && get_comments_number() != '0' && post_type_supports(get_post_type(), 'comments'))
<div class="alert alert-warning">
{{ __('Comments are closed.', 'sage') }}
</div>
@endif
@php(comment_form())
</section>

2
resources/views/partials/content-page.blade.php

@ -0,0 +1,2 @@
@php(the_content())
{!! wp_link_pages(['echo' => 0, 'before' => '<nav class="page-nav"><p>' . __('Pages:', 'sage'), 'after' => '</p></nav>']) !!}

11
resources/views/partials/content-search.blade.php

@ -0,0 +1,11 @@
<article @php(post_class())>
<header>
<h2 class="entry-title"><a href="{{ get_permalink() }}">{{ get_the_title() }}</a></h2>
@if (get_post_type() === 'post')
@include('partials/entry-meta')
@endif
</header>
<div class="entry-summary">
@php(the_excerpt())
</div>
</article>

13
resources/views/partials/content-single.blade.php

@ -0,0 +1,13 @@
<article @php(post_class())>
<header>
<h1 class="entry-title">{{ get_the_title() }}</h1>
@include('partials/entry-meta')
</header>
<div class="entry-content">
@php(the_content())
</div>
<footer>
{!! wp_link_pages(['echo' => 0, 'before' => '<nav class="page-nav"><p>' . __('Pages:', 'sage'), 'after' => '</p></nav>']) !!}
</footer>
@php(comments_template('/partials/comments.blade.php'))
</article>

9
resources/views/partials/content.blade.php

@ -0,0 +1,9 @@
<article @php(post_class())>
<header>
<h2 class="entry-title"><a href="{{ get_permalink() }}">{{ get_the_title() }}</a></h2>
@include('partials/entry-meta')
</header>
<div class="entry-summary">
@php(the_excerpt())
</div>
</article>

6
resources/views/partials/entry-meta.blade.php

@ -0,0 +1,6 @@
<time class="updated" datetime="{{ get_post_time('c', true) }}">{{ get_the_date() }}</time>
<p class="byline author vcard">
{{ __('By', 'sage') }} <a href="{{ get_author_posts_url(get_the_author_meta('ID')) }}" rel="author" class="fn">
{{ get_the_author() }}
</a>
</p>

5
resources/views/partials/footer.blade.php

@ -0,0 +1,5 @@
<footer class="content-info">
<div class="container">
@php(dynamic_sidebar('sidebar-footer'))
</div>
</footer>

6
resources/views/partials/head.blade.php

@ -0,0 +1,6 @@
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
@php(wp_head())
</head>

10
resources/views/partials/header.blade.php

@ -0,0 +1,10 @@
<header class="banner">
<div class="container">
<a class="brand" href="{{ home_url('/') }}">{{ get_bloginfo('name', 'display') }}</a>
<nav class="nav-primary">
@if (has_nav_menu('primary_navigation'))
{!! wp_nav_menu(['theme_location' => 'primary_navigation', 'menu_class' => 'nav']) !!}
@endif
</nav>
</div>
</header>

3
resources/views/partials/page-header.blade.php

@ -0,0 +1,3 @@
<div class="page-header">
<h1>{!! App\title() !!}</h1>
</div>

1
resources/views/partials/sidebar.blade.php

@ -0,0 +1 @@
@php(dynamic_sidebar('sidebar-primary'))

18
resources/views/search.blade.php

@ -0,0 +1,18 @@
@extends('layouts.app')
@section('content')
@include('partials.page-header')
@if (!have_posts())
<div class="alert alert-warning">
{{ __('Sorry, no results were found.', 'sage') }}
</div>
{!! get_search_form(false) !!}
@endif
@while(have_posts()) @php(the_post())
@include('partials.content-search')
@endwhile
{!! get_the_posts_navigation() !!}
@endsection

7
resources/views/single.blade.php

@ -0,0 +1,7 @@
@extends('layouts.app')
@section('content')
@while(have_posts()) @php(the_post())
@include('partials.content-single-'.get_post_type())
@endwhile
@endsection

12
resources/views/template-custom.blade.php

@ -0,0 +1,12 @@
{{--
Template Name: Custom Template
--}}
@extends('layouts.app')
@section('content')
@while(have_posts()) @php(the_post())
@include('partials.page-header')
@include('partials.content-page')
@endwhile
@endsection

6773
yarn.lock

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save