├── .gitignore ├── babel.config.json ├── assets └── src │ ├── scss │ ├── 5-components │ │ └── .gitkeep │ ├── 3-vendors │ │ ├── _lazysizes.scss │ │ ├── _s2r.scss │ │ └── _wordpress.scss │ ├── 2-utilities │ │ ├── _layout.scss │ │ └── _type.scss │ ├── 4-objects │ │ ├── _button.scss │ │ └── _nav.scss │ ├── 6-misc │ │ ├── _hacks.scss │ │ └── _print.scss │ ├── 1-setup │ │ ├── _base.scss │ │ └── _type.scss │ ├── editorStyles.scss │ └── main.scss │ ├── fonts │ ├── montserrat-bold-webfont.woff │ ├── montserrat-black-webfont.woff │ ├── montserrat-black-webfont.woff2 │ ├── montserrat-bold-webfont.woff2 │ ├── montserrat-light-webfont.woff │ ├── montserrat-light-webfont.woff2 │ ├── montserrat-regular-webfont.woff │ └── montserrat-regular-webfont.woff2 │ ├── images │ └── logo-bymattlee-login.svg │ ├── svgs │ ├── icon-facebook.svg │ ├── icon-twitter.svg │ ├── icon-youtube.svg │ ├── icon-bymattlee.svg │ └── icon-instagram.svg │ └── js │ ├── components │ ├── global.js │ ├── richText.js │ └── taxi.js │ ├── utilities │ ├── helper.js │ └── check.js │ ├── transitions │ └── Default.js │ ├── main.js │ └── vendors │ └── Scroll2Reveal.js ├── screenshot.png ├── sidebar.php ├── .eslintrc ├── footer.php ├── gulpfile.babel.js ├── tasks │ ├── default.js │ ├── clean.js │ ├── copy.js │ ├── browserSync.js │ ├── build.js │ ├── svgs.js │ ├── images.js │ ├── watch.js │ ├── scripts.js │ └── styles.js ├── index.js └── config.js ├── partials ├── global │ ├── not_found.php │ ├── pagination-archive.php │ ├── header.php │ ├── pagination-single.php │ └── footer.php ├── page │ └── default.php └── news │ ├── single.php │ └── preview.php ├── searchform.php ├── page.php ├── tailwindUtilities.js ├── single.php ├── style.css ├── 404.php ├── archive.php ├── index.php ├── search.php ├── LICENSE.md ├── includes ├── acf.php ├── editor_styles.php ├── sidebars.php ├── enqueue.php ├── utilities.php ├── require_plugins.php ├── admin_display.php ├── markup_cleanup.php ├── menus.php ├── theme_setup.php └── cpt-books.php ├── .stylelintrc ├── functions.php ├── header.php ├── package.json ├── tailwind.config.js ├── README.md ├── languages └── _bymattlee.po └── acf-global-options.json /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /assets/dist -------------------------------------------------------------------------------- /babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env"] 3 | } -------------------------------------------------------------------------------- /assets/src/scss/5-components/.gitkeep: -------------------------------------------------------------------------------- 1 | User-specific packages can be placed here 2 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bymattlee/bymattlee-wp-starter-theme/HEAD/screenshot.png -------------------------------------------------------------------------------- /assets/src/fonts/montserrat-bold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bymattlee/bymattlee-wp-starter-theme/HEAD/assets/src/fonts/montserrat-bold-webfont.woff -------------------------------------------------------------------------------- /assets/src/fonts/montserrat-black-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bymattlee/bymattlee-wp-starter-theme/HEAD/assets/src/fonts/montserrat-black-webfont.woff -------------------------------------------------------------------------------- /assets/src/fonts/montserrat-black-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bymattlee/bymattlee-wp-starter-theme/HEAD/assets/src/fonts/montserrat-black-webfont.woff2 -------------------------------------------------------------------------------- /assets/src/fonts/montserrat-bold-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bymattlee/bymattlee-wp-starter-theme/HEAD/assets/src/fonts/montserrat-bold-webfont.woff2 -------------------------------------------------------------------------------- /assets/src/fonts/montserrat-light-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bymattlee/bymattlee-wp-starter-theme/HEAD/assets/src/fonts/montserrat-light-webfont.woff -------------------------------------------------------------------------------- /assets/src/fonts/montserrat-light-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bymattlee/bymattlee-wp-starter-theme/HEAD/assets/src/fonts/montserrat-light-webfont.woff2 -------------------------------------------------------------------------------- /assets/src/fonts/montserrat-regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bymattlee/bymattlee-wp-starter-theme/HEAD/assets/src/fonts/montserrat-regular-webfont.woff -------------------------------------------------------------------------------- /assets/src/fonts/montserrat-regular-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bymattlee/bymattlee-wp-starter-theme/HEAD/assets/src/fonts/montserrat-regular-webfont.woff2 -------------------------------------------------------------------------------- /sidebar.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "parserOptions": { 4 | "ecmaVersion": 6, 5 | "sourceType": "module", 6 | }, 7 | "extends": "eslint:recommended", 8 | "env": { 9 | "browser": true, 10 | "es6": true 11 | } 12 | } -------------------------------------------------------------------------------- /footer.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /assets/src/images/logo-bymattlee-login.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/src/svgs/icon-facebook.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/src/scss/3-vendors/_lazysizes.scss: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | ** ***** Vendors/Lazysizes Overrides 3 | ** ***** ----------------------------------------------- ***** */ 4 | 5 | .lazyload, 6 | .lazyloading { 7 | @apply u-opacity-0; 8 | } 9 | 10 | .lazyloaded { 11 | @apply u-opacity-100 u-transition-opacity u-duration-slow; 12 | } 13 | -------------------------------------------------------------------------------- /gulpfile.babel.js/tasks/default.js: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | /* ***** Default 3 | /* ***** ----------------------------------------------- ***** */ 4 | 5 | import build from './build.js' 6 | import gulp from 'gulp' 7 | import watch from './watch.js' 8 | 9 | const defaultTask = gulp.series(build, watch) 10 | 11 | export default defaultTask 12 | -------------------------------------------------------------------------------- /partials/global/not_found.php: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 |

6 | 7 | 8 | 9 |

