11 | display( 'components', 'header' ) ?>
12 |
13 |
14 |
15 | display( 'layouts', Hybrid\Template\hierarchy() ) ?>
16 |
17 |
18 |
19 | display( 'components', 'sidebar', [ 'location' => 'subsidiary' ] ) ?>
20 |
21 | display( 'components', 'footer' ) ?>
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/resources/svg/twitter.svg:
--------------------------------------------------------------------------------
1 |
7 |
23 |
24 |
34 |
35 |
36 |
39 |
40 |
41 | is needed. WordPress will know where to add it. */ ?>
42 |
--------------------------------------------------------------------------------
/app/Providers/AppServiceProvider.php:
--------------------------------------------------------------------------------
1 |
11 | * @copyright Copyright (c) 2018, Brett Mason
12 | * @link https://github.com/brettsmason/luxe
13 | * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
14 | */
15 |
16 | namespace Luxe\Providers;
17 |
18 | use Hybrid\Tools\ServiceProvider;
19 |
20 | /**
21 | * App service provider.
22 | *
23 | * @since 1.0.0
24 | * @access public
25 | */
26 | class AppServiceProvider extends ServiceProvider {
27 |
28 | /**
29 | * Callback executed when the `\Hybrid\Core\Application` class registers
30 | * providers. Use this method to bind items to the container.
31 | *
32 | * @since 1.0.0
33 | * @access public
34 | * @return void
35 | */
36 | public function register() {
37 |
38 | // Bind the asset manifest for cache-busting.
39 | $this->app->singleton( 'luxe/manifest', function() {
40 |
41 | $file = get_theme_file_path( 'public/manifest.json' );
42 |
43 | return file_exists( $file ) ? json_decode( file_get_contents( $file ), true ) : null;
44 | } );
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "brettsmason/luxe",
3 | "type": "wordpress-theme",
4 | "description": "Luxe is a WordPress starter theme using a modern workflow and best practices.",
5 | "keywords": [
6 | "wordpress"
7 | ],
8 | "homepage": "https://github.com/brettsmason/luxe",
9 | "license": "GPL-2.0-or-later",
10 | "authors": [
11 | {
12 | "name": "Brett Mason",
13 | "email": "brettsmason@gmail.com",
14 | "homepage": "https://brettmason.co.uk"
15 | }
16 | ],
17 | "autoload": {
18 | "psr-4": {
19 | "Luxe\\": "app/"
20 | }
21 | },
22 | "require": {
23 | "php": ">=5.6",
24 | "composer/installers": "~1.0",
25 | "justintadlock/hybrid-core": "^5.0.0"
26 | },
27 | "require-dev": {
28 | "php": ">=7.0",
29 | "wp-coding-standards/wpcs": "*",
30 | "dealerdirect/phpcodesniffer-composer-installer": "*",
31 | "phpcompatibility/php-compatibility": "*"
32 | },
33 | "scripts": {
34 | "install-codestandards": [
35 | "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin::run"
36 | ],
37 | "post-install-cmd": [
38 | "@install-codestandards"
39 | ],
40 | "phpcbf-dev": "\"vendor/bin/phpcbf\"",
41 | "run-phpcbf": [
42 | "@phpcbf-dev"
43 | ],
44 | "phpcs-dev": "\"vendor/bin/phpcs\"",
45 | "run-phpcs": [
46 | "@phpcs-dev"
47 | ]
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/resources/scss/tools/_units.scss:
--------------------------------------------------------------------------------
1 | /// Removes the unit (e.g. px, em, rem) from a value, returning the number only.
2 | ///
3 | /// @param {Number} $num - Number to strip unit from.
4 | ///
5 | /// @returns {Number} The same number, sans unit.
6 | @function strip-unit($num) {
7 | @return $num / ($num * 0 + 1);
8 | }
9 |
10 | /// Converts a pixel value to matching rem value. *Any* value passed, regardless of unit, is assumed to be a pixel value. By default, the base pixel value used to calculate the rem value is taken from the `$global-font-size` variable.
11 | ///
12 | /// @param {Number} $value - Pixel value to convert.
13 | /// @param {Number} $base [null] - Base for pixel conversion.
14 | ///
15 | /// @returns {Number} A number in rems, calculated based on the given value and the base pixel value. rem values are passed through as is.
16 | @function rem($value, $base: null) {
17 |
18 | // If no base is defined, defer to the global font size
19 | @if $base == null {
20 | $base: $global-font-size;
21 | }
22 |
23 | // Check if the value is a number
24 | @if type-of($value) != "number" {
25 | @warn inspect($value) + " was passed to rem(), which is not a number.";
26 | @return $value;
27 | }
28 |
29 | // Calculate rem if units for $value is not rem or em
30 | @if unit($value) == "px" {
31 | $value: strip-unit($value) / strip-unit($base) * 1rem;
32 | }
33 |
34 | @return $value;
35 | }
36 |
--------------------------------------------------------------------------------
/resources/js/customizer.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Customize preview script.
3 | *
4 | * This file handles the JavaScript for the live preview frame in the customizer.
5 | * The final result gets saved into `public/js/customizer.js`.
6 | *
7 | * @package Luxe
8 | * @author Brett Mason
9 | * @copyright Copyright (c) 2018, Brett Mason
10 | * @see @link https://github.com/brettsmason/luxe
11 | * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
12 | */
13 |
14 | // Site title.
15 | wp.customize( 'blogname', ( value ) => {
16 | value.bind( ( to ) => {
17 | document.querySelector( '.app-header__title-link' ).textContent = to;
18 | } );
19 | } );
20 |
21 | // Site description.
22 | wp.customize( 'blogdescription', ( value ) => {
23 | value.bind( ( to ) => {
24 | document.querySelector( '.app-header__description' ).textContent = to;
25 | } );
26 | } );
27 |
28 | // Site title/description toggle.
29 | wp.customize( 'header_text', ( value ) => {
30 | value.bind( ( to ) => {
31 | const headerItems = document.querySelectorAll( '.app-header__title-link, .app-header__description' );
32 |
33 | headerItems.forEach( ( text ) => {
34 | if ( false === to ) {
35 | text.style.clip = 'rect(0 0 0 0)';
36 | text.style.position = 'absolute';
37 | } else {
38 | text.style.clip = null;
39 | text.style.position = null;
40 | }
41 | } );
42 | } );
43 | } );
44 |
45 |
--------------------------------------------------------------------------------
/app/WooCommerce/ArchiveProduct/ArchiveProduct.php:
--------------------------------------------------------------------------------
1 |
7 | * @copyright Copyright (c) 2018, Brett Mason
8 | * @link https://github.com/brettsmason/luxe
9 | * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
10 | */
11 |
12 | namespace Luxe\WooCommerce\ArchiveProduct;
13 |
14 | use Hybrid\Contracts\Bootable;
15 |
16 | /**
17 | * Functionality specific to product archives.
18 | *
19 | * @since 1.0.0
20 | * @access public
21 | */
22 | class ArchiveProduct implements Bootable {
23 |
24 | /**
25 | * Adds actions on the appropriate action hooks.
26 | *
27 | * @since 1.0.0
28 | * @access public
29 | * @return void
30 | */
31 | public function boot() {
32 |
33 | // Remove add to cart button from archive view.
34 | remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 );
35 |
36 | // Remove WooCommerce pagination as we are using our own.
37 | remove_action( 'woocommerce_after_shop_loop', 'woocommerce_pagination', 10 );
38 |
39 | // Add our pagination in place of WooCommerce'.
40 | add_action( 'woocommerce_after_shop_loop', [ $this, 'pagination' ], PHP_INT_MAX );
41 | }
42 |
43 | /**
44 | * Add custom pagination.
45 | *
46 | * @since 1.0.0
47 | * @access public
48 | * @return string
49 | */
50 | public function pagination() {
51 | \Hybrid\View\display( 'partials', 'pagination-posts' );
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/app/functions-assets.php:
--------------------------------------------------------------------------------
1 | %2$s',
26 | esc_url( get_permalink( get_the_ID() ) ),
27 | /* translators: %s: Name of current post */
28 | sprintf( __( 'Continue reading "%s"', 'luxe' ), get_the_title( get_the_ID() ) )
29 | );
30 |
31 | return ' … ' . $link;
32 | }
33 | add_filter( 'excerpt_more', __NAMESPACE__ . '\\excerpt_more' );
34 |
35 | /**
36 | * Adds custom classes to the array of body classes.
37 | *
38 | * @param array $classes Classes for the body element.
39 | * @return array
40 | */
41 | function body_class( $classes ) {
42 |
43 | // Adds a class of has-sidebar when the sidebar is enabled and is active.
44 | if ( \is_active_sidebar( 'primary' ) && display_sidebar() ) {
45 | $classes[] = 'has-sidebar-primary';
46 | }
47 |
48 | return $classes;
49 | }
50 | add_filter( 'body_class', __NAMESPACE__ . '\\body_class' );
--------------------------------------------------------------------------------
/resources/scss/tools/_hidden.scss:
--------------------------------------------------------------------------------
1 | /// Makes an element visually hidden, but still accessible to keyboards and assistive devices.
2 | /// @link http://snook.ca/archives/html_and_css/hiding-content-for-accessibility Hiding Content for Accessibility
3 | /// @link http://hugogiraudel.com/2016/10/13/css-hide-and-seek/
4 | ///
5 | /// @param {Boolean} $enforce - If `true`, use `!important` on applied properties
6 | @mixin hide-visually($enforce: false) {
7 | $important: if($enforce, "!important", null);
8 |
9 | border: 0 #{$important};
10 | clip: rect(1px, 1px, 1px, 1px) #{$important};
11 | -webkit-clip-path: inset(50%) #{$important};
12 | clip-path: inset(50%) #{$important};
13 | height: 1px #{$important};
14 | overflow: hidden #{$important};
15 | padding: 0 #{$important};
16 | position: absolute #{$important};
17 | white-space: nowrap #{$important};
18 | width: 1px #{$important};
19 | word-wrap: normal #{$important};
20 | }
21 |
22 | /// This reverses `hide-visually()`.
23 | ///
24 | /// @param {Boolean} $enforce - If `true`, use `!important` on applied properties.
25 | @mixin show-visually($enforce: false) {
26 | $important: if($enforce, "!important", null);
27 |
28 | background-color: $color-button-background;
29 | clip: auto #{$important};
30 | clip-path: none #{$important};
31 | color: $color-button;
32 | height: auto #{$important};
33 | left: vr(1);
34 | overflow: visible #{$important};
35 | padding: vr(1/2) vr(3/4);
36 | text-decoration: none;
37 | top: vr(1);
38 | white-space: normal #{$important};
39 | width: auto #{$important};
40 | }
41 |
--------------------------------------------------------------------------------
/resources/scss/settings/_global.scss:
--------------------------------------------------------------------------------
1 | // Media queries used throughout.
2 | $mq-breakpoints: (
3 | small: 320px,
4 | medium: 740px,
5 | large: 980px,
6 | xlarge: 1300px
7 | );
8 |
9 | // Baseline grid lines height.
10 | $global-baseline: 6px;
11 |
12 | // Base typographical styles.
13 | $global-font-size: 18px;
14 | $global-line-height: $global-baseline * 4.5;
15 |
16 | // UI specific treatments.
17 | $global-radius: null;
18 | $global-transition-duration: 300ms;
19 | $global-transition-type: ease-in-out;
20 |
21 | // Global widths used throughout to constrain elements.
22 | $global-width: 1024px;
23 | $global-width-wide: 1400px;
24 | $global-width-narrow: 800px;
25 |
26 | // Font families.
27 | $font-family-body: -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica Neue', 'Arial', sans-serif;
28 | $font-family-heading: $font-family-body;
29 | $font-family-monospace: "Monaco", "Consolas", "Andale Mono", "DejaVu Sans Mono", monospace;
30 |
31 | // Headings.
32 | $h1: (
33 | null: 32px,
34 | medium: 48px,
35 | );
36 | $h2: (
37 | null: 26px,
38 | medium: 36px,
39 | );
40 | $h3: (
41 | null: 22px,
42 | medium: 28px,
43 | );
44 | $h4: (
45 | null: 20px,
46 | medium: 22px,
47 | );
48 | $h5: (
49 | null: 16px,
50 | medium: 20px,
51 | );
52 | $h6: (
53 | null: 16px,
54 | medium: 18px,
55 | );
56 |
57 | $font-weight-heading: 700;
58 |
59 | // Buttons.
60 | $font-weight-button: 400;
61 |
62 | // Forms.
63 | $font-weight-form-legend: 700;
64 | $font-weight-form-label: 700;
65 |
66 | // Gutters for use with nth-grid.
67 | $grid-gutter: $global-line-height;
68 |
--------------------------------------------------------------------------------
/bootstrap/app.php:
--------------------------------------------------------------------------------
1 | provider( \Luxe\Providers\AppServiceProvider::class );
28 | $luxe->provider( \Luxe\Providers\CustomizeServiceProvider::class );
29 | $luxe->provider( \Luxe\Providers\WooCommerceServiceProvider::class );
30 |
31 | /**
32 | * Perform bootstrap actions.
33 | *
34 | * Creates an action hook for child themes (or even plugins) to hook into the
35 | * bootstrapping process and add their own bindings before the app is booted by
36 | * passing the application instance to the action callback.
37 | */
38 | do_action( 'luxe/bootstrap', $luxe );
39 |
40 | /**
41 | * Bootstrap the application.
42 | *
43 | * Calls the application `boot()` method, which launches the application. Pat
44 | * yourself on the back for a job well done.
45 | */
46 | $luxe->boot();
47 |
--------------------------------------------------------------------------------
/resources/scss/blocks/_wp-block-cover.scss:
--------------------------------------------------------------------------------
1 | .wp-block-cover {
2 | align-items: center;
3 | background-position: center center;
4 | background-size: cover;
5 | display: flex;
6 | justify-content: center;
7 | margin-bottom: vr(1);
8 | min-height: 430px;
9 | position: relative;
10 |
11 | &-text {
12 | @include font-size($h2);
13 | color: $color-white;
14 | margin-bottom: 0;
15 | max-width: rem($global-width);
16 | padding: vr(1);
17 | text-align: center;
18 | z-index: 1;
19 |
20 | a,
21 | a:hover,
22 | a:focus,
23 | a:active {
24 | color: $color-white;
25 | }
26 | }
27 |
28 | &.has-left-content {
29 | justify-content: flex-start;
30 |
31 | .wp-block-cover-image-text {
32 | margin-left: 0;
33 | text-align: left;
34 | }
35 | }
36 |
37 | &.has-right-content {
38 | justify-content: flex-end;
39 |
40 | .wp-block-cover-image-text {
41 | margin-right: 0;
42 | text-align: right;
43 | }
44 | }
45 |
46 | &.has-parallax {
47 | background-attachment: fixed;
48 | }
49 |
50 | &.has-background-dim::before {
51 | background-color: rgba($color-black, 0.5);
52 | bottom: 0;
53 | content: "";
54 | left: 0;
55 | position: absolute;
56 | right: 0;
57 | top: 0;
58 | }
59 |
60 | @for $i from 1 through 10 {
61 |
62 | &.has-background-dim-#{$i * 10}::before {
63 | background-color: rgba($color-black, $i * 0.1);
64 | }
65 | }
66 |
67 | &.components-placeholder {
68 | height: inherit;
69 | }
70 |
71 | // Apply max-width to floated items that have no intrinsic width
72 | [data-align="left"] &,
73 | [data-align="right"] &,
74 | &.alignleft,
75 | &.alignright {
76 | max-width: $global-width / 2;
77 | width: 100%;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/resources/scss/blocks/_wp-block-gallery.scss:
--------------------------------------------------------------------------------
1 | .wp-block-gallery {
2 | display: flex;
3 | flex-wrap: wrap;
4 | list-style-type: none;
5 |
6 | .blocks-gallery-item {
7 | @include nth-grid(2, $selector: type, $gutter: vr(1/2));
8 | display: flex;
9 | flex-direction: column;
10 | flex-grow: 1;
11 | justify-content: center;
12 | margin-bottom: vr(1/2);
13 | margin-left: 0;
14 | position: relative;
15 |
16 | figure {
17 | align-items: flex-end;
18 | display: flex;
19 | height: 100%;
20 | margin: 0;
21 | }
22 |
23 | figcaption {
24 | background-color: rgba($color-black, 0.7);
25 | color: $color-white;
26 | max-height: 100%;
27 | overflow: auto;
28 | padding: vr(1);
29 | position: absolute;
30 | text-align: center;
31 | width: 100%;
32 | }
33 | }
34 |
35 | &.columns-1 .blocks-gallery-item {
36 | width: 100%;
37 | }
38 |
39 | @include mq(medium) {
40 | @for $i from 3 through 8 {
41 |
42 | &.columns-#{$i} .blocks-gallery-item {
43 | @include nth-grid($i, $selector: type, $gutter: vr(1/2));
44 |
45 | // Remove the margin from the last child so we have nice
46 | // full width images without a gap on the right.
47 | &:last-child {
48 | margin-right: 0;
49 | }
50 | }
51 | }
52 | }
53 |
54 | // Cropped
55 | &.is-cropped .blocks-gallery-item {
56 |
57 | a,
58 | img {
59 | flex: 1;
60 | height: 100%;
61 | object-fit: cover;
62 | width: 100%;
63 |
64 | }
65 | }
66 |
67 | // Apply max-width to floated items that have no intrinsic width
68 | [data-align="left"] &,
69 | [data-align="right"] &,
70 | &.alignleft,
71 | &.alignright {
72 | max-width: $global-width / 2;
73 | width: 100%;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/app/Svg/functions-svg.php:
--------------------------------------------------------------------------------
1 | display();
22 | }
23 |
24 | /**
25 | * Returns SVG output.
26 | *
27 | * @since 1.0.0
28 | * @access public
29 | * @param string $file The SVG file.
30 | * @param array $args An array or arguements to apply to the SVG.
31 | * @return string
32 | */
33 | function render( $file, $args = [] ) {
34 | $svg = new Svg( $file, $args );
35 | return $svg->render();
36 | }
37 |
38 | /**
39 | * Returns an array of supported social links (URL and icon name).
40 | *
41 | * @return array $social_links_icons
42 | */
43 | function social_links_icons() {
44 | // Supported social links icons.
45 | $social_links_icons = [
46 | 'facebook.com' => 'facebook',
47 | 'instagram.com' => 'instagram',
48 | 'linkedin.com' => 'linkedin',
49 | 'medium.com' => 'medium',
50 | 'pinterest.com' => 'pinterest',
51 | 'twitter.com' => 'twitter',
52 | 'vimeo.com' => 'vimeo',
53 | 'youtube.com' => 'youtube',
54 | ];
55 |
56 | /**
57 | * Filter social links icons.
58 | *
59 | * @param array $social_links_icons Array of social links icons.
60 | */
61 | return apply_filters( 'luxe_social_links_icons', $social_links_icons ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
62 | }
63 |
--------------------------------------------------------------------------------
/app/Providers/CustomizeServiceProvider.php:
--------------------------------------------------------------------------------
1 |
11 | * @copyright Copyright (c) 2018, Brett Mason
12 | * @link https://github.com/brettsmason/luxe
13 | * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
14 | */
15 |
16 | namespace Luxe\Providers;
17 |
18 | use Hybrid\Tools\ServiceProvider;
19 | use Luxe\Customize\Customize;
20 |
21 | /**
22 | * App service provider.
23 | *
24 | * @since 1.0.0
25 | * @access public
26 | */
27 | class CustomizeServiceProvider extends ServiceProvider {
28 |
29 | /**
30 | * Callback executed when the `\Hybrid\Core\Application` class registers
31 | * providers. Use this method to bind items to the container.
32 | *
33 | * @since 1.0.0
34 | * @access public
35 | * @return void
36 | */
37 | public function register() {
38 |
39 | // Bind a single instance of our customizer class.
40 | $this->app->singleton( Customize::class );
41 | }
42 |
43 | /**
44 | * Callback executed after all the service providers have been registered.
45 | * This is particularly useful for single-instance container objects that
46 | * only need to be loaded once per page and need to be resolved early.
47 | *
48 | * @since 1.0.0
49 | * @access public
50 | * @return void
51 | */
52 | public function boot() {
53 |
54 | // Boot the customizer class instance.
55 | $this->app->resolve( Customize::class )->boot();
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/resources/scss/blocks/_wp-block-button.scss:
--------------------------------------------------------------------------------
1 | .wp-block-button {
2 |
3 | &__link {
4 | @include button;
5 |
6 | &:not(.has-background) {
7 | background-color: $color-button-background;
8 |
9 | &:hover,
10 | &:focus {
11 | background-color: $color-button-hover-background;
12 | }
13 | }
14 |
15 | &:not(.has-text-color) {
16 | color: $color-button;
17 |
18 | &:hover,
19 | &:focus {
20 | color: $color-button-hover;
21 | }
22 | }
23 | }
24 |
25 | &.aligncenter {
26 | text-align: center;
27 | }
28 |
29 | &.alignwide &__link,
30 | &.alignfull &__link {
31 | width: 100%;
32 | }
33 | }
34 |
35 | .is-style-outline .wp-block-button__link {
36 | background-color: transparent;
37 | border-color: $color-button-outline-border;
38 | color: $color-button-outline;
39 |
40 | &:hover,
41 | &:focus {
42 | background-color: $color-button-outline-hover-background;
43 | color: $color-button-outline-hover;
44 | }
45 |
46 | &.has-secondary-background-color {
47 | border-color: $color-secondary;
48 | color: $color-secondary;
49 |
50 | &:hover,
51 | &:focus {
52 | background-color: $color-secondary;
53 | color: $color-white;
54 | }
55 | }
56 |
57 | &.has-black-background-color {
58 | border-color: $color-black;
59 | color: $color-black;
60 |
61 | &:hover,
62 | &:focus {
63 | background-color: $color-black;
64 | color: $color-white;
65 | }
66 | }
67 |
68 | &.has-white-background-color {
69 | border-color: $color-white;
70 | color: $color-black;
71 |
72 | &:hover,
73 | &:focus {
74 | background-color: $color-white;
75 | color: $color-black;
76 | }
77 | }
78 | }
79 |
80 | .is-style-squared .wp-block-button__link {
81 | border-radius: 0;
82 | }
83 |
--------------------------------------------------------------------------------
/resources/scss/components/_comment.scss:
--------------------------------------------------------------------------------
1 | .comment {
2 | align-items: flex-start;
3 | display: flex;
4 |
5 | // The comment avatar.
6 | &__avatar {
7 | margin-right: vr(1/2);
8 | min-width: 32px;
9 |
10 | &-img {
11 | border-radius: $global-radius;
12 | }
13 | }
14 |
15 | // Full comment content container.
16 | // [1] - fixes a bug when content doesn't wrap.
17 | &__body {
18 | flex: 1;
19 | min-width: 0; // [1]
20 | }
21 |
22 | // Metadata wrapper.
23 | &__meta {
24 | margin-bottom: vr(1/4);
25 | }
26 |
27 | &__author {
28 | font-weight: 700;
29 | text-decoration: none;
30 |
31 | a {
32 | text-decoration: none;
33 |
34 | &:hover,
35 | &:focus {
36 | text-decoration: underline;
37 | }
38 | }
39 | }
40 |
41 | &__date {}
42 |
43 | &__time {}
44 |
45 | &__permalink,
46 | &__edit {
47 | text-decoration: none;
48 |
49 | &:hover,
50 | &:focus,
51 | &:active {
52 | text-decoration: underline;
53 | }
54 | }
55 |
56 | // Full comment text/content.
57 | &__content {
58 | margin-bottom: vr(1/4);
59 |
60 | > :last-child {
61 | margin-bottom: 0;
62 | }
63 | }
64 |
65 | // Comment actions (reply link etc).
66 | &__actions {
67 | margin-bottom: vr(1.5);
68 | }
69 |
70 | &__reply {
71 | text-decoration: none;
72 |
73 | &:hover,
74 | &:focus,
75 | &:active {
76 | text-decoration: underline;
77 | }
78 | }
79 |
80 | &__reply-icon {
81 | height: vr(1/2);
82 | margin-right: vr(1/4);
83 | width: vr(1/2);
84 | }
85 |
86 | // Comment under moderation message.
87 | &__moderation {}
88 |
89 | // Type of comment.
90 | &--type-comment {}
91 |
92 | &--type-ping {
93 | margin-bottom: vr(1/2);
94 | }
95 |
96 | // Comment status.
97 | &--status-unapproved {}
98 | }
99 |
--------------------------------------------------------------------------------
/resources/scss/vendor/woocommerce/_single-product.scss:
--------------------------------------------------------------------------------
1 | .single-product {
2 |
3 | // the main product container.
4 | .product {
5 | position: relative;
6 | }
7 |
8 | .woocommerce-product-gallery {
9 | width: 100%;
10 | margin-bottom: vr(2);
11 | position: relative;
12 |
13 | @include mq(medium) {
14 | float: left;
15 | margin-right: vr(2);
16 | width: calc(50% - #{vr(1)});
17 | }
18 | }
19 |
20 | // Product summary, which contains title, price etc.
21 | .summary {
22 | width: 100%;
23 | margin-bottom: vr(2);
24 |
25 | @include mq(medium) {
26 | float: left;
27 | width: calc(50% - #{vr(1)});
28 | }
29 | }
30 |
31 | .cart,
32 | .woocommerce-variation-add-to-cart {
33 | display: flex;
34 | margin-bottom: vr(1);
35 |
36 | .quantity {
37 | margin-right: vr(1/4);
38 | }
39 | }
40 |
41 | // Class added to the .cart form if variations are enabled.
42 | .variations_form {
43 | display: flex;
44 | flex-direction: column;
45 | }
46 |
47 | // Variations table.
48 | .variations {
49 |
50 | td {
51 | display: block;
52 | padding: 0;
53 | }
54 |
55 | input,
56 | select {
57 | margin-bottom: vr(1/2);
58 | }
59 | }
60 |
61 | // Variations reset link.
62 | .reset_variations {}
63 |
64 | .woocommerce-variation-price {
65 | margin-bottom: vr(1);
66 | }
67 |
68 | // Grouped products
69 | .woocommerce-grouped-product-list {
70 | margin-bottom: vr(3/4);
71 | }
72 |
73 | .woocommerce-grouped-product-list-item {
74 | margin-bottom: vr(1/4);
75 | }
76 |
77 | // Set related/upsells back to block as they include the .products
78 | // class on the container for some reason.
79 | .related,
80 | .upsells {
81 | display: block;
82 | }
83 | }
84 |
85 | @import "components/gallery";
86 | @import "components/tabs";
87 |
--------------------------------------------------------------------------------
/resources/scss/woocommerce.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * This is the WooCommerce stylesheet.
3 | */
4 |
5 | // Settings.
6 | //
7 | // Settings handle the configuration and don"t output CSS. This is a good
8 | // place to define things like variables.
9 |
10 | @import "settings/global";
11 | @import "settings/colors";
12 |
13 |
14 | // Tools.
15 | //
16 | // These are used throughout the code but don"t output CSS on their own.
17 | // Things like mixins and extensions go here.
18 |
19 | @import "tools/units";
20 | @import "tools/clearfix";
21 | @import "tools/hidden";
22 | @import "tools/button";
23 | @import "tools/font-size";
24 | @import "tools/vr";
25 | @import "tools/responsive-embed";
26 | @import "tools/wrapper";
27 | @import "~nth-grid/sass/nth-grid";
28 | @import "~sass-mq/mq";
29 |
30 | // Utilities.
31 | //
32 | // Utilities are helper classes and overrides. This gets loaded last.
33 | // If necessary, this is the only place where `!important` rules should
34 | // go, but only if necessary.
35 |
36 | // @import "vendor/woocommerce/global";
37 | // @import "vendor/woocommerce/product-archive";
38 | // @import "vendor/woocommerce/product-single";
39 | // @import "vendor/woocommerce/product-gallery-slider";
40 | // @import "vendor/woocommerce/my-account";
41 | // @import "vendor/woocommerce/cart";
42 | // @import "vendor/woocommerce/checkout";
43 | // @import "vendor/woocommerce/order-confirmation";
44 |
45 | .woocommerce,
46 | .woocommerce-page {
47 |
48 | .woocommerce-checkout-review-order-table {
49 |
50 | .product-name {
51 | text-align: left;
52 | }
53 | }
54 | }
55 |
56 | @import "vendor/woocommerce/general";
57 | @import "vendor/woocommerce/archive-product";
58 | @import "vendor/woocommerce/single-product";
59 | @import "vendor/woocommerce/cart";
60 | @import "vendor/woocommerce/checkout";
61 | @import "vendor/woocommerce/my-account";
62 |
--------------------------------------------------------------------------------
/app/Providers/WooCommerceServiceProvider.php:
--------------------------------------------------------------------------------
1 |
11 | * @copyright Copyright (c) 2018, Brett Mason
12 | * @link https://github.com/brettsmason/luxe
13 | * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
14 | */
15 |
16 | namespace Luxe\Providers;
17 |
18 | use Hybrid\Tools\ServiceProvider;
19 | use Luxe\WooCommerce\Setup;
20 | use Luxe\WooCommerce\ArchiveProduct;
21 |
22 | /**
23 | * App service provider.
24 | *
25 | * @since 1.0.0
26 | * @access public
27 | */
28 | class WooCommerceServiceProvider extends ServiceProvider {
29 |
30 | /**
31 | * Callback executed when the `\Hybrid\Core\Application` class registers
32 | * providers. Use this method to bind items to the container.
33 | *
34 | * @since 1.0.0
35 | * @access public
36 | * @return void
37 | */
38 | public function register() {
39 |
40 | // Bind a single instance of our WooCommerce classes.
41 | $this->app->singleton( Setup\Setup::class );
42 | $this->app->singleton( ArchiveProduct\ArchiveProduct::class );
43 | }
44 |
45 | /**
46 | * Callback executed after all the service providers have been registered.
47 | * This is particularly useful for single-instance container objects that
48 | * only need to be loaded once per page and need to be resolved early.
49 | *
50 | * @since 1.0.0
51 | * @access public
52 | * @return void
53 | */
54 | public function boot() {
55 |
56 | // Boot the WooCommerce class instances.
57 | $this->app->resolve( Setup\Setup::class )->boot();
58 | $this->app->resolve( ArchiveProduct\ArchiveProduct::class )->boot();
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/config/webpack.settings.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 |
3 | /**
4 | * Collection of application front-end assets to be compiled.
5 | */
6 | entries: {
7 | app: './resources/js/app.js',
8 | customizer: './resources/js/customizer.js',
9 | screen: './resources/scss/screen.scss',
10 | editor: './resources/scss/editor.scss',
11 | woocommerce: './resources/scss/woocommerce.scss',
12 | },
13 |
14 | /**
15 | * BrowserSync settings.
16 | */
17 | browserSync: {
18 | host: 'localhost',
19 | port: 3000,
20 | proxy: 'http://theme.test',
21 | open: false,
22 | files: [
23 | '*.php',
24 | 'app/**/*.php',
25 | 'resources/views/**/*.php',
26 | 'public/js/**/*.js',
27 | 'public/css/**/*.css',
28 | 'public/svg/**/*.svg',
29 | 'public/img/**/*.{jpg,jpeg,png,gif}',
30 | 'public/fonts/**/*.{eot,ttf,woff,woff2,svg}',
31 | ],
32 | },
33 |
34 | /**
35 | * List of libraries which will be provided
36 | * within application scripts as external.
37 | */
38 | externals: {
39 | jquery: 'jQuery',
40 | },
41 |
42 | /**
43 | * List of custom modules resolving.
44 | */
45 | resolve: {
46 | alias: {},
47 | },
48 |
49 | /**
50 | * Project paths.
51 | */
52 | paths: {
53 | public: './public',
54 | assets: './resources',
55 | sass: './resources/scss',
56 | javascript: './resources/js',
57 | },
58 |
59 | /**
60 | * List of filename schemas for different
61 | * application assets.
62 | */
63 | outputs: {
64 | css: 'css/[name].css',
65 | javascript: 'js/[name].js',
66 | assets: '[path][name].[ext]',
67 | },
68 |
69 | stats: {
70 | // Copied from `'minimal'`.
71 | all: false,
72 | errors: true,
73 | maxModules: 0,
74 | modules: true,
75 | warnings: true,
76 | // Our additional options.
77 | assets: true,
78 | errorDetails: true,
79 | excludeAssets: /\.(jpe?g|png|gif|svg|woff|woff2)$/i,
80 | moduleTrace: true,
81 | performance: true,
82 | },
83 |
84 | };
85 |
--------------------------------------------------------------------------------
/resources/scss/vendor/woocommerce/_cart.scss:
--------------------------------------------------------------------------------
1 | .woocommerce-cart {
2 |
3 | .woocommerce-cart-form__contents {
4 |
5 | .product-thumbnail {
6 |
7 | @include mq($until: medium) {
8 | display: none;
9 | }
10 | }
11 |
12 | .product-remove {
13 |
14 | @include mq(medium) {
15 | text-align: left;
16 | width: 50px;
17 | }
18 | }
19 |
20 | .product-name {
21 |
22 | @include mq(medium) {
23 | width: 40%;
24 | text-align: left;
25 | }
26 | }
27 |
28 | .product-quantity {
29 | overflow: hidden;
30 |
31 | @include mq(medium) {
32 | width: 120px;
33 | }
34 |
35 | .quantity {
36 | float: right;
37 |
38 | @include mq(medium) {
39 | float: none;
40 | }
41 | }
42 | }
43 |
44 | .actions {
45 | text-align: left;
46 |
47 | @include mq(medium) {
48 | overflow: hidden;
49 | }
50 | }
51 |
52 | .button {
53 | @include button-style($color-secondary);
54 | display: block;
55 | width: 100%;
56 | }
57 |
58 | .coupon {
59 | display: flex;
60 | flex-direction: column;
61 | margin-bottom: vr(1/2);
62 |
63 | @include mq(medium) {
64 | display: inline-flex;
65 | flex-direction: row;
66 | margin-bottom: 0;
67 | }
68 |
69 | label {
70 | display: none;
71 | }
72 |
73 | [name="coupon_code"] {
74 | margin-bottom: vr(1/2);
75 | width: 100%;
76 |
77 | @include mq(medium) {
78 | margin-bottom: 0;
79 | width: 200px;
80 | }
81 | }
82 |
83 | [name="apply_coupon"] {
84 | width: 100%;
85 |
86 | @include mq(medium) {
87 | display: inline-block;
88 | width: auto;
89 | }
90 | }
91 | }
92 |
93 | [name="update_cart"] {
94 | width: 100%;
95 |
96 | @include mq(medium) {
97 | display: inline-block;
98 | float: right;
99 | width: auto;
100 | }
101 |
102 | &[disabled] {
103 | opacity: 0.5;
104 | cursor: not-allowed;
105 | }
106 | }
107 | }
108 |
109 | // the toggleable shipping calculator
110 | .shipping-calculator-form {
111 | margin-top: vr(1);
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/resources/scss/components/_entry.scss:
--------------------------------------------------------------------------------
1 | .entry {
2 | margin-bottom: vr(2);
3 |
4 | .single & {
5 | margin-bottom: 0;
6 | }
7 |
8 | // Featured image.
9 | &__image {
10 | margin-bottom: vr(1/2);
11 | }
12 |
13 | // Header wrapper.
14 | &__header {}
15 |
16 | // Entry title.
17 | &__title {}
18 |
19 | &__permalink {
20 | text-decoration: none;
21 | }
22 |
23 | // Meta wrappers.
24 | &__byline {
25 | @include font-size(16px);
26 | color: $color-grey-700;
27 | margin-bottom: vr(1);
28 | }
29 |
30 | &__published {}
31 |
32 | &__author {
33 | color: inherit;
34 | }
35 |
36 | &__comments {
37 | color: inherit;
38 | }
39 |
40 | // Full entry content.
41 | &__content {
42 | @include clearfix;
43 | margin-bottom: vr(2);
44 |
45 | .single &,
46 | > :last-child {
47 | margin-bottom: 0;
48 | }
49 |
50 | // Add some spacing for anything after entry__content.
51 | & + * {
52 | margin-top: vr(2);
53 | }
54 |
55 | > * {
56 | @include wrapper($global-width);
57 | }
58 |
59 | // Make links have an underline
60 | // when no class is present.
61 | a:not([class]) {
62 | text-decoration: underline;
63 | }
64 |
65 | > ol:not([class]),
66 | > ul:not([class]) {
67 | padding-left: vr(1.5);
68 | }
69 | }
70 |
71 | // Summary/Excerpt.
72 | &__summary {
73 |
74 | > ol:not([class]),
75 | > ul:not([class]) {
76 | padding-left: vr(1.5);
77 | }
78 | }
79 |
80 | &__footer {}
81 |
82 | &__terms-wrapper {
83 | color: $color-grey-700;
84 | display: block;
85 |
86 | & + & {
87 | margin-top: vr(1/4);
88 | }
89 | }
90 |
91 | &__terms {
92 | margin-left: vr(1/4);
93 |
94 | a {
95 | color: inherit;
96 | text-decoration: none;
97 |
98 | &:hover,
99 | &:focus,
100 | &:active {
101 | text-decoration: underline;
102 | }
103 | }
104 | }
105 |
106 | &__terms-icon {
107 | fill: currentColor;
108 | height: 16px;
109 | width: 16px;
110 | }
111 |
112 | // Sticky posts.
113 | &.sticky {}
114 |
115 | // Type of entry/post.
116 | &--type-post {}
117 |
118 | &--type-page {}
119 | }
120 |
--------------------------------------------------------------------------------
/resources/scss/vendor/woocommerce/components/_gallery.scss:
--------------------------------------------------------------------------------
1 | // Product gallery.
2 | .woocommerce-product-gallery {
3 | width: 100%;
4 | margin-bottom: vr(2);
5 | position: relative;
6 |
7 | @include mq(medium) {
8 | float: left;
9 | margin-right: vr(2);
10 | width: calc(50% - #{vr(1)});
11 | }
12 |
13 | img {
14 | display: block;
15 | width: 100%;
16 | height: auto;
17 | box-shadow: none;
18 | }
19 |
20 | &__wrapper {
21 | transition: all cubic-bezier(0.795, -0.035, 0, 1) 0.5s;
22 | margin: 0;
23 | padding: 0;
24 | max-width: none; // Important to make sure other images show.
25 | }
26 |
27 | .zoomImg {
28 | background-color: $color-white;
29 | opacity: 0;
30 | }
31 |
32 | // The zoom trigger.
33 | &__trigger {
34 | display: block;
35 | height: 20px;
36 | position: absolute;
37 | right: vr(1/4);
38 | text-align: center;
39 | top: vr(1/4);
40 | width: 20px;
41 | z-index: 1;
42 | line-height: 1;
43 | }
44 |
45 | // Default gallery without specific version enabled
46 | .woocommerce-product-gallery__image:nth-child(n + 2) {
47 | margin-right: vr(1/2);
48 | margin-top: vr(1/2);
49 | }
50 |
51 | // If its a flexslider gallery, remove margins.
52 | .flex-viewport .woocommerce-product-gallery__image {
53 | margin: 0;
54 | }
55 |
56 | @for $i from 2 through 6 {
57 |
58 | &--columns-#{$i} {
59 |
60 | .woocommerce-product-gallery__image:nth-child(n + 2) {
61 | width: calc(#{percentage(1 / $i)} - (#{vr(1/2)} / #{$i} * (#{$i} - 1)));
62 | float: left;
63 | }
64 |
65 | .woocommerce-product-gallery__image:nth-child(#{$i}n + 1) {
66 | margin-right: 0;
67 | }
68 | }
69 | }
70 |
71 |
72 | // Thumbnails if its a flexslider gallery.
73 | .flex-control-thumbs {
74 | display: flex;
75 | margin: 0;
76 | margin-top: vr(1/2);
77 |
78 | li {
79 | flex: 1;
80 | list-style: none;
81 | margin-right: vr(1/2);
82 | max-width: 100px;
83 |
84 | &:last-child {
85 | margin-right: 0;
86 | }
87 |
88 | img {
89 | cursor: pointer;
90 | opacity: 0.5;
91 | }
92 |
93 | img:hover,
94 | img:focus,
95 | .flex-active {
96 | opacity: 1;
97 | }
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/config/webpack.prod.js:
--------------------------------------------------------------------------------
1 | const merge = require( 'webpack-merge' );
2 | const common = require( './webpack.common.js' );
3 | const ImageminPlugin = require( 'imagemin-webpack-plugin' ).default;
4 | const imageminMozjpeg = require( 'imagemin-mozjpeg' );
5 | const TerserPlugin = require( 'terser-webpack-plugin' );
6 |
7 | module.exports = merge( common, {
8 | mode: 'production',
9 | plugins: [
10 |
11 | // Minify and optimize image/SVG files.
12 | new ImageminPlugin( {
13 | test: /\.(jpe?g|png|gif|svg)$/i,
14 | optipng: {
15 | optimizationLevel: 7,
16 | },
17 | gifsicle: {
18 | optimizationLevel: 3,
19 | },
20 | pngquant: {
21 | quality: '65-90',
22 | speed: 4,
23 | },
24 | svgo: {
25 | plugins: [
26 | { cleanupIDs: false },
27 | { mergePaths: false },
28 | { removeUnknownsAndDefaults: false },
29 | { removeViewBox: false },
30 | ],
31 | },
32 | plugins: [ imageminMozjpeg( { quality: 75 } ) ],
33 | } ),
34 | ],
35 |
36 | optimization: {
37 | minimizer: [
38 | new TerserPlugin( {
39 | cache: true,
40 | parallel: true,
41 | sourceMap: false,
42 | terserOptions: {
43 | parse: {
44 | // We want terser to parse ecma 8 code. However, we don't want it
45 | // to apply any minfication steps that turns valid ecma 5 code
46 | // into invalid ecma 5 code. This is why the 'compress' and 'output'
47 | // sections only apply transformations that are ecma 5 safe
48 | // https://github.com/facebook/create-react-app/pull/4234
49 | ecma: 8,
50 | },
51 | compress: {
52 | ecma: 5,
53 | warnings: false,
54 | // Disabled because of an issue with Uglify breaking seemingly valid code:
55 | // https://github.com/facebook/create-react-app/issues/2376
56 | // Pending further investigation:
57 | // https://github.com/mishoo/UglifyJS2/issues/2011
58 | comparisons: false,
59 | // Disabled because of an issue with Terser breaking valid code:
60 | // https://github.com/facebook/create-react-app/issues/5250
61 | // Pending futher investigation:
62 | // https://github.com/terser-js/terser/issues/120
63 | inline: 2,
64 | },
65 | output: {
66 | ecma: 5,
67 | comments: false,
68 | },
69 | ie8: false,
70 | },
71 | } ),
72 | ],
73 | },
74 | } );
75 |
--------------------------------------------------------------------------------
/resources/scss/elements/_forms.scss:
--------------------------------------------------------------------------------
1 | // 1. Reset Chrome and Firefox behaviour which sets a `min-width: min-content;`
2 | // on fieldsets.
3 | fieldset {
4 | border: 0;
5 | font-family: inherit;
6 | margin-bottom: vr(1);
7 | min-width: 0; /* [1] */
8 | }
9 |
10 | legend {
11 | font-weight: $font-weight-form-legend;
12 | margin-bottom: vr(1/2);
13 | }
14 |
15 | [type="text"],
16 | [type="email"],
17 | [type="url"],
18 | [type="password"],
19 | [type="search"],
20 | [type="number"],
21 | [type="tel"],
22 | [type="range"],
23 | [type="date"],
24 | [type="month"],
25 | [type="week"],
26 | [type="time"],
27 | [type="datetime"],
28 | [type="datetime-local"],
29 | [type="color"],
30 | textarea,
31 | select {
32 | background-color: $color-form-input-background;
33 | border: 1px solid $color-form-input-border;
34 | border-radius: $global-radius;
35 | color: $color-form-input;
36 | display: block;
37 | font-family: inherit;
38 | height: vr(1.75);
39 | outline: none;
40 | padding: vr(1/4) vr(1/2);
41 | width: 100%;
42 | }
43 |
44 | select[multiple] {
45 | height: auto;
46 | padding: vr(1/4) vr(1/2);
47 | }
48 |
49 | textarea {
50 | height: auto;
51 | padding: vr(1/2);
52 | vertical-align: top;
53 | }
54 |
55 | [type="file"] {
56 | background: none;
57 | border: none;
58 | box-shadow: none;
59 | display: inline-block;
60 | height: auto;
61 | padding: 0;
62 | width: auto;
63 | }
64 |
65 | [type="radio"],
66 | [type="checkbox"] {
67 | display: inline-block;
68 | height: auto;
69 | padding: 0;
70 | width: auto;
71 |
72 | & + & {
73 | margin-left: vr(1/2);
74 | }
75 |
76 | + label {
77 | display: inline-block;
78 | margin-left: vr(1/4);
79 | }
80 | }
81 |
82 | input,
83 | textarea,
84 | select {
85 |
86 | &:focus {
87 | border-color: $color-form-input-border-focus;
88 | outline: none;
89 | }
90 |
91 | &:disabled {
92 | color: $color-grey-500;
93 | cursor: not-allowed;
94 | font-style: italic;
95 | opacity: 0.3;
96 | resize: none;
97 | }
98 | }
99 |
100 | label {
101 | color: $color-form-label;
102 | display: block;
103 | font-weight: $font-weight-form-label;
104 | margin-bottom: vr(1/4);
105 | }
106 |
107 | [type="button"],
108 | [type="reset"],
109 | [type="submit"] {
110 | @include button;
111 | @include button-style($color-button-background, $color-button);
112 | }
113 |
--------------------------------------------------------------------------------
/resources/scss/vendor/woocommerce/_checkout.scss:
--------------------------------------------------------------------------------
1 | .woocommerce-checkout {
2 |
3 | /**
4 | * Notices and forms on the checkout
5 | */
6 | .woocommerce-form-coupon-toggle,
7 | .woocommerce-form-login-toggle {
8 |
9 | @include mq(medium) {
10 | margin-left: auto;
11 | margin-right: auto;
12 | max-width: 50%;
13 | }
14 |
15 | .woocommerce-info {
16 | text-align: center;
17 | background-color: transparent;
18 | color: $color-text;
19 | padding: 0;
20 |
21 | a {
22 | color: $color-text;
23 | }
24 | }
25 | }
26 |
27 |
28 | .woocommerce-form-login {
29 |
30 | p:first-child {
31 | text-align: center;
32 | }
33 | }
34 |
35 | .checkout_coupon {
36 | text-align: center;
37 | display: flex;
38 | flex-direction: column;
39 |
40 | @include mq(medium) {
41 | margin-left: auto;
42 | margin-right: auto;
43 | max-width: 50%;
44 | flex-direction: row;
45 | flex-wrap: wrap;
46 |
47 | p {
48 | width: 100%;
49 | }
50 | }
51 |
52 | .form-row-first {
53 | margin-right: 0;
54 | margin-bottom: vr(1/2);
55 | }
56 |
57 | [name="apply_coupon"] {
58 | width: 100%;
59 | }
60 | }
61 |
62 | // login form
63 | .woocommerce-form-login {
64 |
65 | @include mq(medium) {
66 | margin-left: auto;
67 | margin-right: auto;
68 | max-width: 50%;
69 | }
70 |
71 | p:first-child {
72 | text-align: center;
73 | }
74 | }
75 |
76 | // login form submit button
77 | .woocommerce-form-login__submit {
78 | width: 100%;
79 | }
80 |
81 | // Space between the form and any notices/coupon/login
82 | .woocommerce-checkout {
83 | margin-top: vr(2);
84 | }
85 |
86 | // The ship to a different address label
87 | .woocommerce-shipping-fields .woocommerce-form__label {
88 | font-size: $global-font-size;
89 | }
90 |
91 | // Order review table.
92 | .woocommerce-checkout-review-order-table {
93 |
94 | .product-name {
95 | text-align: left;
96 | }
97 | }
98 |
99 | // Payment methods
100 | .wc_payment_methods {
101 | list-style: none;
102 | margin-left: 0;
103 | }
104 |
105 | // Individual payment method
106 | .wc_payment_method {
107 | padding-top: vr(1/4);
108 | padding-bottom: vr(1/4);
109 | }
110 |
111 | // The box describing the payment method
112 | .payment_box {
113 | border: 1px solid $color-border;
114 | padding: vr(1/2);
115 | position: relative;
116 |
117 | :last-child {
118 | margin-bottom: 0;
119 | }
120 | }
121 |
122 | [name="woocommerce_checkout_place_order"] {
123 | @include button-style($color-primary);
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "luxe",
3 | "version": "1.0.0",
4 | "description": "Luxe is a WordPress starter theme using a modern workflow and best practices.",
5 | "main": "resources/js/app.js",
6 | "scripts": {
7 | "dev": "cross-env NODE_ENV=development webpack --config ./config/webpack.dev.js",
8 | "watch": "cross-env NODE_ENV=development webpack --watch --config ./config/webpack.dev.js",
9 | "production": "cross-env NODE_ENV=production webpack --config ./config/webpack.prod.js",
10 | "build": "npm run production && npm run i18n",
11 | "lint": "npm run lint:styles && npm run lint:scripts && npm run lint:php",
12 | "lint:styles": "cross-env stylelint './resources/scss/**/*.scss' --syntax scss",
13 | "lint:scripts": "cross-env eslint './resources/js/**/*.js'",
14 | "lint:php": "cross-env ./vendor/bin/phpcs .",
15 | "i18n": "npm run i18n:textdomain && npm run i18n:pot",
16 | "i18n:textdomain": "npx node-wp-i18n addtextdomain --exclude=vendor,node_modules",
17 | "i18n:pot": "npx node-wp-i18n makepot",
18 | "rename": "theme-claim --config='./config/rename.json'"
19 | },
20 | "repository": {
21 | "type": "git",
22 | "url": "git+https://github.com/brettsmason/luxe.git"
23 | },
24 | "author": "Brett Mason",
25 | "license": "GPL-2.0+",
26 | "bugs": {
27 | "url": "https://github.com/brettsmason/luxe/issues"
28 | },
29 | "homepage": "https://github.com/brettsmason/luxe#readme",
30 | "devDependencies": {
31 | "@babel/core": "^7.11.1",
32 | "@babel/preset-env": "^7.11.0",
33 | "@wordpress/eslint-plugin": "^3.3.0",
34 | "babel-loader": "^8.0.6",
35 | "browser-sync": "^2.26.13",
36 | "browser-sync-webpack-plugin": "^2.3.0",
37 | "clean-webpack-plugin": "^3.0.0",
38 | "copy-webpack-plugin": "^5.1.1",
39 | "cross-env": "^7.0.0",
40 | "css-loader": "^4.2.1",
41 | "cssnano": "^4.1.10",
42 | "eslint": "^6.8.0",
43 | "eslint-plugin-import": "^2.22.1",
44 | "fibers": "^5.0.0",
45 | "friendly-errors-webpack-plugin": "^1.7.0",
46 | "imagemin-mozjpeg": "^9.0.0",
47 | "imagemin-webpack-plugin": "^2.4.2",
48 | "mini-css-extract-plugin": "^0.9.0",
49 | "nth-grid": "github:brettsmason/nth-grid",
50 | "postcss-loader": "^3.0.0",
51 | "postcss-preset-env": "^6.7.0",
52 | "sass": "^1.32.5",
53 | "sass-loader": "^8.0.2",
54 | "sass-mq": "^5.0.1",
55 | "stylelint": "^12.0.1",
56 | "stylelint-config-wordpress": "^17.0.0",
57 | "stylelint-order": "^4.1.0",
58 | "stylelint-scss": "^3.14.2",
59 | "terser-webpack-plugin": "^4.2.3",
60 | "theme-claim": "^0.2.0",
61 | "webpack": "^4.44.2",
62 | "webpack-cli": "^3.3.12",
63 | "webpack-fix-style-only-entries": "^0.4.0",
64 | "webpack-manifest-plugin": "^2.2.0",
65 | "webpack-merge": "^4.2.2",
66 | "webpackbar": "^4.0.0"
67 | },
68 | "dependencies": {
69 | "core-js": "^3.6.5"
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/resources/scss/settings/_colors.scss:
--------------------------------------------------------------------------------
1 | // Brand colors
2 | $color-primary: #482880;
3 | $color-secondary: #292f36;
4 | $color-tertiary: #6b5ca5;
5 |
6 | // State colors
7 | $color-alert: #8c182b;
8 | $color-warning: #f6bf27;
9 | $color-success: #407d80;
10 |
11 |
12 | // Greyscale
13 | $color-grey-900: #202833;
14 | $color-grey-800: #404b5a;
15 | $color-grey-700: #6e7a8a;
16 | $color-grey-600: #929fb1;
17 | $color-grey-500: #aebecd;
18 | $color-grey-400: #ccd4db;
19 | $color-grey-300: #d5dde5;
20 | $color-grey-200: #e1e7ec;
21 | $color-grey-100: #f8f9fa;
22 |
23 | // Black/white
24 | $color-black: $color-grey-900;
25 | $color-white: #fff;
26 |
27 | /// Component specific colors
28 |
29 | // Page.
30 | $color-background: $color-white;
31 | $color-text: $color-grey-900;
32 |
33 | // Borders.
34 | $color-border: $color-grey-300;
35 |
36 | // Headings.
37 | $color-heading: $color-black;
38 |
39 | // Links.
40 | $color-link: $color-primary;
41 | $color-link-hover: $color-black;
42 |
43 | // Buttons.
44 | $color-button: $color-white;
45 | $color-button-background: $color-primary;
46 | $color-button-hover: $color-white;
47 | $color-button-hover-background: lighten($color-primary, 10%);
48 | $color-button-outline: $color-primary;
49 | $color-button-outline-border: $color-primary;
50 | $color-button-outline-hover: $color-white;
51 | $color-button-outline-hover-background: $color-primary;
52 |
53 | // Forms
54 | $color-form-fieldset-border: $color-border;
55 | $color-form-input-background: $color-white;
56 | $color-form-input: $color-text;
57 | $color-form-input-border: $color-border;
58 | $color-form-input-border-focus: $color-primary;
59 | $color-form-input-required: $color-alert;
60 | $color-form-label: $color-text;
61 |
62 | // Blockquotes.
63 | $color-blockquote: $color-grey-900;
64 | $color-blockquote-border: $color-grey-300;
65 |
66 | // Cite.
67 | $color-cite: $color-primary;
68 |
69 | // Code.
70 | $color-code: $color-grey-900;
71 | $color-code-background: $color-grey-100;
72 |
73 | // HR.
74 | $color-hr: $color-grey-300;
75 |
76 | // Colors used for social networks
77 | $colors-social: (
78 | facebook: #3b5998,
79 | instagram: #c13584,
80 | linkedin: #0077b5,
81 | pinterest: #bd081c,
82 | twitter: #1da1f2,
83 | vimeo: #1ab7ea,
84 | youtube: #cd201f
85 | );
86 |
87 | // Site Header.
88 | $color-header-title: $color-text;
89 |
90 | // Menu.
91 | $color-menu-items-background: $color-white;
92 | $color-menu-item-border: $color-border;
93 | $color-menu-link: $color-text;
94 | $color-menu-link-hover: $color-primary;
95 | $color-menu-dropdown-icon: $color-grey-900;
96 | $color-menu-sub-menu-background: $color-white;
97 | $color-menu-sub-menu-toggle: $color-grey-900;
98 | $color-menu-sub-menu-toggle-background: $color-grey-300;
99 |
100 | // Pagination.
101 | $color-pagination-anchor-border: $color-border;
102 |
103 | // Tables.
104 | $color-table-border: $color-border;
105 | $color-table-striped-background: $color-grey-300;
106 |
--------------------------------------------------------------------------------
/bootstrap/compat.php:
--------------------------------------------------------------------------------
1 | %s
', esc_html( luxe_compat_message() ) );
76 | }
77 |
78 | /**
79 | * Kills the loading of the customizer.
80 | *
81 | * @since 1.0.0
82 | * @access public
83 | * @return void
84 | */
85 | function luxe_load_customize() {
86 | wp_die( esc_html( luxe_compat_message() ), '', [ 'back_link' => true ] );
87 | }
88 |
89 | /**
90 | * Kills the customizer previewer on installs prior to WP 4.7.
91 | *
92 | * @since 1.0.0
93 | * @access public
94 | * @return void
95 | */
96 | function luxe_preview() {
97 | if ( isset( $_GET['preview'] ) ) { // WPCS: CSRF ok.
98 | wp_die( esc_html( luxe_compat_message() ) );
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/resources/scss/tools/_font-size.scss:
--------------------------------------------------------------------------------
1 | // Generates a rem font-size and a baseline-compatible
2 | // unitless line-height from a pixel font-size value. Basic usage is simply:
3 | //
4 | // @include font-size(18px);
5 | //
6 | // You can force a specific line-height by passing it as the second argument:
7 | //
8 | // @include font-size(16px, 1);
9 | //
10 | // You can also modify the line-height by increments, while staying in the
11 | // baseline grid, by setting the `$modifier` parameter. It takes a positive
12 | // or negative integer, and it will add or remove "lines" to the generated
13 | // line-height. This is the recomended way to do it, unless you really need
14 | // an absolute value. i.e.:
15 | //
16 | // // add 2 lines:
17 | // @include font-size(24px, $modifier: +2);
18 | //
19 | // // subtract 1 line:
20 | // @include font-size(24px, $modifier: -1);
21 |
22 | @mixin font-size(
23 | $font-size,
24 | $line-height: auto,
25 | $modifier: 0,
26 | $important: false
27 | ) {
28 | @if (type-of($font-size) == map) {
29 | @each $breakpoint, $size in $font-size {
30 |
31 | $_font-size: if(type-of($size) == list, nth($size, 1), $size);
32 | $_line-height: if(type-of($size) == list and length($size) >= 2, nth($size, 2), auto);
33 | $_modifier: if(type-of($size) == list and length($size) == 3, nth($size, 3), 0);
34 |
35 | @if ($breakpoint == null) {
36 | @include _get-font-size($_font-size, $_line-height, $_modifier);
37 | } @else {
38 | @include mq($breakpoint) {
39 | @include _get-font-size($_font-size, $_line-height, $_modifier);
40 | }
41 | }
42 | }
43 |
44 | } @else {
45 | @include _get-font-size($font-size, $line-height, $modifier, $important);
46 | }
47 | }
48 |
49 | // The internal logic for the font-size() mixin.
50 | @mixin _get-font-size(
51 | $font-size,
52 | $line-height: auto,
53 | $modifier: 0,
54 | $important: false
55 | ) {
56 | @if (type-of($font-size) == number) {
57 | @if (unit($font-size) != "px") {
58 | @error "`#{$font-size}` needs to be a pixel value.";
59 | }
60 | } @else {
61 | @error "`#{$font-size}` needs to be a number.";
62 | }
63 |
64 | @if ($important == true) {
65 | $important: !important;
66 | } @else if ($important == false) {
67 | $important: null;
68 | } @else {
69 | @error "`#{$important}` needs to be `true` or `false`.";
70 | }
71 |
72 | // Output the font size.
73 | font-size: $font-size $important;
74 |
75 | @if ($line-height == "auto") {
76 |
77 | // Define how many grid lines each text line should span.
78 | // By default, we set it to the minimum number of lines necessary
79 | // in order to contain the defined font-size, +1 for some breathing room.
80 | // This can be modified with the `$modifier` parameter.
81 | $lines: ceil($font-size / $global-baseline) + $modifier + 1;
82 | $line-height: $lines * $global-baseline;
83 |
84 | line-height: ($line-height / $font-size) $important;
85 |
86 | } @else {
87 |
88 | @if (type-of($line-height) == number or $line-height == "inherit" or $line-height == "normal") {
89 | line-height: $line-height $important;
90 | } @else if ($line-height != "none" and $line-height != false) {
91 | @error "D’oh! `#{$line-height}` is not a valid value for `$line-height`.";
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/resources/scss/editor.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * Blocks stylesheet for the theme.
3 | *
4 | * This is for the editor in WordPress 5.0 and beyond.
5 | */
6 |
7 | // Settings.
8 | //
9 | // Settings handle the configuration and don't output CSS. This is a good
10 | // place to define things like variables.
11 |
12 | @import "settings/global";
13 | @import "settings/colors";
14 |
15 |
16 | // Tools.
17 | //
18 | // These are used throughout the code but don't output CSS on their own.
19 | // Things like mixins and extensions go here.
20 |
21 | @import "~nth-grid/sass/nth-grid";
22 | @import "~sass-mq/mq";
23 | @import "tools/units";
24 | @import "tools/clearfix";
25 | @import "tools/hidden";
26 | @import "tools/button";
27 | @import "tools/font-size";
28 | @import "tools/vr";
29 | @import "tools/responsive-embed";
30 | @import "tools/wrapper";
31 |
32 |
33 | // Elements.
34 | //
35 | // Elements are (or should be) class-less designs for the base
36 | // HTML elements.
37 |
38 | @import "elements/headings";
39 | @import "elements/links";
40 | @import "elements/blockquote";
41 | @import "elements/lists";
42 | @import "elements/hr";
43 | @import "elements/tables";
44 | @import "elements/media";
45 | @import "elements/code";
46 | @import "elements/misc";
47 |
48 |
49 | // Blocks.
50 | //
51 | // Blocks are styles for specific editor blocks.
52 | //
53 |
54 | @import "blocks/wp-block-audio";
55 | @import "blocks/wp-block-button";
56 | @import "blocks/wp-block-categories";
57 | @import "blocks/wp-block-code";
58 | @import "blocks/wp-block-columns";
59 | @import "blocks/wp-block-cover";
60 | @import "blocks/wp-block-embed";
61 | @import "blocks/wp-block-file";
62 | @import "blocks/wp-block-gallery";
63 | @import "blocks/wp-block-image";
64 | @import "blocks/wp-block-latest-posts";
65 | @import "blocks/wp-block-media-text";
66 | @import "blocks/wp-block-preformatted";
67 | @import "blocks/wp-block-pullquote";
68 | @import "blocks/wp-block-quote";
69 | @import "blocks/wp-block-separator";
70 | @import "blocks/wp-block-table";
71 | @import "blocks/wp-block-verse";
72 |
73 |
74 | // Utilities.
75 | //
76 | // Utilities are helper classes and overrides. This gets loaded last.
77 | // If necessary, this is the only place where `!important` rules should
78 | // go, but only if necessary.
79 |
80 | @import "utilities/alignment";
81 | @import "utilities/clearfix";
82 | @import "utilities/color-palette";
83 | @import "utilities/headings";
84 | @import "utilities/hide";
85 |
86 |
87 | // Editor related styles which overwrite above styles.
88 |
89 | body {
90 | background-color: $color-background;
91 | color: $color-text;
92 | font-family: $font-family-body;
93 | font-size: $global-font-size;
94 | line-height: $global-line-height;
95 | }
96 |
97 | p {
98 | font-size: $global-font-size;
99 | }
100 |
101 | .editor-post-title__block .editor-post-title__input {
102 | @include font-size($h1);
103 | color: $color-heading;
104 | font-family: $font-family-heading;
105 | font-weight: $font-weight-heading;
106 | }
107 |
108 | // Sets the default width of the content and the title.
109 | .wp-block {
110 | max-width: $global-width;
111 |
112 | // Wide aligned blocks.
113 | &[data-align="wide"] {
114 | max-width: $global-width-wide;
115 | }
116 |
117 | // Full width aligned blocks.
118 | &[data-align="full"] {
119 | max-width: none;
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/app/WooCommerce/Setup/Setup.php:
--------------------------------------------------------------------------------
1 |
7 | * @copyright Copyright (c) 2018, Brett Mason
8 | * @link https://github.com/brettsmason/luxe
9 | * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
10 | */
11 |
12 | namespace Luxe\WooCommerce\Setup;
13 |
14 | use Hybrid\Contracts\Bootable;
15 | use function Hybrid\Template\path;
16 | use function Luxe\asset;
17 |
18 | /**
19 | * Handles setting up everything we need for WooCommerce.
20 | *
21 | * @since 1.0.0
22 | * @access public
23 | */
24 | class Setup implements Bootable {
25 |
26 | /**
27 | * Adds actions on the appropriate action hooks.
28 | *
29 | * @since 1.0.0
30 | * @access public
31 | * @return void
32 | */
33 | public function boot() {
34 |
35 | // Register theme support for WooCommerce features.
36 | add_action( 'after_setup_theme', [ $this, 'register' ] );
37 |
38 | // Set path to WooCommerce templates.
39 | add_filter( 'woocommerce_template_loader_files', [ $this, 'templateLoaderFiles' ], PHP_INT_MAX );
40 |
41 | // Moves the WooCommerce template path.
42 | add_filter( 'woocommerce_template_path', [ $this, 'templatePath' ] );
43 |
44 | // Disable WooCommerce core styles.
45 | add_filter( 'woocommerce_enqueue_styles', [ $this, 'disableCoreStyles' ] );
46 |
47 | // Add custom WooCommerce styles.
48 | add_action( 'wp_enqueue_scripts', [ $this, 'styles' ], 10 );
49 | }
50 |
51 | /**
52 | * Add theme support for WooCommerce features.
53 | *
54 | * @link https://docs.woocommerce.com/document/woocommerce-theme-developer-handbook/
55 | * @since 1.0.0
56 | * @access public
57 | * @return void
58 | */
59 | public function register() {
60 |
61 | add_theme_support( 'woocommerce', [
62 | 'thumbnail_image_width' => 300,
63 | 'single_image_width' => 600,
64 |
65 | 'product_grid' => [
66 | 'default_rows' => 4,
67 | 'min_rows' => 2,
68 | 'max_rows' => 8,
69 | 'default_columns' => 4,
70 | 'min_columns' => 2,
71 | 'max_columns' => 6,
72 | ],
73 | ] );
74 |
75 | add_theme_support( 'wc-product-gallery-zoom' );
76 | add_theme_support( 'wc-product-gallery-lightbox' );
77 | add_theme_support( 'wc-product-gallery-slider' );
78 | }
79 |
80 | /**
81 | * This overrides the top-level WooCommerce templates that would normally go in
82 | * the theme root. By default, we're looking for a `resources/views/woocommerce.php`
83 | * template, which falls back to `resources/views/index.php`.
84 | *
85 | * @since 1.0.0
86 | * @access public
87 | * @param array $files
88 | * @return array
89 | */
90 | public function templateLoaderFiles( $files ) {
91 |
92 | return [
93 | path( 'woocommerce.php' ),
94 | path( 'index.php' ),
95 | ];
96 | }
97 |
98 | /**
99 | * Filters the path to the `woocommerce` template parts folder. This filter
100 | * moves that folder to `resources/views/woocommerce`.
101 | *
102 | * @since 1.0.0
103 | * @access public
104 | * @param string $path
105 | * @return string
106 | */
107 | public function templatePath( $path ) {
108 |
109 | return path( $path );
110 | }
111 |
112 | /**
113 | * Disable core WooCommerce stylesheets.
114 | */
115 | public function disableCoreStyles() {
116 | return [];
117 | }
118 |
119 | /**
120 | * Enqueue WooCommerce custom styles.
121 | *
122 | * @since 1.0.0
123 | * @access public
124 | * @return void
125 | */
126 | public function styles() {
127 |
128 | wp_enqueue_style(
129 | 'luxe-woocommerce',
130 | asset( 'css/woocommerce.css' ),
131 | false,
132 | null
133 | );
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/config/webpack.common.js:
--------------------------------------------------------------------------------
1 | const path = require( 'path' );
2 | const { CleanWebpackPlugin } = require( 'clean-webpack-plugin' );
3 | const CopyWebpackPlugin = require( 'copy-webpack-plugin' );
4 | const FixStyleOnlyEntriesPlugin = require( 'webpack-fix-style-only-entries' );
5 | const FriendlyErrorsWebpackPlugin = require( 'friendly-errors-webpack-plugin' );
6 | const ManifestPlugin = require( 'webpack-manifest-plugin' );
7 | const MiniCssExtractPlugin = require( 'mini-css-extract-plugin' );
8 | const WebpackBar = require( 'webpackbar' );
9 |
10 | const isProduction = process.env.NODE_ENV === 'production';
11 |
12 | // Build settings.
13 | const settings = require( './webpack.settings.js' );
14 |
15 | module.exports = {
16 | entry: settings.entries,
17 |
18 | output: {
19 | path: path.resolve( process.cwd(), settings.paths.public ),
20 | filename: settings.outputs.javascript,
21 | },
22 |
23 | // Console stats output.
24 | stats: settings.stats,
25 |
26 | // External objects.
27 | externals: settings.externals,
28 |
29 | // custom modules resolving.
30 | resolve: settings.resolve,
31 |
32 | // Performance settings.
33 | performance: {
34 | hints: false,
35 | maxAssetSize: 100000,
36 | },
37 |
38 | // Build rules to handle asset files.
39 | module: {
40 | rules: [
41 |
42 | // Scripts.
43 | {
44 | test: /\.js$/,
45 | exclude: /node_modules/,
46 | use: [
47 | {
48 | loader: 'babel-loader',
49 | options: {
50 | cacheDirectory: true,
51 | sourceMap: ! isProduction,
52 | },
53 | },
54 | ],
55 | },
56 |
57 | // Styles.
58 | {
59 | test: /\.s[ac]ss$/,
60 | include: path.resolve( process.cwd(), settings.paths.sass ),
61 | use: [
62 | MiniCssExtractPlugin.loader,
63 | {
64 | loader: 'css-loader',
65 | options: {
66 | sourceMap: ! isProduction,
67 | url: false,
68 | },
69 | },
70 | {
71 | loader: 'postcss-loader',
72 | options: {
73 | sourceMap: ! isProduction,
74 | },
75 | },
76 | {
77 | loader: 'sass-loader',
78 | options: {
79 | implementation: require( 'sass' ),
80 | sourceMap: ! isProduction,
81 | sassOptions: {
82 | fiber: require( 'fibers' ),
83 | outputStyle: 'expanded',
84 | },
85 | },
86 | },
87 | ],
88 | },
89 | ],
90 | },
91 |
92 | plugins: [
93 |
94 | // Friendlier errors.
95 | new FriendlyErrorsWebpackPlugin(),
96 |
97 | // Remove the extra JS files Webpack creates for Sass entries.
98 | // This should be fixed in Webpack 5.
99 | new FixStyleOnlyEntriesPlugin( {
100 | silent: true,
101 | } ),
102 |
103 | // Clean the `public` folder on build.
104 | new CleanWebpackPlugin( {
105 | cleanStaleWebpackAssets: true,
106 | verbose: false,
107 | } ),
108 |
109 | // Create our cache busting asset manifest.
110 | new ManifestPlugin( {
111 |
112 | // Filter using only .js and .css files.
113 | filter: ( { name } ) => name.endsWith( '.js' ) || name.endsWith( '.css' ),
114 | map: ( file ) => {
115 | // Add hash details on production for cache busting.
116 | return {
117 | name: file.path,
118 | path: isProduction ? `${ file.path }?id=${ file.chunk.hash }` : file.path,
119 | };
120 | },
121 | } ),
122 |
123 | // Extract CSS into individual files.
124 | new MiniCssExtractPlugin( {
125 | filename: settings.outputs.css,
126 | chunkFilename: '[id].css',
127 | } ),
128 |
129 | // Copy static assets to the `public` folder.
130 | new CopyWebpackPlugin(
131 | [ {
132 | from: '**/*.{jpg,jpeg,png,gif,svg,eot,ttf,woff,woff2}',
133 | to: '[path][name].[ext]',
134 | context: path.resolve( process.cwd(), settings.paths.assets ),
135 | } ],
136 | {
137 | copyUnmodified: true,
138 | }
139 | ),
140 |
141 | // Fancy WebpackBar.
142 | new WebpackBar(),
143 | ],
144 | };
145 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | # Travis CI (MIT License) configuration file for the WordPress theme.
2 | # @link https://travis-ci.org/
3 |
4 | # For use with the WordPress theme.
5 | # @link https://github.com/samikeijonen/uuups
6 |
7 | # Ditch sudo and use containers.
8 | # @link https://docs.travis-ci.com/user/migrating-from-legacy/#Why-migrate-to-container-based-infrastructure%3F
9 | # @link https://docs.travis-ci.com/user/workers/container-based-infrastructure/#Routing-your-build-to-container-based-infrastructure
10 | sudo: false
11 | dist: trusty
12 |
13 | # Declare project language.
14 | # @link https://about.travis-ci.org/docs/user/languages/php/
15 | language: php
16 |
17 | # Declare versions of PHP to use. Use one decimal max.
18 | # @link https://docs.travis-ci.com/user/build-configuration/
19 | matrix:
20 | fast_finish: true
21 |
22 | include:
23 | # aliased to a recent 5.6.x version
24 | - php: '5.6'
25 | env: SNIFF=1
26 | # aliased to a recent 7.0.x version
27 | - php: '7.0'
28 | # aliased to a recent 7.2.x version
29 | - php: '7.2'
30 | # bleeding edge PHP
31 | - php: 'nightly'
32 |
33 | allow_failures:
34 | - php: 'nightly'
35 |
36 | # Use this to prepare the system to install prerequisites or dependencies.
37 | # e.g. sudo apt-get update.
38 | # Failures in this section will result in build status 'errored'.
39 | before_install:
40 | - npm install -g npm@latest
41 |
42 | # Use this to prepare your build for testing.
43 | # e.g. copy database configurations, environment variables, etc.
44 | # Failures in this section will result in build status 'errored'.
45 | before_script:
46 | # Speed up build time by disabling Xdebug.
47 | - phpenv config-rm xdebug.ini || echo 'No xdebug config.'
48 | # Set up temporary paths.
49 | - export PHPCS_DIR=/tmp/phpcs
50 | - export WPCS_DIR=/tmp/wpcs
51 | - export PHPCOMPAT_DIR=/tmp/phpcompatibility
52 | # Install CodeSniffer for WordPress Coding Standards checks.
53 | - if [[ "$SNIFF" == "1" ]]; then git clone -b master --depth 1 https://github.com/squizlabs/PHP_CodeSniffer.git $PHPCS_DIR; fi
54 | # Install WordPress Coding Standards.
55 | - if [[ "$SNIFF" == "1" ]]; then git clone -b master --depth 1 https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards.git $WPCS_DIR; fi
56 | # Install PHP Compatibility sniffs.
57 | - if [[ "$SNIFF" == "1" ]]; then git clone -b master --depth 1 https://github.com/wimg/PHPCompatibility.git $PHPCOMPAT_DIR; fi
58 | # Set install path for PHPCS sniffs.
59 | # @link https://github.com/squizlabs/PHP_CodeSniffer/blob/4237c2fc98cc838730b76ee9cee316f99286a2a7/CodeSniffer.php#L1941
60 | - if [[ "$SNIFF" == "1" ]]; then $PHPCS_DIR/bin/phpcs --config-set installed_paths $WPCS_DIR,$PHPCOMPAT_DIR; fi
61 | # After CodeSniffer install you should refresh your path.
62 | - if [[ "$SNIFF" == "1" ]]; then phpenv rehash; fi
63 | # Install eslint.
64 | # @link https://eslint.org/
65 | - if [[ "$SNIFF" == "1" ]]; then npm install -g eslint eslint-config-wordpress; fi
66 | # Install stylelint.
67 | # @link https://stylelint.io/
68 | - if [[ "$SNIFF" == "1" ]]; then npm install -g stylelint stylelint-config-wordpress; fi
69 |
70 | # Run test script commands.
71 | # Default is specific to project language.
72 | # All commands must exit with code 0 on success. Anything else is considered failure.
73 | script:
74 | # Search for PHP syntax errors.
75 | - find -L . -name '*.php' -print0 | xargs -0 -n 1 -P 4 php -l
76 | # Run the theme through ESLint.
77 | - if [[ "$SNIFF" == "1" ]]; then eslint './resources/js/**/*.js' --config ./.eslintrc.js .; fi
78 | # Run the theme through stylelint.
79 | - if [[ "$SNIFF" == "1" ]]; then stylelint './resources/scss/**/*.scss' --syntax scss --config node_modules/stylelint-config-wordpress/scss.js .; fi
80 | # WordPress Coding Standards.
81 | # @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards
82 | # @link https://pear.php.net/package/PHP_CodeSniffer/
83 | # Uses a custom ruleset based on WordPress. This ruleset is automatically
84 | # picked up by PHPCS as it's named `phpcs.xml(.dist)`.
85 | - if [[ "$SNIFF" == "1" ]]; then $PHPCS_DIR/bin/phpcs --runtime-set ignore_warnings_on_exit 1; fi
86 |
87 | # Receive notifications for build results.
88 | # @link https://docs.travis-ci.com/user/notifications/#Email-notifications
89 | notifications:
90 | email: false
91 |
--------------------------------------------------------------------------------
/phpcs.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
17 | 18 | 'ol', 22 | 'callback' => function( $comment, $args, $depth ) { 23 | Hybrid\View\display( 'components', Hybrid\Comment\hierarchy(), compact( 'comment', 'args', 'depth' ) ); 24 | } 25 | ] 26 | ) 27 | ?> 28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 |36 | 37 |
38 | 39 | 40 | 41 |