10 | 11 | 12 | 13 |
-------------------------------------------------------------------------------- /searchform.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/src/js/components/global.js: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | ** ***** Global JS 3 | ** ***** ----------------------------------------------- ***** */ 4 | 5 | import Alpine from 'alpinejs' 6 | import 'lazysizes' 7 | import 'lazysizes/plugins/bgset/ls.bgset' 8 | 9 | const init = () => { 10 | window.Alpine = Alpine 11 | Alpine.start() 12 | } 13 | 14 | export { init } 15 | -------------------------------------------------------------------------------- /gulpfile.babel.js/tasks/clean.js: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | /* ***** Gulp - Clean 3 | /* ***** ----------------------------------------------- ***** */ 4 | 5 | import config from '../config' 6 | import del from 'del' 7 | 8 | // Delete dist directory for a clean project rebuild 9 | const clean = () => { 10 | return del(config.clean.dest) 11 | } 12 | 13 | export default clean 14 | -------------------------------------------------------------------------------- /assets/src/scss/2-utilities/_layout.scss: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | ** ***** Utilities/Layout 3 | ** ***** ----------------------------------------------- ***** */ 4 | 5 | @layer utilities { 6 | .l-container { 7 | @apply u-w-full u-mx-auto u-px-30 u-relative sm:u-px-50; 8 | max-width: 128rem; 9 | 10 | &--small { 11 | max-width: 78rem; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /gulpfile.babel.js/index.js: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | /* ***** Gulp 3 | /* ***** ----------------------------------------------- ***** */ 4 | 5 | import gulp from 'gulp' 6 | import defaultTask from './tasks/default.js' 7 | import build from './tasks/build.js' 8 | import watch from './tasks/watch.js' 9 | 10 | // Available tasks 11 | gulp.task('default', defaultTask) 12 | gulp.task('build', build) 13 | gulp.task('watch', watch) 14 | -------------------------------------------------------------------------------- /page.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 |
18 |
19 | 20 | -------------------------------------------------------------------------------- /assets/src/scss/4-objects/_button.scss: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | ** ***** Objects/Buttons Styles 3 | ** ***** ----------------------------------------------- ***** */ 4 | 5 | .o-button { 6 | @apply u-inline-block u-bg-grey-light-c u-text-black u-leading-loose u-px-20 u-py-8 7 | u-transition-colors u-duration-slow hover:u-bg-grey-dark-4 hover:u-text-grey-light-c 8 | active:u-bg-grey-light-a active:u-text-black sm:u-px-25 sm:u-py-10; 9 | } 10 | -------------------------------------------------------------------------------- /tailwindUtilities.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | fontFallbacks: [ 3 | 'ui-sans-serif', 4 | 'system-ui', 5 | '-apple-system', 6 | 'BlinkMacSystemFont', 7 | '"Segoe UI"', 8 | 'Roboto', 9 | '"Helvetica Neue"', 10 | 'Arial', 11 | '"Noto Sans"', 12 | 'sans-serif', 13 | '"Apple Color Emoji"', 14 | '"Segoe UI Emoji"', 15 | '"Segoe UI Symbol"', 16 | '"Noto Color Emoji"', 17 | ], 18 | pxToEm: function(px) { 19 | return `${px / 16}em` 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /assets/src/svgs/icon-twitter.svg: -------------------------------------------------------------------------------- 1 | icon -------------------------------------------------------------------------------- /gulpfile.babel.js/tasks/copy.js: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | /* ***** Gulp - Copy 3 | /* ***** ----------------------------------------------- ***** */ 4 | 5 | import changed from 'gulp-changed' 6 | import config from '../config' 7 | import gulp from 'gulp' 8 | 9 | // Copy all asset files to dist directory (fonts, swfs, videos, etc) 10 | const copy = () => { 11 | return gulp 12 | .src(config.copy.src) 13 | .pipe(changed(config.copy.dest)) 14 | .pipe(gulp.dest(config.copy.dest)) 15 | } 16 | 17 | export default copy 18 | -------------------------------------------------------------------------------- /single.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 |
20 |
21 | 22 | -------------------------------------------------------------------------------- /assets/src/svgs/icon-youtube.svg: -------------------------------------------------------------------------------- 1 | icon -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** 2 | Theme Name: ByMattLee WP Starter Theme 3 | Theme URI: https://github.com/bymattlee/bymattlee-wp-starter-theme 4 | Description: A starter theme created by Matt Lee 5 | Tags: bymattlee starter files, matt lee, starter files, bymattlee 6 | Version: 1.0.0 7 | Author: Matt Lee 8 | Author URI: http://www.bymattlee.com 9 | Text Domain: bymattlee 10 | Domain Path: /languages 11 | License: MIT License 12 | License URI: http://opensource.org/licenses/MIT 13 | /* ***** ----------------------------------------------- ***** */ -------------------------------------------------------------------------------- /assets/src/scss/3-vendors/_s2r.scss: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | ** ***** Vendors/Scroll2Reveal 3 | ** ***** ----------------------------------------------- ***** */ 4 | 5 | [data-s2r-type='block-fade-up'], 6 | [data-s2r-type='block-fade-in'], 7 | [data-s2r-el]:not([data-s2r-el='stagger-fade-up']):not([data-s2r-el='stagger-fade-in']), 8 | [data-s2r-el='stagger-fade-up'] > *, 9 | [data-s2r-el='stagger-fade-in'] > *, 10 | [data-s2r-type='stagger-fade-up-children'] > *, 11 | [data-s2r-type='stagger-fade-in-children'] > * { 12 | @apply u-opacity-0; 13 | } 14 | -------------------------------------------------------------------------------- /gulpfile.babel.js/tasks/browserSync.js: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | /* ***** Gulp - BrowserSync 3 | /* ***** ----------------------------------------------- ***** */ 4 | 5 | import browserSync from 'browser-sync' 6 | import config from '../config' 7 | 8 | /* 9 | ** -- Initialize BrowserSync 10 | ** -- Use directory specified in config as the root for the server 11 | */ 12 | const browserSyncTask = () => { 13 | browserSync.init(config.browserSync.files, { 14 | proxy: config.browserSync.proxy, 15 | }) 16 | } 17 | 18 | export default browserSyncTask 19 | -------------------------------------------------------------------------------- /assets/src/js/utilities/helper.js: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | ** ***** Helper Utilities JS 3 | ** ***** ----------------------------------------------- ***** */ 4 | 5 | const getUrlParameter = (name) => { 6 | name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]') // eslint-disable-line no-useless-escape 7 | const regex = new RegExp('[\\?&]' + name + '=([^&#]*)') 8 | const results = regex.exec(location.search) 9 | 10 | return results === null 11 | ? '' 12 | : decodeURIComponent(results[1].replace(/\+/g, ' ')) 13 | } 14 | 15 | export { getUrlParameter } 16 | -------------------------------------------------------------------------------- /assets/src/js/transitions/Default.js: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | ** ***** Default JS 3 | ** ***** ----------------------------------------------- ***** */ 4 | 5 | import { Transition } from '@unseenco/taxi' 6 | import gsap from 'gsap' 7 | 8 | export default class Default extends Transition { 9 | onLeave({ from, done }) { 10 | gsap.fromTo(from, 0.3, { opacity: 1 }, { opacity: 0, onComplete: done }) 11 | } 12 | 13 | onEnter({ to, done }) { 14 | // Reset Scroll 15 | window.scrollTo(0, 0) 16 | 17 | // Animation 18 | gsap.fromTo(to, 0.3, { opacity: 0 }, { opacity: 1, onComplete: done }) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /partials/global/pagination-archive.php: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 5 | 6 | 7 |
8 |
9 | 10 | 11 | 12 |
13 |
14 | -------------------------------------------------------------------------------- /gulpfile.babel.js/tasks/build.js: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | /* ***** Gulp - Build 3 | /* ***** ----------------------------------------------- ***** */ 4 | 5 | import clean from './clean.js' 6 | import copy from './copy.js' 7 | import gulp from 'gulp' 8 | import images from './images.js' 9 | import scripts from './scripts.js' 10 | import { styles } from './styles.js' 11 | import svgs from './svgs.js' 12 | 13 | /* 14 | ** -- Clean dist directory 15 | ** -- Run all tasks to rebuild project 16 | */ 17 | const build = gulp.series( 18 | clean, 19 | gulp.parallel(styles, scripts, images, svgs, copy) 20 | ) 21 | 22 | export default build 23 | -------------------------------------------------------------------------------- /partials/global/header.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/src/scss/4-objects/_nav.scss: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | ** ***** Objects/Nav Styles 3 | ** ***** ----------------------------------------------- ***** */ 4 | 5 | .o-nav { 6 | $this: &; 7 | 8 | &__menu { 9 | @apply u-m-0; 10 | } 11 | 12 | &__menu-list-item { 13 | @apply u-inline-block u-ml-10 md:u-ml-15; 14 | 15 | &:first-child { 16 | @apply u-ml-0; 17 | } 18 | 19 | &--current { 20 | #{$this}__menu-item { 21 | @apply u-text-white; 22 | } 23 | } 24 | } 25 | 26 | &__menu-item { 27 | @apply u-inline-block u-font-heading u-text-14 u-uppercase; 28 | } 29 | 30 | &__sub-menu { 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /assets/src/svgs/icon-bymattlee.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /partials/global/pagination-single.php: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 5 | 6 | 7 | 8 |
9 |
10 | 11 | 12 | 13 | 14 |
15 |
16 | -------------------------------------------------------------------------------- /404.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |
6 |
7 |

8 |
9 |
10 |

11 |

12 |
13 |
14 | 15 | 16 | 17 |
18 |
19 | 20 | -------------------------------------------------------------------------------- /assets/src/js/components/richText.js: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | ** ***** Rich Text JS 3 | ** ***** ----------------------------------------------- ***** */ 4 | 5 | const responsiveVideoWrap = () => { 6 | const iframes = document.querySelectorAll('.js-rich-text iframe') 7 | 8 | iframes.forEach((iframe) => { 9 | const iframeSrc = iframe.getAttribute('src') 10 | if (iframeSrc.includes('youtube') || iframeSrc.includes('vimeo')) { 11 | const embedWrapper = document.createElement('div') 12 | embedWrapper.classList = 13 | 'u-aspect-w-16 u-aspect-h-9 u-my-30 u-mx-0 sm:u-my-40' 14 | iframe.parentNode.insertBefore(embedWrapper, iframe) 15 | embedWrapper.appendChild(iframe) 16 | } 17 | }) 18 | } 19 | 20 | const init = () => { 21 | responsiveVideoWrap() 22 | } 23 | 24 | export { init } 25 | -------------------------------------------------------------------------------- /partials/page/default.php: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | <?php echo get_post_meta( get_post_thumbnail_id(), '_wp_attachment_image_alt', true ); ?> 5 |
6 | 7 | 8 | 9 |
10 |

11 |
12 | 13 | 14 | 15 |
16 | 17 |
18 | 19 |
-------------------------------------------------------------------------------- /gulpfile.babel.js/tasks/svgs.js: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | /* ***** Gulp - SVGs 3 | /* ***** ----------------------------------------------- ***** */ 4 | 5 | import config from '../config' 6 | import gulp from 'gulp' 7 | import imagemin from 'gulp-imagemin' 8 | import size from 'gulp-size' 9 | import svgSprite from 'gulp-svg-sprite' 10 | 11 | /* 12 | ** -- Optimize SVG files 13 | ** -- Create SVG sprite 14 | */ 15 | const svgs = () => { 16 | return gulp 17 | .src(config.svgs.src) 18 | .pipe(imagemin()) 19 | .pipe( 20 | svgSprite({ 21 | mode: { 22 | symbol: { 23 | dest: '', 24 | sprite: config.svgs.sprite, 25 | }, 26 | }, 27 | }) 28 | ) 29 | .pipe( 30 | size({ 31 | title: 'Optimized File Size:', 32 | showFiles: true, 33 | }) 34 | ) 35 | .pipe(gulp.dest(config.svgs.dest)) 36 | } 37 | 38 | export default svgs 39 | -------------------------------------------------------------------------------- /assets/src/scss/6-misc/_hacks.scss: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | ** ***** Base/Hacks (http://browserstrangeness.bitbucket.org/css_hacks.html) 3 | ** ***** ----------------------------------------------- ***** */ 4 | 5 | /* ***** IE Hacks 6 | ** ***** ----------------------------------------------- ***** */ 7 | 8 | // Edge 12+ 9 | @supports (-webkit-appearance:none) { 10 | 11 | } 12 | 13 | // IE 10 and 11 14 | @media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) { 15 | 16 | } 17 | 18 | 19 | /* ***** Safari Hacks 20 | ** ***** ----------------------------------------------- ***** */ 21 | 22 | /* stylelint-disable */ 23 | 24 | // Example 25 | _::-webkit-full-page-media, 26 | _:future, 27 | :root .selector { 28 | 29 | } 30 | 31 | /* ***** Firefox Hacks 32 | ** ***** ----------------------------------------------- ***** */ 33 | 34 | // Example 35 | _::-moz-range-track, 36 | body:last-child .selector { 37 | 38 | } 39 | 40 | /* stylelint-enable */ 41 | -------------------------------------------------------------------------------- /archive.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |
6 |
7 |

8 |
9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 |
30 | 31 | 32 | 33 |
34 |
35 | 36 | -------------------------------------------------------------------------------- /assets/src/scss/1-setup/_base.scss: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | ** ***** Setup/Base 3 | ** ***** ----------------------------------------------- ***** */ 4 | 5 | :root { 6 | @apply u-bg-grey-dark-2; 7 | font-size: 62.5%; 8 | } 9 | 10 | *::selection { 11 | @apply u-bg-grey-light-a u-text-white; 12 | } 13 | 14 | html { 15 | -webkit-overflow-scrolling: touch; 16 | } 17 | 18 | body { 19 | @apply u-flex u-flex-col u-h-full u-text-body u-text-grey-light-a; 20 | -moz-osx-font-smoothing: grayscale; 21 | -webkit-font-smoothing: antialiased; 22 | -ms-text-size-adjust: 100%; 23 | } 24 | 25 | a { 26 | @apply u-text-grey-light-c hover:u-text-grey-dark-6 active:u-text-grey-light-c u-no-underline 27 | u-transition-colors u-duration-slow; 28 | } 29 | 30 | button { 31 | @apply u-text-body; 32 | } 33 | 34 | svg { 35 | @apply u-inline-block u-fill-current; 36 | } 37 | 38 | input, 39 | textarea { 40 | @apply u-bg-transparent u-text-body u-rounded-none u-outline-none focus-visible:u-outline-none; 41 | } 42 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |
6 |
7 |

Latest Posts

8 |
9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 |
30 | 31 | 32 | 33 |
34 |
35 | 36 | -------------------------------------------------------------------------------- /search.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |
6 |
7 |

8 |
9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 |
30 | 31 | 32 | 33 |
34 |
35 | 36 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright © 2023 Matt Lee 4 | 5 | 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: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | 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. 10 | -------------------------------------------------------------------------------- /gulpfile.babel.js/tasks/images.js: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | /* ***** Gulp - Images 3 | /* ***** ----------------------------------------------- ***** */ 4 | 5 | import changed from 'gulp-changed' 6 | import config from '../config' 7 | import gulp from 'gulp' 8 | import imagemin from 'gulp-imagemin' 9 | import imageminJpegRecompress from 'imagemin-jpeg-recompress' 10 | import size from 'gulp-size' 11 | 12 | /* 13 | ** -- Check if image is already in dist directory and has changed 14 | ** -- Optimize image for production 15 | */ 16 | const images = () => { 17 | return gulp 18 | .src(config.images.src) 19 | .pipe(changed(config.images.dest)) 20 | .pipe( 21 | imagemin([ 22 | imagemin.gifsicle({ interlaced: true }), 23 | imageminJpegRecompress(), 24 | imagemin.optipng({ optimizationLevel: 5 }), 25 | ]) 26 | ) 27 | .pipe( 28 | size({ 29 | title: 'Optimized File Size:', 30 | showFiles: true, 31 | }) 32 | ) 33 | .pipe(gulp.dest(config.images.dest)) 34 | } 35 | 36 | export default images 37 | -------------------------------------------------------------------------------- /includes/acf.php: -------------------------------------------------------------------------------- 1 | __( 'Global Options', 'bymattlee' ), 12 | 'page_title' => __( 'Global Options', 'bymattlee' ), 13 | 'menu_slug' => 'global-options', 14 | 'position' => '31', 15 | 'capability' => 'edit_posts', 16 | 'icon_url' => 'dashicons-admin-generic', 17 | )); 18 | 19 | // Add Social Options section under the Global Options tab 20 | acf_add_options_sub_page( array( 21 | 'page_title' => __( 'Social Options', 'bymattlee' ), 22 | 'menu_title' => __( 'Social', 'bymattlee' ), 23 | 'parent_slug' => 'global-options', 24 | )); 25 | 26 | // Add Code Options section under the Global Options tab 27 | acf_add_options_sub_page( array( 28 | 'page_title' => __( 'Code Options', 'bymattlee' ), 29 | 'menu_title' => __( 'Code', 'bymattlee' ), 30 | 'parent_slug' => 'global-options', 31 | )); 32 | 33 | } 34 | 35 | ?> -------------------------------------------------------------------------------- /assets/src/scss/6-misc/_print.scss: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | ** ***** Base/Print (from HTML5 Boilerplate) 3 | ** ***** ----------------------------------------------- ***** */ 4 | 5 | @media print { 6 | *, 7 | *::before, 8 | *::after, 9 | *::first-letter, 10 | *::first-line { 11 | background: transparent !important; 12 | box-shadow: none !important; 13 | color: get-color('black') !important; 14 | text-shadow: none !important; 15 | } 16 | 17 | a, 18 | a::visited { 19 | text-decoration: underline; 20 | } 21 | 22 | a[href]::after { 23 | content: ' (' attr(href) ')'; 24 | } 25 | 26 | abbr[title]::after { 27 | content: ' (' attr(title) ')'; 28 | } 29 | 30 | a[href^='#']::after, 31 | a[href^='javascript:']::after { 32 | content: ''; 33 | } 34 | 35 | pre, 36 | blockquote { 37 | border: 1px solid #666; 38 | page-break-inside: avoid; 39 | } 40 | 41 | thead { 42 | display: table-header-group; 43 | } 44 | 45 | tr, 46 | img { 47 | page-break-inside: avoid; 48 | } 49 | 50 | img { 51 | max-width: 100% !important; 52 | } 53 | 54 | p, 55 | h2, 56 | h3 { 57 | orphans: 3; 58 | widows: 3; 59 | } 60 | 61 | h2, 62 | h3 { 63 | page-break-after: avoid; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /assets/src/svgs/icon-instagram.svg: -------------------------------------------------------------------------------- 1 | icon -------------------------------------------------------------------------------- /includes/editor_styles.php: -------------------------------------------------------------------------------- 1 | 'CTA Button', 27 | 'block' => 'a', 28 | 'classes' => 'o-button', 29 | 'wrapper' => true, 30 | ), 31 | ); 32 | 33 | // Insert the array, JSON ENCODED, into 'style_formats' 34 | $init_array[ 'style_formats' ] = json_encode( $style_formats ); 35 | 36 | return $init_array; 37 | 38 | } 39 | // add_filter( 'tiny_mce_before_init', 'bml_custom_editor_styles' ); 40 | 41 | ?> 42 | -------------------------------------------------------------------------------- /.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "stylelint-config-standard", 3 | "plugins": [ 4 | "stylelint-order" 5 | ], 6 | "rules": { 7 | "block-no-empty": , 8 | "selector-type-no-unknown": , 9 | "selector-pseudo-element-no-unknown": , 10 | "rule-empty-line-before": [ 11 | "always-multi-line", { 12 | "except": ["first-nested"], 13 | "ignore": ["after-comment", "inside-block"] 14 | } 15 | ], 16 | "block-closing-brace-empty-line-before": , 17 | "at-rule-empty-line-before": , 18 | "font-family-name-quotes": "always-where-recommended", 19 | "function-url-quotes": "always", 20 | "selector-attribute-quotes": "always", 21 | "color-named": [ 22 | "never", 23 | ignore: ["inside-function"] 24 | ], 25 | "font-weight-notation": "numeric", 26 | "order/properties-alphabetical-order": true, 27 | "declaration-empty-line-before": "never", 28 | "at-rule-no-unknown": null, 29 | "no-descending-specificity": null, 30 | "function-comma-newline-after": null, 31 | "value-keyword-case": null, 32 | "function-no-unknown": null, 33 | "selector-class-pattern": null, 34 | "property-no-vendor-prefix": null, 35 | "no-invalid-position-at-import-rule": null, 36 | "number-max-precision": null, 37 | "selector-no-vendor-prefix": null, 38 | "keyframes-name-pattern": null, 39 | "import-notation": null, 40 | "selector-not-notation": null 41 | } 42 | } -------------------------------------------------------------------------------- /gulpfile.babel.js/tasks/watch.js: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | /* ***** Gulp - Watch 3 | /* ***** ----------------------------------------------- ***** */ 4 | 5 | import browserSync from 'browser-sync' 6 | import browserSyncTask from './browserSync.js' 7 | import config from '../config' 8 | import copy from './copy.js' 9 | import gulp from 'gulp' 10 | import images from './images.js' 11 | import { stylesMain, stylesEditor } from './styles.js' 12 | import svgs from './svgs.js' 13 | import scripts from './scripts.js' 14 | 15 | /* 16 | ** -- Initialize BrowserSync 17 | ** -- Watch *.php files for changes 18 | ** -- Use proxy specified in config (development server must be running) 19 | ** -- Initialize watch for styles, scripts, images, svgs and asset files 20 | ** -- Force browser reload when changes are made to images, svgs and asset files 21 | */ 22 | const watchChanges = () => { 23 | gulp.watch(config.wordpress.src, stylesMain).on('change', browserSync.reload) 24 | gulp.watch(config.styles.mainSrc, stylesMain) 25 | gulp.watch(config.styles.editorSrc, stylesEditor) 26 | gulp.watch(config.scripts.watchSrc, scripts) 27 | gulp.watch(config.images.src, images).on('change', browserSync.reload) 28 | gulp.watch(config.svgs.src, svgs).on('change', browserSync.reload) 29 | gulp.watch(config.copy.src, copy).on('change', browserSync.reload) 30 | } 31 | 32 | const watchInit = gulp.parallel(browserSyncTask, watchChanges) 33 | 34 | export default watchInit 35 | -------------------------------------------------------------------------------- /includes/sidebars.php: -------------------------------------------------------------------------------- 1 | __( 'Default Sidebar', 'bymattlee' ), 12 | 'id' => 'default_sidebar', 13 | 'description' => __( 'Widgets will appear on the default sidebar.', 'bymattlee' ), 14 | 'before_widget' => '
', 15 | 'after_widget' => '
', 16 | 'before_title' => '

', 17 | 'after_title' => '

' 18 | )); 19 | 20 | } 21 | add_action( 'widgets_init', 'bml_register_default_sidebar' ); 22 | 23 | // Widget - ByMattLee Widget 24 | class widget_bymattlee_widget extends WP_Widget { 25 | public function __construct() { 26 | parent::__construct( 27 | 'widget_bymattlee_widget', 28 | __( 'ByMattLee Widget', 'bymattlee' ), 29 | array( 'description' => __( 'Displays the ByMattLee Widget.', 'bymattlee' ), ) 30 | ); 31 | } 32 | 33 | public function widget( $args, $instance ) { 34 | get_template_part( 'partials/sidebar-bymattlee_widget' ); 35 | } 36 | } 37 | 38 | // Register all of the widgets above 39 | function register_widgets() { 40 | register_widget( 'widget_bymattlee_widget' ); 41 | } 42 | //add_action( 'widgets_init', 'register_widgets' ); 43 | 44 | ?> -------------------------------------------------------------------------------- /assets/src/js/components/taxi.js: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | ** ***** Taxi JS 3 | ** ***** ----------------------------------------------- ***** */ 4 | 5 | /* global gtag, gaId */ 6 | 7 | // Set active link on newly loaded page 8 | // Check if user is on the same page as current nav item 9 | // Or if user is in the same section as nav item 10 | const setActiveLink = () => { 11 | const menuItem = document.querySelectorAll('.js-nav__menu-item') 12 | 13 | menuItem.forEach((item) => { 14 | item.parentElement.classList.remove('o-nav__menu-list-item--current') 15 | if (item.href === location.href) { 16 | item.parentElement.classList.add('o-nav__menu-list-item--current') 17 | } else { 18 | const currentItemSlug = item.href.split('/')[3] 19 | const currentLocationSlug = location.href.split('/')[3] 20 | if (currentItemSlug === currentLocationSlug) 21 | item.parentElement.classList.add('o-nav__menu-list-item--current') 22 | } 23 | }) 24 | } 25 | 26 | // Update body classes from new page 27 | const updateBodyClasses = (to) => { 28 | document.body.classList = to.page.body.classList 29 | } 30 | 31 | // Track Google Analytics on a new page load 32 | const trackGA = (to) => { 33 | if (typeof gtag === 'undefined') return 34 | 35 | gtag('config', gaId, { 36 | page_path: location.pathname, 37 | page_title: to.page.title, 38 | page_location: location.href, 39 | }) 40 | } 41 | 42 | export { setActiveLink, updateBodyClasses, trackGA } 43 | -------------------------------------------------------------------------------- /functions.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /partials/news/single.php: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | <?php echo get_post_meta( get_post_thumbnail_id(), '_wp_attachment_image_alt', true ); ?> 5 |
6 | 7 | 8 |
9 | 10 |

11 | 12 |
13 | 14 | / 15 |
16 | 17 | / 18 |
19 | 20 | 21 | / 22 |
23 | 24 |
25 |
26 | 27 | 28 |
29 | 30 |
31 | 32 |
-------------------------------------------------------------------------------- /assets/src/scss/editorStyles.scss: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | ** ***** Editor Styles 3 | ** ***** ----------------------------------------------- ***** */ 4 | 5 | 6 | /* ***** Base Styles 7 | ** ***** ----------------------------------------------- ***** */ 8 | 9 | :root { 10 | font-size: 62.5%; 11 | } 12 | 13 | body { 14 | @apply u-font-fallback u-text-16 u-leading-normal; 15 | -moz-osx-font-smoothing: grayscale; 16 | -webkit-font-smoothing: antialiased; 17 | } 18 | 19 | p { 20 | @apply u-leading-loose u-mx-0 u-my-15; 21 | } 22 | 23 | ul, 24 | ol { 25 | @apply u-leading-loose u-mr-0 u-my-15 u-ml-30 u-p-0; 26 | 27 | li { 28 | @apply u-my-10; 29 | } 30 | } 31 | 32 | a { 33 | @apply u-text-black; 34 | } 35 | 36 | h1, 37 | h2, 38 | h3, 39 | h4, 40 | h5, 41 | h6 { 42 | @apply u-font-fallback u-font-bold u-m-0 u-p-0; 43 | text-rendering: optimizeLegibility; 44 | } 45 | 46 | h1 { 47 | @apply u-text-36; 48 | } 49 | 50 | h2 { 51 | @apply u-text-30; 52 | } 53 | 54 | h3 { 55 | @apply u-text-24; 56 | } 57 | 58 | h4 { 59 | @apply u-text-18; 60 | } 61 | 62 | h5 { 63 | @apply u-text-14; 64 | } 65 | 66 | h6 { 67 | @apply u-text-12; 68 | } 69 | 70 | * + h1, 71 | * + h2, 72 | * + h3, 73 | * + h4, 74 | * + h5, 75 | * + h6 { 76 | @apply u-mt-30; 77 | } 78 | 79 | blockquote { 80 | @apply u-border-0 u-border-l-2 u-border-solid u-border-black u-my-30 u-mx-20 u-pl-30; 81 | } 82 | 83 | hr { 84 | @apply u-border-0 u-border-t-1 u-border-solid u-border-black u-my-40; 85 | } 86 | 87 | 88 | /* ***** Custom Editor Styles 89 | ** ***** ----------------------------------------------- ***** */ 90 | -------------------------------------------------------------------------------- /header.php: -------------------------------------------------------------------------------- 1 | 7 | 8 | > 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | > 43 | 44 | 45 | 46 |
-------------------------------------------------------------------------------- /includes/enqueue.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/src/js/main.js: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | /* ***** Main JS 3 | /* ***** ----------------------------------------------- ***** */ 4 | 5 | import { Core } from '@unseenco/taxi' 6 | import DefaultTransition from './transitions/Default' 7 | import { setActiveLink, updateBodyClasses, trackGA } from './components/taxi.js' 8 | 9 | import { init as globalInit } from './components/global.js' 10 | import { init as richTextInit } from './components/richText.js' 11 | import Scroll2Reveal from './vendors/Scroll2Reveal.js' 12 | 13 | // Init on first load 14 | globalInit() 15 | richTextInit() 16 | const s2r = new Scroll2Reveal() 17 | 18 | // Init Taxi 19 | const taxi = new Core({ 20 | transitions: { 21 | default: DefaultTransition, 22 | }, 23 | links: 24 | 'a:not([target]):not([href^=\\#]):not([href*="wp-admin"]):not([data-taxi-ignore])', 25 | }) 26 | 27 | // Executed at the start of every page load 28 | taxi.on('NAVIGATE_IN', ({ to }) => { 29 | setActiveLink() 30 | updateBodyClasses(to) 31 | s2r.reInit() 32 | richTextInit() 33 | }) 34 | 35 | // Executed when the page has loaded completely 36 | taxi.on('NAVIGATE_END', ({ to }) => { 37 | const isLoggedIn = document.body.classList.contains('logged-in') 38 | if (isLoggedIn) { 39 | // Query admin bar links, and new page's admin bar links 40 | const adminBar = document.querySelector('#wpadminbar') 41 | const newAdminBar = to.page.body.querySelector('#wpadminbar') 42 | 43 | // Replace current admin bar with new admin bar content 44 | if (adminBar && newAdminBar) adminBar.innerHTML = newAdminBar.innerHTML 45 | } 46 | 47 | trackGA(to) 48 | }) 49 | -------------------------------------------------------------------------------- /gulpfile.babel.js/config.js: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | /* ***** Gulp Config 3 | /* ***** ----------------------------------------------- ***** */ 4 | 5 | // Global variables 6 | const src = './assets/src' 7 | const dest = './assets/dist' 8 | 9 | // Contains all main configurations for Gulp 10 | module.exports = { 11 | fileHeader: [ 12 | '/*', 13 | '**', 14 | '**', 15 | '**', 16 | '**', 17 | '**', 18 | '** {{ @bymattlee }}', 19 | '** {{ bymattlee.com }}', 20 | '**', 21 | '**', 22 | '**', 23 | '**', 24 | '**', 25 | '*/\n', 26 | ], 27 | wordpress: { 28 | src: ['./**/*.php', './tailwind.config.js'], 29 | }, 30 | styles: { 31 | mainSrc: [src + '/scss/**/*.scss', '!' + src + '/scss/editorStyles.scss'], 32 | editorSrc: src + '/scss/editorStyles.scss', 33 | dest: dest + '/css', 34 | tailwindConfig: './tailwind.config.js', 35 | purgeContent: ['./**/*.php', src + '/js/components/**/*.js'], 36 | }, 37 | scripts: { 38 | src: src + '/js/main.js', 39 | watchSrc: src + '/js/**/*.js', 40 | dest: dest + '/js', 41 | }, 42 | images: { 43 | src: src + '/images/**/*', 44 | dest: dest + '/images', 45 | }, 46 | svgs: { 47 | src: src + '/svgs/*.svg', 48 | dest: dest + '/svgs', 49 | sprite: 'sprite.svg', 50 | }, 51 | copy: { 52 | src: [ 53 | src + '/**/*.+(eot|svg|ttf|woff|woff2|swf|mp4|mp3)', 54 | '!' + src + '/svgs/*.svg', 55 | '!' + src + '/vendors/**/*', 56 | ], 57 | dest: dest, 58 | }, 59 | clean: { 60 | dest: dest, 61 | }, 62 | browserSync: { 63 | proxy: 'localhost:10008', 64 | }, 65 | } 66 | -------------------------------------------------------------------------------- /partials/news/preview.php: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 | <?php echo get_post_meta( get_post_thumbnail_id(), '_wp_attachment_image_alt', true ); ?> 6 | 7 |
8 | 9 | 10 |
11 | 12 |

13 | 14 |
15 | 16 | / 17 |
18 | 19 | / 20 |
21 | 22 | 23 | / 24 |
25 | 26 |
27 |
28 | 29 | 30 |
31 | 32 |
33 | 34 |
-------------------------------------------------------------------------------- /assets/src/js/utilities/check.js: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | ** ***** Check Utilities JS 3 | ** ***** ----------------------------------------------- ***** */ 4 | 5 | const windowWidth = window.outerWidth 6 | const xSmallWidth = 480 7 | const smallWidth = 768 8 | const mediumWidth = 1024 9 | const largeWidth = 1280 10 | const xLargeWidth = 1440 11 | const xxLargeWidth = 1800 12 | 13 | const isXSmallWidth = windowWidth <= xSmallWidth 14 | const isSmallWidth = windowWidth <= smallWidth 15 | const isMediumWidth = windowWidth <= mediumWidth 16 | const isLargeWidth = windowWidth <= largeWidth 17 | const isXLargeWidth = windowWidth >= xLargeWidth 18 | const isXxLargeWidth = windowWidth >= xxLargeWidth 19 | 20 | const isChrome = 21 | navigator.userAgent.match(/Chrome/i) || navigator.userAgent.match(/CriOS/i) 22 | const isSafari = navigator.userAgent.match(/Safari/i) && !isChrome 23 | const isFirefox = navigator.userAgent.match(/Firefox/i) 24 | const isEdge = navigator.userAgent.match(/Edge/i) 25 | const isDeviceAndroid = navigator.userAgent.match(/Android/i) 26 | const isDeviceBlackBerry = navigator.userAgent.match(/BlackBerry/i) 27 | const isDeviceiOS = navigator.userAgent.match(/iPhone|iPad|iPod/i) 28 | const isDeviceOpera = navigator.userAgent.match(/Opera Mini/i) 29 | const isDeviceWindows = navigator.userAgent.match(/IEMobile/i) 30 | const isDevice = 31 | isDeviceAndroid || 32 | isDeviceBlackBerry || 33 | isDeviceiOS || 34 | isDeviceOpera || 35 | isDeviceWindows 36 | 37 | export { 38 | isXSmallWidth, 39 | isSmallWidth, 40 | isMediumWidth, 41 | isLargeWidth, 42 | isXLargeWidth, 43 | isXxLargeWidth, 44 | isChrome, 45 | isSafari, 46 | isFirefox, 47 | isEdge, 48 | isDeviceAndroid, 49 | isDeviceBlackBerry, 50 | isDeviceiOS, 51 | isDeviceOpera, 52 | isDeviceWindows, 53 | isDevice, 54 | } 55 | -------------------------------------------------------------------------------- /includes/utilities.php: -------------------------------------------------------------------------------- 1 | $name, 13 | 'menu_class' => 'o-nav-menu', 14 | 'walker' => new Site_Nav_Walker() 15 | ) ); 16 | } 17 | 18 | } 19 | 20 | // Display SVG 21 | function bml_the_svg($filename, $viewbox = '0 0 50 50', $classes = '') { 22 | 23 | $markup = ''; 26 | 27 | echo $markup; 28 | } 29 | 30 | // Print the image's srcset for lazyload 31 | function bml_the_image_srcset( $image_id, $echo = true ) { 32 | 33 | if ( !$image_id ) return; 34 | 35 | $image_labels = [ 'size_400', 'size_600', 'size_800', 'size_1000', 'size_1200', 'size_1400', 'size_1600', 'size_1800', 'full' ]; 36 | $image_set = []; 37 | 38 | foreach ( $image_labels as $image_label ) { 39 | 40 | $image = wp_get_attachment_image_src( $image_id, $image_label ); 41 | $image_url = $image[0]; 42 | $image_width = $image[1] <= 300 ? 301 : $image[1]; 43 | 44 | $image_set[] = $image_url . ' ' . ( $image_width - 300 ) . 'w' ; 45 | } 46 | 47 | $image_set = array_unique( $image_set ); 48 | 49 | if ( $echo ) { 50 | echo implode( ', ', $image_set ); 51 | } else { 52 | return implode( ', ', $image_set ); 53 | } 54 | 55 | } 56 | 57 | // Get page URL by page path 58 | function bml_get_page_url_by_path( $slug ) { 59 | return get_permalink( get_page_by_path( $slug ) ); 60 | } 61 | 62 | // Get page ID by page path 63 | function bml_get_page_id_by_path( $path ) { 64 | $page = get_page_by_path( $path ); 65 | return $page->ID; 66 | } 67 | 68 | ?> -------------------------------------------------------------------------------- /partials/global/footer.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bymattlee-wp-starter-theme", 3 | "version": "1.0.0", 4 | "description": "ByMattLee WP Starter Theme", 5 | "homepage": "http://bymattlee.com", 6 | "author": "Matt Lee ", 7 | "engines": { 8 | "node": "16.17.1" 9 | }, 10 | "scripts": { 11 | "start": "yarn dev", 12 | "dev": "NODE_ENV=development gulp", 13 | "stage": "NODE_ENV=staging gulp build", 14 | "prod": "NODE_ENV=production gulp build" 15 | }, 16 | "keywords": [ 17 | "ByMattLee", 18 | "WP", 19 | "Starter", 20 | "Theme" 21 | ], 22 | "license": "MIT", 23 | "repository": { 24 | "type": "git", 25 | "url": "git://github.com/bymattlee/bymattlee-wp-starter-theme.git" 26 | }, 27 | "bugs": { 28 | "url": "https://github.com/bymattlee/bymattlee-wp-starter-theme/issues" 29 | }, 30 | "devDependencies": { 31 | "@babel/core": "^7.22.5", 32 | "@babel/eslint-parser": "^7.22.5", 33 | "@babel/preset-env": "^7.22.5", 34 | "@babel/register": "^7.22.5", 35 | "@tailwindcss/aspect-ratio": "^0.4.2", 36 | "acorn": "^8.9.0", 37 | "babel-eslint": "^10.1.0", 38 | "browser-sync": "^2.29.3", 39 | "del": "^6.0.0", 40 | "gulp": "^4.0.2", 41 | "gulp-add-src": "^1.0.0", 42 | "gulp-autoprefixer": "^8.0.0", 43 | "gulp-better-rollup": "^4.0.1", 44 | "gulp-changed": "^4.0.3", 45 | "gulp-clean-css": "^4.3.0", 46 | "gulp-concat": "^2.6.1", 47 | "gulp-eslint": "^6.0.0", 48 | "gulp-header": "^2.0.9", 49 | "gulp-if": "^3.0.0", 50 | "gulp-imagemin": "^7.1.0", 51 | "gulp-plumber": "^1.2.1", 52 | "gulp-postcss": "^9.0.1", 53 | "gulp-rename": "^2.0.0", 54 | "gulp-sass": "^5.1.0", 55 | "gulp-size": "^4.0.1", 56 | "gulp-sourcemaps": "^3.0.0", 57 | "gulp-svg-sprite": "^2.0.3", 58 | "gulp-terser": "^2.1.0", 59 | "imagemin-jpeg-recompress": "^7.1.0", 60 | "postcss-reporter": "^7.0.5", 61 | "postcss-scss": "^4.0.6", 62 | "rollup": "^3.25.1", 63 | "rollup-plugin-babel": "^4.4.0", 64 | "rollup-plugin-commonjs": "^10.1.0", 65 | "rollup-plugin-json": "^4.0.0", 66 | "rollup-plugin-node-resolve": "^5.2.0", 67 | "sass": "^1.63.6", 68 | "stylelint": "^15.8.0", 69 | "stylelint-config-standard": "^33.0.0", 70 | "stylelint-order": "^6.0.3", 71 | "tailwindcss": "^3.3.2" 72 | }, 73 | "dependencies": { 74 | "@unseenco/taxi": "^1.3.0", 75 | "alpinejs": "^3.12.2", 76 | "gsap": "^3.12.1", 77 | "lazysizes": "^5.3.2", 78 | "throttle-debounce": "^5.0.0" 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /gulpfile.babel.js/tasks/scripts.js: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | /* ***** Gulp - Scripts 3 | /* ***** ----------------------------------------------- ***** */ 4 | 5 | import addSrc from 'gulp-add-src' 6 | import babel from 'rollup-plugin-babel' 7 | import browserSync from 'browser-sync' 8 | import concat from 'gulp-concat' 9 | import commonjs from 'rollup-plugin-commonjs' 10 | import config from '../config' 11 | import eslint from 'gulp-eslint' 12 | import gif from 'gulp-if' 13 | import gulp from 'gulp' 14 | import header from 'gulp-header' 15 | import json from 'rollup-plugin-json' 16 | import nodeResolve from 'rollup-plugin-node-resolve' 17 | import plumber from 'gulp-plumber' 18 | import rename from 'gulp-rename' 19 | import rollup from 'gulp-better-rollup' 20 | import size from 'gulp-size' 21 | import sourcemaps from 'gulp-sourcemaps' 22 | import terser from 'gulp-terser' 23 | 24 | // Environment variables 25 | const isDevelopment = process.env.NODE_ENV === 'development' 26 | 27 | // Lint files with ESLint 28 | const scriptsLint = () => { 29 | return gulp.src(config.scripts.watchSrc).pipe(eslint()).pipe(eslint.format()) 30 | } 31 | 32 | /* 33 | ** -- Create sourcemaps if in development mode (use gulp --production or gulp --staging to disable soucemaps) 34 | ** -- Bundle all files 35 | ** -- Minify all files 36 | ** -- Add ByMattLee header to bundled file 37 | ** -- Print bundled file size 38 | ** -- Reload browser 39 | */ 40 | const scriptsMain = () => { 41 | return gulp 42 | .src(config.scripts.src) 43 | .pipe(plumber()) 44 | .pipe(gif(isDevelopment, sourcemaps.init())) 45 | .pipe( 46 | rollup( 47 | { 48 | plugins: [ 49 | babel({ 50 | exclude: 'node_modules/**', 51 | }), 52 | nodeResolve(), 53 | commonjs(), 54 | json(), 55 | ], 56 | }, 57 | 'umd' 58 | ) 59 | ) 60 | .pipe( 61 | terser({ 62 | format: { 63 | comments: false, 64 | }, 65 | }) 66 | ) 67 | .pipe(concat('main.js')) 68 | .pipe( 69 | rename({ 70 | suffix: '.min', 71 | }) 72 | ) 73 | .pipe(header(config.fileHeader.join('\n'))) 74 | .pipe( 75 | size({ 76 | title: 'Compressed File Size:', 77 | showFiles: true, 78 | }) 79 | ) 80 | .pipe(gif(isDevelopment, sourcemaps.write('./'))) 81 | .pipe(gulp.dest(config.scripts.dest)) 82 | .pipe(browserSync.stream()) 83 | } 84 | 85 | const scripts = gulp.series(scriptsLint, scriptsMain) 86 | 87 | export default scripts 88 | -------------------------------------------------------------------------------- /assets/src/scss/2-utilities/_type.scss: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | ** ***** Utilities/Type 3 | ** ***** ----------------------------------------------- ***** */ 4 | 5 | @layer utilities { 6 | h1, 7 | h2, 8 | h3, 9 | h4, 10 | h5, 11 | h6, 12 | .u-h1, 13 | .u-h2, 14 | .u-h3, 15 | .u-h4, 16 | .u-h5, 17 | .u-h6 { 18 | @apply u-font-heading u-font-bold; 19 | text-rendering: optimizeLegibility; 20 | } 21 | 22 | .u-h1 { 23 | @apply u-text-36 sm:u-text-48; 24 | } 25 | 26 | .u-h2 { 27 | @apply u-text-30 sm:u-text-36; 28 | } 29 | 30 | .u-h3 { 31 | @apply u-text-24 sm:u-text-28; 32 | } 33 | 34 | .u-h4 { 35 | @apply u-text-18 sm:u-text-24; 36 | } 37 | 38 | .u-h5 { 39 | @apply u-text-14 sm:u-text-18; 40 | } 41 | 42 | .u-h6 { 43 | @apply u-text-12 sm:u-text-14; 44 | } 45 | 46 | .u-text-body { 47 | @apply u-font-body u-leading-normal u-text-14 sm:u-text-16; 48 | } 49 | 50 | .u-rich-text { 51 | > * { 52 | &:first-child { 53 | @apply u-mt-0; 54 | } 55 | 56 | &:last-child { 57 | @apply u-mb-0; 58 | } 59 | } 60 | 61 | h1, 62 | h2, 63 | h3, 64 | h4, 65 | h5, 66 | h6 { 67 | @apply u-mb-10; 68 | } 69 | 70 | h1 { 71 | @apply u-text-36 sm:u-text-48; 72 | } 73 | 74 | h2 { 75 | @apply u-text-30 sm:u-text-36; 76 | } 77 | 78 | h3 { 79 | @apply u-text-24 sm:u-text-28; 80 | } 81 | 82 | h4 { 83 | @apply u-text-18 sm:u-text-24; 84 | } 85 | 86 | * + h1, 87 | * + h2, 88 | * + h3, 89 | * + h4, 90 | * + h5, 91 | * + h6 { 92 | @apply u-mt-40 sm:u-mt-50; 93 | } 94 | 95 | a { 96 | @include text-underline; 97 | } 98 | 99 | p { 100 | @apply u-leading-loose u-my-20 sm:u-my-30; 101 | } 102 | 103 | ul, 104 | ol { 105 | @apply u-leading-loose u-my-20 u-mr-0 u-ml-30 sm:u-my-30 sm:u-ml-35; 106 | 107 | ul, 108 | ol { 109 | @apply u-mt-5 u-mr-0 u-mb-5 u-ml-35; 110 | } 111 | } 112 | 113 | ul { 114 | @apply u-list-disc; 115 | 116 | &.wp-block-gallery { 117 | @apply u-ml-0; 118 | } 119 | } 120 | 121 | ol { 122 | @apply u-list-decimal; 123 | } 124 | 125 | blockquote { 126 | @apply u-border-l-2 u-my-30 u-mx-20 u-pl-30; 127 | } 128 | 129 | .o-button { 130 | @apply u-no-underline; 131 | } 132 | 133 | .emoji { 134 | @apply u-inline-block u-w-20; 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /assets/src/scss/1-setup/_type.scss: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | ** ***** Setup/Type 3 | ** ***** ----------------------------------------------- ***** */ 4 | 5 | /* ***** Mixins 6 | ** ***** ----------------------------------------------- ***** */ 7 | 8 | // Font face 9 | @mixin font-face($name, $file, $weight: 400, $style: normal) { 10 | @font-face { 11 | font-display: swap; 12 | font-family: $name; 13 | font-style: $style; 14 | font-weight: $weight; 15 | src: 16 | url('../fonts/#{$file}.woff2') format('woff2'), 17 | url('../fonts/#{$file}.woff') format('woff'); 18 | } 19 | } 20 | 21 | // Placeholder text 22 | @mixin placeholder($color) { 23 | &::-webkit-input-placeholder { 24 | @apply opacity-100 u-transition-opacity u-duration-slow; 25 | color: $color; 26 | } 27 | 28 | &::-moz-placeholder { 29 | @apply opacity-100 u-transition-opacity u-duration-slow; 30 | color: $color; 31 | } 32 | 33 | &:-ms-input-placeholder { 34 | @apply opacity-100 u-transition-opacity u-duration-slow; 35 | color: $color; 36 | } 37 | 38 | &:-moz-placeholder { 39 | @apply opacity-100 u-transition-opacity u-duration-slow; 40 | color: $color; 41 | } 42 | 43 | &:focus { 44 | &::-webkit-input-placeholder { 45 | @apply opacity-50; 46 | } 47 | 48 | &::-moz-placeholder { 49 | @apply opacity-50; 50 | } 51 | 52 | &:-ms-input-placeholder { 53 | @apply opacity-50; 54 | } 55 | 56 | &:-moz-placeholder { 57 | @apply opacity-50; 58 | } 59 | } 60 | } 61 | 62 | // Input autofill 63 | @mixin autofill($border-color, $font-color, $background-color) { 64 | &:-webkit-autofill, 65 | &:-webkit-autofill:hover, 66 | &:-webkit-autofill:focus { 67 | border: 1px solid $border-color; 68 | -webkit-box-shadow: 0 0 0 1000px $background-color inset; 69 | -webkit-text-fill-color: $font-color; 70 | transition: background-color 5000s ease-in-out 0s; 71 | } 72 | } 73 | 74 | // Text Underline 75 | @mixin text-underline() { 76 | background: linear-gradient(currentColor, currentColor); 77 | background-position: 0 100%; 78 | background-repeat: no-repeat; 79 | background-size: 100% 0.1rem; 80 | } 81 | 82 | 83 | /* ***** Includes 84 | ** ***** ----------------------------------------------- ***** */ 85 | 86 | @layer base { 87 | // Montserrat 88 | @include font-face('Montserrat', 'montserrat-light-webfont', 200); 89 | @include font-face('Montserrat', 'montserrat-regular-webfont'); 90 | @include font-face('Montserrat', 'montserrat-bold-webfont', 700); 91 | @include font-face('Montserrat', 'montserrat-black-webfont', 800); 92 | 93 | // Open Sans 94 | @import url('https://fonts.googleapis.com/css?family=Open+Sans:400,600,700&display=swap'); 95 | } 96 | -------------------------------------------------------------------------------- /includes/require_plugins.php: -------------------------------------------------------------------------------- 1 | 'Advanced Custom Fields PRO', 17 | 'slug' => 'advanced-custom-fields-pro', 18 | 'source' => 'https://github.com/wp-premium/advanced-custom-fields-pro/archive/master.zip', 19 | 'required' => true, 20 | ), 21 | 22 | // Require Contact Form 7 plugin 23 | array( 24 | 'name' => 'Contact Form 7', 25 | 'slug' => 'contact-form-7', 26 | 'required' => true, 27 | ), 28 | 29 | // Require Favicon by RealFaviconGenerator plugin 30 | array( 31 | 'name' => 'Favicon by RealFaviconGenerator', 32 | 'slug' => 'favicon-by-realfavicongenerator', 33 | 'required' => true, 34 | ), 35 | 36 | // Require Yoast SEO plugin 37 | array( 38 | 'name' => 'Yoast SEO', 39 | 'slug' => 'wordpress-seo', 40 | 'required' => true, 41 | ), 42 | 43 | // Require Classic Editor plugin 44 | array( 45 | 'name' => 'Classic Editor', 46 | 'slug' => 'classic-editor', 47 | 'required' => true, 48 | ), 49 | 50 | // Require WP Migrate DB plugin 51 | array( 52 | 'name' => 'WP Migrate DB', 53 | 'slug' => 'wp-migrate-db', 54 | 'required' => true, 55 | ), 56 | 57 | ); 58 | 59 | $config = array( 60 | 'id' => 'bymattlee', // Unique ID for hashing notices for multiple instances of TGMPA. 61 | 'default_path' => '', // Default absolute path to bundled plugins. 62 | 'menu' => 'tgmpa-install-plugins', // Menu slug. 63 | 'parent_slug' => 'themes.php', // Parent menu slug. 64 | 'capability' => 'edit_theme_options', // Capability needed to view plugin install page, should be a capability associated with the parent menu used. 65 | 'has_notices' => true, // Show admin notices or not. 66 | 'dismissable' => true, // If false, a user cannot dismiss the nag message. 67 | 'dismiss_msg' => '', // If 'dismissable' is false, this message will be output at top of nag. 68 | 'is_automatic' => false, // Automatically activate plugins after installation or not. 69 | 'message' => '', // Message to output right before the plugins table. 70 | ); 71 | 72 | tgmpa( $plugins, $config ); 73 | } 74 | 75 | add_action( 'tgmpa_register', 'bml_register_required_plugins' ); 76 | 77 | ?> 78 | -------------------------------------------------------------------------------- /assets/src/scss/main.scss: -------------------------------------------------------------------------------- 1 | /* ***** ----------------------------------------------- ***** ** 2 | /* ***** Main 3 | /* ***** ----------------------------------------------- ***** */ 4 | 5 | /* 6 | ** All CSS classes use namespaces to further improve organization. 7 | ** 8 | ** -- (u-) Utility classes have a very specific role and usually contain one declaration. 9 | ** - Example: A class that hides the element on mobile, a class that bolds the text, etc. 10 | ** 11 | ** -- (l-) Layout classes provides structure that hold the site elements together. 12 | ** - Example: Containers, grids, etc. 13 | ** 14 | ** -- (o-) Objects are the smallest of all elements. Should be reused as much as possible. 15 | ** They are either used multiple times on a page and/or in multiple contexts on a site. 16 | ** - Example: social icons, news posts, buttons, section titles, etc. 17 | ** 18 | ** -- (c-) Components are also known as modules that are made up of smaller, related elements. 19 | ** They are used at most once per page in one type of context. 20 | ** - Example: A header is a component and is made up of smaller elements such as the 21 | ** site's logo, navigation, social icons, etc. 22 | ** 23 | ** -- (js-) JavaScript classes do not have any styling attached to them. They are used to 24 | ** signify that there is some behavior attached to it. 25 | ** - Example: A button that toggles the menu, a social icon that opens a popup window, etc. 26 | ** 27 | ** -- (t-) Theme classes modify the color palette of the site. Usually used on the body element. 28 | ** - Example: A dark theme that utilizes a lighter type color on a dark background. 29 | ** 30 | ** -- (s-) State classes signify the current state of an element. 31 | ** - Example: A mobile menu that is open when the menu button is clicked. 32 | ** 33 | ** -- (p-) Page classes identifies the current page. 34 | ** - Example: The home page will use the class '.p-home'. 35 | */ 36 | 37 | /* ***** Tailwind 38 | ** ***** ----------------------------------------------- ***** */ 39 | 40 | @tailwind base; 41 | @tailwind components; 42 | @tailwind utilities; 43 | 44 | /* ***** Setup 45 | ** ***** ----------------------------------------------- ***** */ 46 | 47 | @import '1-setup/type'; 48 | @import '1-setup/base'; 49 | 50 | /* ***** Utilities 51 | ** ***** ----------------------------------------------- ***** */ 52 | 53 | @import '2-utilities/layout'; 54 | @import '2-utilities/type'; 55 | 56 | /* ***** Vendors 57 | ** ***** ----------------------------------------------- ***** */ 58 | 59 | @import '3-vendors/lazysizes'; 60 | @import '3-vendors/s2r'; 61 | @import '3-vendors/wordpress'; 62 | 63 | /* ***** Objects 64 | ** ***** ----------------------------------------------- ***** */ 65 | 66 | @import '4-objects/button'; 67 | @import '4-objects/nav'; 68 | 69 | /* ***** Components 70 | ** ***** ----------------------------------------------- ***** */ 71 | 72 | // @import '5-components/component'; 73 | 74 | /* ***** Misc 75 | ** ***** ----------------------------------------------- ***** */ 76 | 77 | @import '6-misc/hacks'; 78 | @import '6-misc/print'; 79 | -------------------------------------------------------------------------------- /includes/admin_display.php: -------------------------------------------------------------------------------- 1 | li.comment-count, li.comment-mod-count, #latest-comments, #wp-admin-bar-comments { display:none; }'; 53 | } 54 | add_action( 'admin_head', 'bml_remove_dashboard_comment_activity' ); 55 | 56 | // Remove comments from admin bar 57 | function bml_remove_comments_from_admin_bar() { 58 | global $wp_admin_bar; 59 | $wp_admin_bar->remove_menu('comments'); 60 | } 61 | add_action( 'wp_before_admin_bar_render', 'bml_remove_comments_from_admin_bar' ); 62 | 63 | // Rename Posts label to News 64 | function bml_change_post_object() { 65 | global $wp_post_types; 66 | $labels = &$wp_post_types[ 'post' ]->labels; 67 | $labels->name = 'News'; 68 | $labels->singular_name = 'News'; 69 | $labels->add_new = 'Add New'; 70 | $labels->add_new_item = 'Add New News'; 71 | $labels->edit_item = 'Edit News'; 72 | $labels->new_item = 'News'; 73 | $labels->view_item = 'View News'; 74 | $labels->search_items = 'Search News'; 75 | $labels->not_found = 'No News found'; 76 | $labels->not_found_in_trash = 'No News found in Trash'; 77 | $labels->all_items = 'All News'; 78 | $labels->menu_name = 'News'; 79 | $labels->name_admin_bar = 'News'; 80 | } 81 | add_action( 'init', 'bml_change_post_object' ); 82 | 83 | ?> -------------------------------------------------------------------------------- /includes/markup_cleanup.php: -------------------------------------------------------------------------------- 1 | surrounding the dynamic navigation to cleanup markup 42 | function bml_my_wp_nav_menu_args( $args = '' ) { 43 | $args[ 'container' ] = false; 44 | return $args; 45 | } 46 | add_filter( 'wp_nav_menu_args', 'bml_my_wp_nav_menu_args' ); 47 | 48 | // Remove invalid rel attribute values in the category list 49 | function bml_remove_category_rel_from_category_list( $thelist ) { 50 | return str_replace( 'rel="category tag"', 'rel="tag"', $thelist ); 51 | } 52 | add_filter( 'the_category', 'bml_remove_category_rel_from_category_list' ); 53 | 54 | // Remove thumbnail width and height dimensions that prevent fluid images 55 | function bml_remove_thumbnail_dimensions( $html ) { 56 | $html = preg_replace( '/(width|height)=\"\d*\"\s/', "", $html ); 57 | return $html; 58 | } 59 | add_filter( 'post_thumbnail_html', 'bml_remove_thumbnail_dimensions', 10 ); 60 | add_filter( 'image_send_to_editor', 'bml_remove_thumbnail_dimensions', 10 ); 61 | 62 | // Remove wp_head() injected Recent Comment styles 63 | function bml_remove_recent_comments_style(){ 64 | global $wp_widget_factory; 65 | 66 | remove_action( 'wp_head', array( 67 | $wp_widget_factory->widgets[ 'WP_Widget_Recent_Comments' ], 68 | 'recent_comments_style' 69 | )); 70 | } 71 | add_action( 'widgets_init', 'bml_remove_recent_comments_style' ); 72 | 73 | // Removes the [...] after an excerpt 74 | function bml_custom_excerpt_more( $more ) { 75 | global $post; 76 | return '...'; 77 | } 78 | add_filter( 'excerpt_more', 'bml_custom_excerpt_more' ); 79 | 80 | ?> -------------------------------------------------------------------------------- /includes/menus.php: -------------------------------------------------------------------------------- 1 | __( 'Primary Menu', 'bymattlee' ), 11 | 'footer_menu' => __( 'Footer Menu', 'bymattlee' ), 12 | ) 13 | ); 14 | 15 | // Custom walker for slideout menu that removes all unnecessary classes 16 | class Site_Nav_Walker extends Walker_Nav_Menu { 17 | 18 | // Rename sub menu class name 19 | function start_lvl( &$output, $depth = 0, $args = array() ) { 20 | $indent = str_repeat("\t", $depth); 21 | $output .= "\n$indent