diff --git a/.travis.yml b/.travis.yml index 604be66..5657654 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,7 +36,7 @@ env: - WP_VERSION=trunk WP_MULTISITE=1 install: - - npm install + - npm install github:xwp/wp-dev-lib - export DEV_LIB_PATH=node_modules/wp-dev-lib - source $DEV_LIB_PATH/travis.install.sh diff --git a/404.php b/404.php new file mode 100644 index 0000000..f52cbf3 --- /dev/null +++ b/404.php @@ -0,0 +1,60 @@ + + +
+ +
+ + +
+

+ + + +
+

+
    + 'count', + 'order' => 'DESC', + 'show_count' => 1, + 'title_li' => '', + 'number' => 10, + ) + ); + ?> +
+
+ + ' . sprintf( esc_html__( 'Try looking in the monthly archives. %1$s', 'travel' ), convert_smilies( ':)' ) ) . '

'; + the_widget( 'WP_Widget_Archives', 'dropdown=1', "after_title=$archive_content" ); + + the_widget( 'WP_Widget_Tag_Cloud' ); + ?> + +
+
+ +
+ + Themes and click the Add New button. @@ -24,4 +39,4 @@ Custom theme based on the [AMP Start Travel Theme](https://ampstart-iframes.fire ## Credits ## * Based on the [AMP Start Travel Theme](https://ampstart-iframes.firebaseapp.com/templates/travel/travel.amp) - +* Built with [PSTT theme](https://github.com/mor10/pstt) diff --git a/css/comments.css b/css/comments.css new file mode 100644 index 0000000..0ebfa77 --- /dev/null +++ b/css/comments.css @@ -0,0 +1,10 @@ +/*-------------------------------------------------------------- +# Comments +--------------------------------------------------------------*/ +.comment-content a { + word-wrap: break-word; +} + +.bypostauthor { + display: block; +} diff --git a/css/content.css b/css/content.css new file mode 100644 index 0000000..8494a72 --- /dev/null +++ b/css/content.css @@ -0,0 +1,440 @@ +/*-------------------------------------------------------------- +>>> TABLE OF CONTENTS: +---------------------------------------------------------------- +# Post and page content + # Alignments + # Blocks + # Media + # Captions + # Galleries + # Comments +--------------------------------------------------------------*/ +/*-------------------------------------------------------------- +# Post and page content +--------------------------------------------------------------*/ +/* Custom rule for sticky posts: +.sticky { + +} +*/ + +.hentry { + margin-bottom: 1rem; +} + +.entry-meta, +.entry-footer { + font-family: 'Roboto Condensed', sans-serif; + font-size: 80%; +} + +/* Hides the update date and time. */ +.updated:not(.published) { + display: none; +} + +.post-thumbnail img { + margin: 0 auto; +} + +.page-content, +.entry-content, +.entry-summary { + margin: 1.5em 0 0; +} + +.page-content > *, +.entry-content > *, +.entry-summary > * { + margin-right: auto; + margin-left: auto; + padding-right: 24px; + padding-right: 1.5rem; + padding-left: 24px; + padding-left: 1.5rem; + max-width: 720px; /* Fallback for older browsers. */ + max-width: 45rem; +} + +.page-title, +.entry-header, +.entry-footer, +.site-info, +.post-navigation, +.page-navigation, +.comments-area { + margin: 1.5em auto; + padding-right: 24px; + padding-right: 1.5rem; + padding-left: 24px; + padding-left: 1.5rem; + max-width: 720px; /* Fallback for older browsers. */ + max-width: 45rem; +} + +@media screen and (min-width: 48em) { + .page-content > *, + .entry-content > *, + .entry-summary > *, + .page-title, + .entry-header, + .entry-footer, + .site-info, + .post-navigation, + .page-navigation, + .comments-area { + padding-left: 0px; + padding-right: 0px; + } +} + +.page-links { + clear: both; + margin: 0 0 1.5em; +} + +.entry-footer span { + margin-right: 1em; +} + +.entry-footer { + clear: both; + padding: 1.5em 1.5rem 3em; + border-bottom: 1px solid #111; +} + +@media screen and (min-width: 48em) { + .entry-footer { + padding-right: 0; + padding-left: 0; + } +} +/*-------------------------------------------------------------- +## Alignments +--------------------------------------------------------------*/ +.alignleft { + float: left; + margin-right: 1.5rem; +} + +.alignright { + float: right; + margin-left: 1.5rem; +} + +.aligncenter { + clear: both; + display: block; + margin-left: auto; + margin-right: auto; +} + +@media screen and (min-width: 48em) { + + .wp-caption.alignright, + .wp-block-image.alignright { + margin-right: calc(50% - 360px)px; + margin-right: calc(50% - 22.5rem)rem; + } + + .wp-caption.alignleft, + .wp-block-image.alignleft { + margin-right: calc(50% - 360px)px; + margin-left: calc(50% - 22.5rem)rem; + } + +} + +/*-------------------------------------------------------------- +## Blocks +--------------------------------------------------------------*/ +/* + * Available block selectors: + + * .wp-block-image + * .wp-block-gallery + * .wp-block-video + * .wp-block-quote + * .wp-block-text-columns + * .wp-block-cover-text + * .wp-block-button + * .wp-block-gallery + * .wp-block-table + * .wp-block-embed + * .wp-block-audio + * .wp-block-pullquote + * .wp-block-preformatted + * .wp-block-code + * .wp-block-verse + + */ + +.entry-content ul, +.entry-content ol { + padding-right: 3em; + padding-left: 3em; +} + +@media screen and (min-width: 48em) { + .entry-content ul, + .entry-content ol { + padding-right: 1.5em; + padding-left: 1.5em; + } +} + +.wp-block-video video { + max-width: 45rem; +} + +.alignwide { + max-width: calc(50% + 22.5rem); +} + +.alignfull { + max-width: 100%; +} + +.wp-block-image img { + display: block; + width: 100%; +} + +.wp-block-cover-text p { + padding: 1.5em 1.5em; +} + +@media screen and (min-width: 48em) { + .wp-block-cover-text p { + padding: 1.5em 0; + } + + .entry-content pre { + padding: 1.5em; + } +} + +ul.wp-block-latest-posts.alignwide, +ul.wp-block-latest-posts.alignfull, +ul.wp-block-latest-posts.is-grid.alignwide, +ul.wp-block-latest-posts.is-grid.alignwide { + padding: 0 1.5em; +} + +.wp-block-table { + display: block; + overflow-x: auto; +} + +.wp-block-table table { + border-collapse: collapse; + width: 100% +} + +.wp-block-table td, .wp-block-table th { + padding: .5em; +} + +.entry-content li { + list-style-position: outside; +} + +/* Responsive video embed magic stuff: */ +.wp-block-embed.type-video > .wp-block-embed__wrapper { + position: relative; + width: 100%; + height: 0; + padding-top: 56.25%; +} + +.wp-block-embed.type-video > .wp-block-embed__wrapper > iframe { + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; + bottom: 0; + right: 0; +} + + + +/*-------------------------------------------------------------- +## Media +--------------------------------------------------------------*/ +.page-content .wp-smiley, +.entry-content .wp-smiley, +.comment-content .wp-smiley { + border: none; + margin-bottom: 0; + margin-top: 0; + padding: 0; +} + +/* Make sure embeds and iframes fit their containers. */ +embed, +iframe, +object { + max-width: 100%; +} + +/* Make sure logo link wraps around logo image. */ +.custom-logo-link { + display: inline-block; +} + +/*-------------------------------------------------------------- +### Captions +--------------------------------------------------------------*/ +.wp-caption { + margin-bottom: 1.5em; + max-width: 100%; +} + +.wp-caption img[class*="wp-image-"] { + display: block; + margin-left: auto; + margin-right: auto; +} + +.wp-caption .wp-caption-text { + margin: 0.8075em 0; +} + +.wp-caption-text { + text-align: center; +} + +/*-------------------------------------------------------------- +### Gallery Block - overrides core styles +--------------------------------------------------------------*/ + +.wp-block-gallery:not(.components-placeholder) { + margin: 1.5em auto; +} + +/* Override standard ul indentation. */ +.entry-content .wp-block-gallery { + padding-right: 1.5em; + padding-left: 1.5em; +} + +@media screen and (min-width: 48em) { + .entry-content .wp-block-gallery { + padding-right: 0; + padding-left: 0; + } +} + +.wp-block-gallery { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + grid-gap: .5em; +} + +.wp-block-gallery.columns-2 .blocks-gallery-item, +.wp-block-gallery.columns-3 .blocks-gallery-item, +.wp-block-gallery.columns-4 .blocks-gallery-item, +.wp-block-gallery.columns-5 .blocks-gallery-item, +.wp-block-gallery.columns-6 .blocks-gallery-item, +.wp-block-gallery.columns-7 .blocks-gallery-item, +.wp-block-gallery.columns-8 .blocks-gallery-item, +.wp-block-gallery.columns-9 .blocks-gallery-item { + width: 100%; + margin: 0; +} + +@media screen and (min-width: 40em) { + .wp-block-gallery.columns-2 { + grid-template-columns: repeat(2, 1fr); + } + + .wp-block-gallery.columns-3 { + grid-template-columns: repeat(3, 1fr); + } + + .wp-block-gallery.columns-4 { + grid-template-columns: repeat(4, 1fr); + } + + .wp-block-gallery.columns-5 { + grid-template-columns: repeat(5, 1fr); + } + + .wp-block-gallery.columns-6 { + grid-template-columns: repeat(6, 1fr); + } + + .wp-block-gallery.columns-7 { + grid-template-columns: repeat(7, 1fr); + } + + .wp-block-gallery.columns-8 { + grid-template-columns: repeat(8, 1fr); + } + + .wp-block-gallery.columns-9 { + grid-template-columns: repeat(9, 1fr); + } +} +/*-------------------------------------------------------------- +### Galleries (Legacy) +--------------------------------------------------------------*/ +.gallery { + margin-bottom: 1.5em; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); + grid-gap: .5em; +} + +@media screen and (min-width: 40em) { + .gallery-columns-2 { + grid-template-columns: repeat(2, 1fr); + } + + .gallery-columns-3 { + grid-template-columns: repeat(3, 1fr); + } + + .gallery-columns-4 { + grid-template-columns: repeat(4, 1fr); + } + + .gallery-columns-5 { + grid-template-columns: repeat(5, 1fr); + } + + .gallery-columns-6 { + grid-template-columns: repeat(6, 1fr); + } + + .gallery-columns-7 { + grid-template-columns: repeat(7, 1fr); + } + + .gallery-columns-8 { + grid-template-columns: repeat(8, 1fr); + } + + .gallery-columns-9 { + grid-template-columns: repeat(9, 1fr); + } +} + +.gallery-item { + padding: .5em; + border: 1px solid rgb(222, 222, 222); +} + +.gallery-icon { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; +} + +.gallery-caption { + font-size: 80%; +} diff --git a/css/front-page.css b/css/front-page.css new file mode 100644 index 0000000..5cdec84 --- /dev/null +++ b/css/front-page.css @@ -0,0 +1,46 @@ +/** + * Custom styles for the front-page.php template. + */ + +@media screen and (min-width: 60em) { + .site { + margin: 0 1em; + display: grid; + grid-template-columns: 1fr; + } + + .site-main { + margin-top: 2rem; + display: grid; + grid-template-columns: repeat(4, 1fr); + grid-gap: 2rem; + } + + .post { + grid-column: 2/4; + } + + .post:nth-child(-n+4) { + grid-column: span 2; + margin: 0 4rem; + } + + .post:nth-child(-n+4) .entry-footer { + border-bottom: none; + padding-bottom: 1.5em; + } + + .post:first-of-type { + grid-column: 1/5; + margin: 0; + padding: 1rem 0; + border: 10px solid hsl(240, 100%, 90%); + } + + .primary-sidebar { + grid-column: 4; + grid-row: 3/8; + min-width: 0; + } + +} diff --git a/css/sidebar.css b/css/sidebar.css new file mode 100644 index 0000000..38066a0 --- /dev/null +++ b/css/sidebar.css @@ -0,0 +1,13 @@ +/*-------------------------------------------------------------- +# Sidebar +--------------------------------------------------------------*/ + +.primary-sidebar { + padding: 1.5rem; +} + +@media screen and (min-width: 60em) { + .primary-sidebar { + padding: 0; + } +} diff --git a/css/widgets.css b/css/widgets.css new file mode 100644 index 0000000..0d5fd26 --- /dev/null +++ b/css/widgets.css @@ -0,0 +1,176 @@ +/*-------------------------------------------------------------- +# Widgets +--------------------------------------------------------------*/ +.widget { + margin: 0 0 1.5em; + /* Make sure select elements fit in widgets. */ +} + +.widget_archive ul, +.widget_categories ul, +.widget_meta ul, +.widget_nav_menu ul, +.widget_recent_comments ul, +.widget_pages ul, +.widget_recent_entries ul, +.widget_rss ul { + margin: 0; + padding: 0; + list-style-type: none; +} + +.widget select { + max-width: 100%; + text-overflow: ellipsis; +} + +/* Archive and Categories widgets */ +.widget_archive li { + color: #7D7D7D; +} + +.widget_categories .children { + padding-top: 0; +} + +/* Search widget. */ +.widget_search .search-submit { + display: none; +} + +/* Pages and Menu widgets */ +.widget_pages .children, +.widget_nav_menu .sub-menu { + padding-top: 0; + padding-bottom: .5em; +} + +.widget_pages a, +.widget_nav_menu a { + display: block; + padding: 1em 0; + text-decoration: none; + border-bottom: 1px dashed gray; +} + +.widget_pages a:hover, .widget_pages a:focus, +.widget_nav_menu a:hover, +.widget_nav_menu a:focus { + text-decoration: none; + border-bottom: 1px dashed gray; +} + +.widget_pages li, +.widget_nav_menu li { + padding: 0; +} + +.widget_pages li ul, +.widget_nav_menu li ul { + margin-left: 1em; +} + +/* Meta widget */ +.widget_meta li { + padding: 0; +} + +/* Recent comments */ +.widget_recent_comments li { + line-height: 1.3em; + padding-bottom: .5em; +} + +.widget_recent_comments a:hover, +.widget_recent_comments a:focus { + padding-left: 0; +} + +/* RSS widget */ +.widget_rss li { + margin-bottom: 1em; +} + +.widget li a.rsswidget { + padding-right: .5em; + font-size: 1em; + line-height: 1.4em; +} + +.rss-date, +.widget_rss cite { + color: #333; + font-size: .8em; +} + +.rssSummary { + padding: .5em 0; + font-size: .8em; + line-height: 1.4em; +} + +/* Search widget */ +.widget_search input[type="search"] { + -webkit-box-sizing: border-box; + box-sizing: border-box; + width: 100%; + padding: .5em 1em; + border: 1px solid #c3c3c3; + border-radius: 0; +} + +/* Calendar widget */ +.widget_calendar { + font-weight: 400; +} + +.widget_calendar caption { + padding: .5em 0; + font-size: 1em; + font-weight: 500; + text-align: left; +} + +.widget_calendar thead { + background: transparent; + color: black; +} + +.widget_calendar thead th { + border-bottom-width: 2px; +} + +.widget_calendar td { + padding: .2em; + font-size: .8em; + text-align: center; + background: white; + border: 1px solid #cccccc; +} + +.widget_calendar th { + border: none; + text-align: center; +} + +.widget_calendar .pad { + background: #eaeaea; +} + +.widget_calendar a { + font-weight: 900; + text-decoration: none; +} + +/* Text widget */ +.textwidget { + font-size: 80%; + line-height: 1.3em; +} + +/* Footer widget stylings */ +.footer-widgets { + margin: 2em 0 0; + padding: 1em 0; + background-color: #1a1a1a; +} diff --git a/functions.php b/functions.php index 9923c4a..6236dc6 100644 --- a/functions.php +++ b/functions.php @@ -5,6 +5,8 @@ * @package WPAMPTheme */ +define( 'AMP_TRAVEL_LIVE_LIST_POLL_INTERVAL', 15000 ); + if ( ! file_exists( get_template_directory() . '/assets/js/editor-blocks.js' ) ) { /** * Print admin notice when theme build is needed. @@ -19,9 +21,278 @@ function _amp_travel_print_build_needed_admin_notice() { add_action( 'admin_notices', '_amp_travel_print_build_needed_admin_notice' ); } -// Load theme. -require_once get_template_directory() . '/includes/functions.php'; -require_once get_template_directory() . '/includes/class-amp-travel-theme.php'; +if ( ! function_exists( 'travel_setup' ) ) : + /** + * Sets up theme defaults and registers support for various WordPress features. + * + * Note that this function is hooked into the after_setup_theme hook, which + * runs before the init hook. The init hook is too late for some features, such + * as indicating support for post thumbnails. + */ + function travel_setup() { + /** + * Make theme available for translation. + * Translations can be filed in the /languages/ directory. + * If you're building a theme based on travel, use a find and replace + * to change 'travel' to the name of your theme in all the template files. + */ + load_theme_textdomain( 'travel', get_template_directory() . '/languages' ); + + // Add default posts and comments RSS feed links to head. + add_theme_support( 'automatic-feed-links' ); + + /** + * Let WordPress manage the document title. + * By adding theme support, we declare that this theme does not use a + * hard-coded tag in the document head, and expect WordPress to + * provide it for us. + */ + add_theme_support( 'title-tag' ); + + /** + * Enable support for Post Thumbnails on posts and pages. + * + * @link https://developer.wordpress.org/themes/functionality/featured-images-post-thumbnails/ + */ + add_theme_support( 'post-thumbnails' ); + + // This theme uses wp_nav_menu() in one location. + register_nav_menus( + array( + 'menu-1' => esc_html__( 'Primary', 'travel' ), + ) + ); + + /** + * Switch default core markup for search form, comment form, and comments + * to output valid HTML5. + */ + add_theme_support( + 'html5', array( + 'search-form', + 'comment-form', + 'comment-list', + 'gallery', + 'caption', + ) + ); + + // Set up the WordPress core custom background feature. + add_theme_support( + 'custom-background', apply_filters( + 'travel_custom_background_args', array( + 'default-color' => 'ffffff', + 'default-image' => '', + ) + ) + ); + + // Add theme support for selective refresh for widgets. + add_theme_support( 'customize-selective-refresh-widgets' ); + + /** + * Add support for core custom logo. + * + * @link https://codex.wordpress.org/Theme_Logo + */ + add_theme_support( + 'custom-logo', array( + 'height' => 250, + 'width' => 250, + 'flex-width' => true, + 'flex-height' => true, + ) + ); + + add_theme_support( + 'gutenberg', array( + 'wide-images' => true, + 'colors' => array( + '#0073aa', + '#229fd8', + '#eee', + '#444', + ), + ) + ); + + } +endif; +add_action( 'after_setup_theme', 'travel_setup' ); + +/** + * Set the content width in pixels, based on the theme's design and stylesheet. + * + * Priority 0 to make it available to lower priority callbacks. + * + * @global int $content_width + */ +function travel_content_width() { + + if ( isset( $GLOBALS['content_width'] ) ) { + $content_width = $GLOBALS['content_width']; + } + + // Check if the sidebar is in use. + if ( is_active_sidebar( 'sidebar-1' ) ) { + $content_width = 864; + } else { + $content_width = 864; + } + + /** + * Filter content width of the theme. + * + * @param int $content_width Content width in pixels. + */ + $GLOBALS['content_width'] = apply_filters( 'travel_content_width', $content_width ); +} +add_action( 'template_redirect', 'travel_content_width', 0 ); + +/** + * Register Google Fonts + */ +function travel_fonts_url() { + $fonts_url = ''; + + /** + * Translator: If Roboto Sans does not support characters in your language, translate this to 'off'. + */ + $lora = esc_html_x( 'on', 'Roboto Sans font: on or off', 'travel' ); + /** + * Translator: If Crimson Text does not support characters in your language, translate this to 'off'. + */ + $raleway = esc_html_x( 'on', 'Crimson Text font: on or off', 'travel' ); + + $font_families = array(); + + if ( 'off' !== $lora ) { + $font_families[] = 'Roboto Condensed:300,300i,400,400i'; + } + + if ( 'off' !== $raleway ) { + $font_families[] = 'Crimson Text:400,400i,600,600i'; + } + + if ( in_array( 'on', array( $lora, $raleway ) ) ) { + $query_args = array( + 'family' => urlencode( implode( '|', $font_families ) ), + 'subset' => urlencode( 'latin,latin-ext' ), + ); + + $fonts_url = add_query_arg( $query_args, 'https://fonts.googleapis.com/css' ); + } + + return esc_url_raw( $fonts_url ); + +} + +/** + * Add preconnect for Google Fonts. + * + * @since Twenty Seventeen 1.0 + * + * @param array $urls URLs to print for resource hints. + * @param string $relation_type The relation type the URLs are printed. + * @return array $urls URLs to print for resource hints. + */ +function travel_resource_hints( $urls, $relation_type ) { + if ( wp_style_is( 'travel-fonts', 'queue' ) && 'preconnect' === $relation_type ) { + $urls[] = array( + 'href' => 'https://fonts.gstatic.com', + 'crossorigin', + ); + } + + return $urls; +} +add_filter( 'wp_resource_hints', 'travel_resource_hints', 10, 2 ); + +/** + * Register widget area. + * + * @link https://developer.wordpress.org/themes/functionality/sidebars/#registering-a-sidebar + */ +function travel_widgets_init() { + register_sidebar( array( + 'name' => esc_html__( 'Sidebar', 'travel' ), + 'id' => 'sidebar-1', + 'description' => esc_html__( 'Add widgets here.', 'travel' ), + 'before_widget' => '<section id="%1$s" class="widget %2$s">', + 'after_widget' => '</section>', + 'before_title' => '<h2 class="widget-title">', + 'after_title' => '</h2>', + ) ); +} +add_action( 'widgets_init', 'travel_widgets_init' ); + +/** + * Enqueue styles. + */ +function travel_styles() { + // Add custom fonts, used in the main stylesheet. + wp_enqueue_style( 'travel-fonts', travel_fonts_url(), array(), null ); + + // Enqueue main stylesheet. + wp_enqueue_style( 'travelbase-style', get_stylesheet_uri(), array(), '20151215' ); + + // Register component styles that are printed as needed. + wp_register_style( 'travel-comments', get_theme_file_uri() . '/css/comments.css', array(), '20151215' ); + wp_register_style( 'travel-content', get_theme_file_uri() . '/css/content.css', array(), '20151215' ); + wp_register_style( 'travel-sidebar', get_theme_file_uri() . '/css/sidebar.css', array(), '20151215' ); + wp_register_style( 'travel-widgets', get_theme_file_uri() . '/css/widgets.css', array(), '20151215' ); + wp_register_style( 'travel-front-page', get_theme_file_uri() . '/css/front-page.css', array(), '20151215' ); +} +add_action( 'wp_enqueue_scripts', 'travel_styles' ); + +/** + * Enqueue scripts. + */ +function travel_scripts() { + + if ( ! travel_is_amp() ) { + wp_enqueue_script( 'travel-navigation', get_theme_file_uri() . '/js/navigation.js', array(), '20151215', false ); + wp_script_add_data( 'travel-navigation', 'async', true ); + + wp_enqueue_script( 'travel-skip-link-focus-fix', get_theme_file_uri() . '/js/skip-link-focus-fix.js', array(), '20151215', false ); + wp_script_add_data( 'travel-skip-link-focus-fix', 'defer', true ); + + if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) { + wp_enqueue_script( 'comment-reply' ); + } + } + +} +add_action( 'wp_enqueue_scripts', 'travel_scripts' ); + +/** + * Implement the Custom Header feature. + */ +require get_template_directory() . '/pluggable/custom-header.php'; + +/** + * Custom template tags for this theme. + */ +require get_template_directory() . '/inc/template-tags.php'; -// Initialize theme. -amp_travel_theme()->init(); +/** + * Functions which enhance the theme by hooking into WordPress. + */ +require get_template_directory() . '/inc/template-functions.php'; + +/** + * Customizer additions. + */ +require get_template_directory() . '/inc/customizer.php'; + +/** + * Load Jetpack compatibility file. + */ +if ( defined( 'JETPACK__VERSION' ) ) { + require get_template_directory() . '/inc/jetpack.php'; +} + +/** + * Bring in theme features bootstrap + */ +require_once get_template_directory() . '/inc/features-bootstrap.php'; \ No newline at end of file diff --git a/gulpfile.babel.js b/gulpfile.babel.js new file mode 100644 index 0000000..6d852dd --- /dev/null +++ b/gulpfile.babel.js @@ -0,0 +1,265 @@ +/* eslint-env es6 */ +'use strict'; + +/** + * To start theme building process, define the theme name below, + * then run "gulp" in command line. + */ + +import gulp from 'gulp'; +import autoprefixer from 'autoprefixer'; +import browserSync from 'browser-sync'; +import cssnano from 'gulp-cssnano'; +import babel from 'gulp-babel'; +import cssnext from 'postcss-cssnext'; +import eslint from 'gulp-eslint'; +import log from 'fancy-log'; +import gulpif from 'gulp-if'; +import image from 'gulp-image'; +import newer from 'gulp-newer'; +import partialImport from 'postcss-partial-import'; +import phpcs from 'gulp-phpcs'; +import postcss from 'gulp-postcss'; +import print from 'gulp-print'; +import replace from 'gulp-string-replace'; +import requireUncached from 'require-uncached'; +import sass from 'gulp-sass'; +import sourcemaps from 'gulp-sourcemaps'; +import sort from 'gulp-sort'; +import tabify from 'gulp-tabify'; +import uglify from 'gulp-uglify'; +import wppot from 'gulp-wp-pot'; +import zip from 'gulp-zip'; + +// Import theme-specific configurations. +var config = require( './dev/config/themeConfig.js' ); + +// Project paths +const paths = { + config: { + cssVars: './dev/config/cssVariables.json' + }, + php: { + src: [ 'dev/**/*.php', '!dev/optional/**/*.*' ], + dest: './' + }, + styles: { + src: [ 'dev/**/*.css', '!dev/optional/**/*.*' ], + dest: './', + sass: [ 'dev/**/*.scss' ] + }, + scripts: { + src: [ 'dev/**/*.js', '!dev/js/libs/**/*.js', '!dev/optional/**/*.*', '!dev/config/**/*' ], + dest: './', + libs: 'dev/js/libs/**/*.js', + libsDest: './js/libs/' + }, + images: { + src: [ 'dev/**/*.{jpg,JPG,png}', '!dev/optional/**/*.*' ], + dest: './' + }, + languages: { + src: [ './**/*.php', '!dev/**/*.php', '!verbose/**/*.php' ], + dest: './languages/' + config.theme.name + '.pot' + }, + verbose: './verbose/', + export: { + src: [ '**/*', '!dev/**/*', '!node_modules', '!node_modules/**/*', '!vendor', '!vendor/**/*', '!.*', '!composer.*', '!gulpfile.*', '!package*.*', '!phpcs.*', '!*.zip' ], + dest: './' + } +}; + +/** + * Conditionally set up BrowserSync. + * Only run BrowserSync if config.browserSync.live = true. + */ + +// Create a BrowserSync instance: +const server = browserSync.create(); + +// Initialize the BrowserSync server conditionally: +function serve( done ) { + if ( config.browserSync.live ) { + server.init( { + proxy: config.browserSync.proxyURL, + port: config.browserSync.bypassPort, + liveReload: true + } ); + } + done(); +} + +// Reload the live site: +function reload( done ) { + config = requireUncached( './dev/config/themeConfig.js' ); + if ( config.browserSync.live ) { + if ( server.paused ) { + server.resume(); + } + server.reload(); + } + else { + server.pause(); + } + done(); +} + +/** + * PHP via PHP Code Sniffer. + */ + +const themeSupportsArray = `// Add custom theme supports. + add_theme_support( 'amp' );`; + +export function php() { + config = requireUncached( './dev/config/themeConfig.js' ); + return gulp.src( paths.php.src ) + .pipe( newer( paths.php.dest ) ) + .pipe( gulpif( config.themeSupports.amp, replace( '// customThemeSupports.', themeSupportsArray ) ) ) + .pipe( phpcs( { + bin: 'vendor/bin/phpcs', + standard: 'WordPress', + warningSeverity: 0 + } ) ) + // Log all problems that was found + .pipe( phpcs.reporter( 'log' ) ) + .pipe( gulp.dest( paths.verbose ) ) + .pipe( gulp.dest( paths.php.dest ) ); +} + +/** + * Sass, if that's being used. + */ +export function sassStyles() { + return gulp.src( paths.styles.sass, {base: './'} ) + .pipe( sourcemaps.init() ) + .pipe( sass().on( 'error', sass.logError ) ) + .pipe( tabify( 2, true ) ) + .pipe( sourcemaps.write( './maps' ) ) + .pipe( gulp.dest( '.' ) ); +} + +/** + * CSS via PostCSS + CSSNext (includes Autoprefixer by default). + */ +export function styles() { + config = requireUncached( './dev/config/themeConfig.js' ); + + // Reload cssVars every time the task runs. + let cssVars = requireUncached( paths.config.cssVars ); + + return gulp.src( paths.styles.src ) + .pipe( print() ) + .pipe( phpcs( { + bin: 'vendor/bin/phpcs', + standard: 'WordPress', + warningSeverity: 0 + } ) ) + // Log all problems that was found + .pipe( phpcs.reporter( 'log' ) ) + .pipe( postcss( [ + cssnext( { + browsers: config.theme.browserslist, + features: { + customProperties: { + variables: cssVars.variables, + }, + customMedia: { + extensions: cssVars.queries, + } + } + } ) + ] ) ) + .pipe( gulp.dest( paths.verbose ) ) + .pipe( gulpif( !config.debug.styles, cssnano() ) ) + .pipe( gulp.dest( paths.styles.dest ) ); +} + +/** + * JavaScript via Babel, ESlint, and uglify. + */ +export function scripts() { + config = requireUncached( './dev/config/themeConfig.js' ); + return gulp.src( paths.scripts.src ) + .pipe( newer( paths.scripts.dest ) ) + .pipe( eslint() ) + .pipe( eslint.format() ) + .pipe( babel() ) + .pipe( gulp.dest( paths.verbose ) ) + .pipe( gulpif( !config.debug.styles, uglify() ) ) + .pipe( gulp.dest( paths.scripts.dest ) ); +} + +/** + * Copy JS libraries without touching them. + */ +export function jsCopy() { + return gulp.src( paths.scripts.libs ) + .pipe( newer( paths.scripts.libsDest ) ) + .pipe( gulp.dest( paths.verbose ) ) + .pipe( gulp.dest( paths.scripts.libsDest ) ); +} + +/** + * Optimize images. + */ +export function images() { + return gulp.src( paths.images.src ) + .pipe( newer( paths.images.dest ) ) + .pipe( image() ) + .pipe( gulp.dest( paths.images.dest ) ); +} + +/** + * Watch everything + */ +export function watch() { + gulp.watch( paths.php.src, gulp.series( php, reload ) ); + gulp.watch( paths.config.cssVars, gulp.series( styles, reload ) ); + gulp.watch( paths.styles.sass, sassStyles ); + gulp.watch( paths.styles.src, gulp.series( styles, reload ) ); + gulp.watch( paths.scripts.src, gulp.series( gulp.parallel( scripts, jsCopy ), reload ) ); + gulp.watch( paths.images.src, gulp.series( images, reload ) ); +} + +/** + * Map out the sequence of events on first load: + */ +const firstRun = gulp.series( php, gulp.parallel( scripts, jsCopy ), sassStyles, styles, images, serve, watch ); + +/** + * Run the whole thing. + */ +export default firstRun; + +/** + * Generate translation files. + */ +export function translate() { + return gulp.src( paths.languages.src ) + .pipe( sort() ) + .pipe( wppot( { + domain: config.theme.name, + package: config.theme.name, + bugReport: config.theme.name, + lastTranslator: config.theme.author + } ) ) + .pipe( gulp.dest( paths.languages.dest ) ); +} + +/** + * Create zip archive from generated theme files. + */ +export function bundle() { + return gulp.src( paths.export.src ) + .pipe( print() ) + .pipe( gulpif( config.export.compress, zip( config.theme.name + '.zip' ), gulp.dest( paths.export.dest + config.theme.name ) ) ) + .pipe( gulpif( config.export.compress, gulp.dest( paths.export.dest ) ) ); +} + +/** + * Export theme for distribution. + */ +const bundleTheme = gulp.series( php, gulp.parallel( scripts, jsCopy ), styles, images, translate, bundle ); + +export { bundleTheme }; diff --git a/includes/class-amp-travel-blocks.php b/inc/classes/class-amp-travel-blocks.php similarity index 97% rename from includes/class-amp-travel-blocks.php rename to inc/classes/class-amp-travel-blocks.php index 6ea3a30..f8d9dd7 100644 --- a/includes/class-amp-travel-blocks.php +++ b/inc/classes/class-amp-travel-blocks.php @@ -58,9 +58,16 @@ public function filter_pre_get_posts( $query ) { if ( ! is_admin() && is_search() ) { $meta_query = array(); - if ( ! empty( $_GET['start'] ) && ! empty( $_GET['end'] ) ) { - $start = sanitize_text_field( wp_unslash( $_GET['start'] ) ); - $end = sanitize_text_field( wp_unslash( $_GET['end'] ) ); + $vars = array( + 'start' => 'FILTER_SANITIZE_STRING', + 'end' => 'FILTER_SANITIZE_STRING', + ); + + $data = wp_unslash( filter_input_array( INPUT_GET, $vars ) ); + + if ( ! empty( $data['start'] ) && ! empty( $data['end'] ) ) { + $start = sanitize_text_field( $data['start'] ); + $end = sanitize_text_field( $data['end'] ); $meta_query = array( 'relation' => 'OR', array( @@ -100,8 +107,8 @@ public function filter_pre_get_posts( $query ) { ); // If we only have start date, only the end date is relevant. - } elseif ( ! empty( $_GET['start'] ) ) { - $start = sanitize_text_field( wp_unslash( $_GET['start'] ) ); + } elseif ( ! empty( $data['start'] ) ) { + $start = sanitize_text_field( $data['start'] ); $meta_query = array( 'relation' => 'OR', array( @@ -115,8 +122,8 @@ public function filter_pre_get_posts( $query ) { 'compare' => '>=', ), ); - } elseif ( ! empty( $_GET['end'] ) ) { - $end = sanitize_text_field( wp_unslash( $_GET['end'] ) ); + } elseif ( ! empty( $data['end'] ) ) { + $end = sanitize_text_field( $data['end'] ); $meta_query = array( 'relation' => 'OR', array( diff --git a/includes/class-amp-travel-cpt.php b/inc/classes/class-amp-travel-cpt.php similarity index 92% rename from includes/class-amp-travel-cpt.php rename to inc/classes/class-amp-travel-cpt.php index 64cb48d..e41167d 100644 --- a/includes/class-amp-travel-cpt.php +++ b/inc/classes/class-amp-travel-cpt.php @@ -205,31 +205,39 @@ public function adventure_meta_box_html() { * Saves the custom meta. */ public function save_adventure_post() { + $vars = array( + 'amp_travel_start_date' => 'FILTER_SANITIZE_STRING', + 'amp_travel_end_date' => 'FILTER_SANITIZE_STRING', + 'amp_travel_price' => 'FILTER_SANITIZE_STRING', + 'amp_travel_adventure_nonce' => 'FILTER_SANITIZE_STRING', + ); + + $data = wp_unslash( filter_input_array( INPUT_POST, $vars ) ); // This check is needed since otherwise Gutenberg save will fail -- it uses different saving logic. if ( - isset( $_POST['amp_travel_start_date'] ) + isset( $data['amp_travel_start_date'] ) || - isset( $_POST['amp_travel_end_date'] ) + isset( $data['amp_travel_end_date'] ) || - isset( $_POST['amp_travel_price'] ) + isset( $data['amp_travel_price'] ) ) { global $post; - if ( ! wp_verify_nonce( $_POST['amp_travel_adventure_nonce'], basename( __FILE__ ) ) ) { + if ( ! wp_verify_nonce( $data['amp_travel_adventure_nonce'], basename( __FILE__ ) ) ) { return; } - if ( isset( $_POST['amp_travel_price'] ) ) { - update_post_meta( get_the_ID(), 'amp_travel_price', sanitize_text_field( wp_unslash( $_POST['amp_travel_price'] ) ) ); + if ( isset( $data['amp_travel_price'] ) ) { + update_post_meta( get_the_ID(), 'amp_travel_price', sanitize_text_field( $data['amp_travel_price'] ) ); } - if ( isset( $_POST['amp_travel_start_date'] ) ) { - update_post_meta( $post->ID, 'amp_travel_start_date', sanitize_text_field( wp_unslash( $_POST['amp_travel_start_date'] ) ) ); + if ( isset( $data['amp_travel_start_date'] ) ) { + update_post_meta( $post->ID, 'amp_travel_start_date', sanitize_text_field( $data['amp_travel_start_date'] ) ); } - if ( isset( $_POST['amp_travel_end_date'] ) ) { - update_post_meta( $post->ID, 'amp_travel_end_date', sanitize_text_field( wp_unslash( $_POST['amp_travel_end_date'] ) ) ); + if ( isset( $data['amp_travel_end_date'] ) ) { + update_post_meta( $post->ID, 'amp_travel_end_date', sanitize_text_field( $data['amp_travel_end_date'] ) ); } } } diff --git a/includes/class-amp-travel-theme.php b/inc/classes/class-amp-travel-features.php similarity index 52% rename from includes/class-amp-travel-theme.php rename to inc/classes/class-amp-travel-features.php index 937661a..c9e48cf 100644 --- a/includes/class-amp-travel-theme.php +++ b/inc/classes/class-amp-travel-features.php @@ -1,16 +1,23 @@ <?php /** - * AMP Travel Theme class. + * AMP Travel Theme Features class. * * @package WPAMPTheme */ /** - * Class AMP_Travel_Theme. + * Class AMP_Travel_Features. * * @package WPAMPTheme */ -class AMP_Travel_Theme { +class AMP_Travel_Features { + + /** + * Array of feature objects. + * + * @var stdClass + */ + public $features; /** * Get theme instance. @@ -20,8 +27,8 @@ class AMP_Travel_Theme { public static function get_instance() { static $instance; - if ( ! $instance instanceof AMP_Travel_Theme ) { - $instance = new AMP_Travel_Theme(); + if ( ! $instance instanceof AMP_Travel_Features ) { + $instance = new AMP_Travel_Features(); } return $instance; @@ -37,25 +44,34 @@ public function init() { } /** - * Theme includes. + * Include feature classes. */ public function includes() { $dir = get_template_directory(); - require_once $dir . '/includes/class-amp-travel-blocks.php'; - require_once $dir . '/includes/class-amp-travel-cpt.php'; - require_once $dir . '/includes/class-amp-travel-taxonomies.php'; + + require_once $dir . '/inc/classes/class-amp-travel-taxonomies.php'; + require_once $dir . '/inc/classes/class-amp-travel-blocks.php'; + require_once $dir . '/inc/classes/class-amp-travel-cpt.php'; + require_once $dir . '/inc/classes/class-amp-travel-taxonomies.php'; } /** * Init classes. */ public function instantiate_classes() { - $travel_blocks = new AMP_Travel_Blocks(); - $travel_blocks->init(); - $travel_cpt = new AMP_Travel_CPT(); - $travel_cpt->init(); - $travel_taxonomies = new AMP_Travel_Taxonomies(); - $travel_taxonomies->init(); + $this->features = new stdClass(); + + // Init blocks. + $this->features->blocks = new AMP_Travel_Blocks(); + $this->features->blocks->init(); + + // Init custom post type. + $this->features->cpt = new AMP_Travel_CPT(); + $this->features->cpt->init(); + + // Init taxonomies. + $this->features->taxonomies = new AMP_Travel_Taxonomies(); + $this->features->taxonomies->init(); } /** diff --git a/includes/class-amp-travel-taxonomies.php b/inc/classes/class-amp-travel-taxonomies.php similarity index 94% rename from includes/class-amp-travel-taxonomies.php rename to inc/classes/class-amp-travel-taxonomies.php index cc8dc5c..714e8ef 100644 --- a/includes/class-amp-travel-taxonomies.php +++ b/inc/classes/class-amp-travel-taxonomies.php @@ -168,7 +168,7 @@ public function add_activity_meta_fields() { <div class='form-field form-required term-svg-wrap'> <label for='travel-activity-svg'>SVG</label> <?php wp_nonce_field( basename( __FILE__ ), 'travel_activity_svg_nonce' ); ?> - <textarea aria-required='true' name='travel-activity-svg' id='travel-activity-svg'></textarea> + <textarea aria-required='true' name='travel_activity_svg' id='travel-activity-svg'></textarea> <p class="description"><?php esc_html_e( 'This is for the background icon of the activity term. Only <path>, <svg>, <g>, and <circle> elements are allowed', 'travel' ); ?></p> </div> <?php @@ -230,9 +230,7 @@ public function edit_activity_meta_fields( $term ) { <th scope="row"><label for="travel-activity-svg"><?php esc_attr_e( 'SVG', 'travel' ); ?></label></th> <td> <?php wp_nonce_field( basename( __FILE__ ), 'travel_activity_svg_nonce' ); ?> - <textarea aria-required="true" name="travel-activity-svg" id="travel-activity-svg"> - <?php echo $this->sanitize_activity_svg( $value ); // WPCS: XSS ok. ?> - </textarea> + <textarea aria-required="true" name="travel_activity_svg" id="travel-activity-svg"><?php echo $this->sanitize_activity_svg( $value ); // WPCS: XSS ok. ?></textarea> <p class="description"><?php esc_html_e( 'This is for the background icon of the activity term. Only <path>, <svg>, <g>, and <circle> elements are allowed', 'travel' ); ?></p> </td> </tr> @@ -245,14 +243,20 @@ public function edit_activity_meta_fields( $term ) { * @param integer $term_id Term ID. */ public function save_activity_meta( $term_id ) { + $vars = array( + 'travel_activity_svg' => 'FILTER_UNSAFE_RAW', + 'travel_activity_svg_nonce' => 'FILTER_SANITIZE_STRING', + ); + + $data = filter_input_array( INPUT_POST, $vars ); - if ( ! wp_verify_nonce( $_POST['travel_activity_svg_nonce'], basename( __FILE__ ) ) ) { + if ( ! wp_verify_nonce( $data['travel_activity_svg_nonce'], basename( __FILE__ ) ) ) { return; } $old_value = get_term_meta( $term_id, 'amp_travel_activity_svg', true ); - $original_value = isset( $_POST['travel-activity-svg'] ) ? trim( $_POST['travel-activity-svg'] ) : ''; - $new_value = isset( $_POST['travel-activity-svg'] ) ? $this->sanitize_activity_svg( $_POST['travel-activity-svg'] ) : ''; + $original_value = isset( $data['travel_activity_svg'] ) ? trim( $data['travel_activity_svg'] ) : ''; + $new_value = isset( $data['travel_activity_svg'] ) ? $this->sanitize_activity_svg( $data['travel_activity_svg'] ) : ''; if ( $old_value !== $new_value ) { diff --git a/inc/customizer.php b/inc/customizer.php new file mode 100644 index 0000000..1359577 --- /dev/null +++ b/inc/customizer.php @@ -0,0 +1,59 @@ +<?php +/** + * Travel Theme Customizer + * + * @package WPAMPTheme + */ + +/** + * Add postMessage support for site title and description for the Theme Customizer. + * + * @param WP_Customize_Manager $wp_customize Theme Customizer object. + */ +function travel_customize_register( $wp_customize ) { + $wp_customize->get_setting( 'blogname' )->transport = 'postMessage'; + $wp_customize->get_setting( 'blogdescription' )->transport = 'postMessage'; + $wp_customize->get_setting( 'header_textcolor' )->transport = 'postMessage'; + + if ( isset( $wp_customize->selective_refresh ) ) { + $wp_customize->selective_refresh->add_partial( + 'blogname', array( + 'selector' => '.site-title a', + 'render_callback' => 'travel_customize_partial_blogname', + ) + ); + $wp_customize->selective_refresh->add_partial( + 'blogdescription', array( + 'selector' => '.site-description', + 'render_callback' => 'travel_customize_partial_blogdescription', + ) + ); + } +} +add_action( 'customize_register', 'travel_customize_register' ); + +/** + * Render the site title for the selective refresh partial. + * + * @return void + */ +function travel_customize_partial_blogname() { + bloginfo( 'name' ); +} + +/** + * Render the site tagline for the selective refresh partial. + * + * @return void + */ +function travel_customize_partial_blogdescription() { + bloginfo( 'description' ); +} + +/** + * Binds JS handlers to make Theme Customizer preview reload changes asynchronously. + */ +function travel_customize_preview_js() { + wp_enqueue_script( 'travel-customizer', get_template_directory_uri() . '/js/customizer.js', array( 'customize-preview' ), '20151215', true ); +} +add_action( 'customize_preview_init', 'travel_customize_preview_js' ); diff --git a/inc/features-bootstrap.php b/inc/features-bootstrap.php new file mode 100644 index 0000000..91c231e --- /dev/null +++ b/inc/features-bootstrap.php @@ -0,0 +1,21 @@ +<?php +/** + * Theme features bootstrap file. + * + * @package WPAMPTheme + */ + +/** + * AMP_Travel_Features object helper function. + * + * @return object Theme object + */ +function amp_travel_features() { + return AMP_Travel_Features::get_instance(); +} + +// Require the features class. +require_once get_template_directory() . '/inc/classes/class-amp-travel-features.php'; + +// Initialize features. +amp_travel_features()->init(); diff --git a/inc/jetpack.php b/inc/jetpack.php new file mode 100644 index 0000000..ba4832e --- /dev/null +++ b/inc/jetpack.php @@ -0,0 +1,58 @@ +<?php +/** + * Jetpack Compatibility File + * + * @link https://jetpack.com/ + * + * @package WPAMPTheme + */ + +/** + * Jetpack setup function. + * + * See: https://jetpack.com/support/infinite-scroll/ + * See: https://jetpack.com/support/responsive-videos/ + * See: https://jetpack.com/support/content-options/ + */ +function travel_jetpack_setup() { + // Add theme support for Infinite Scroll. + add_theme_support( + 'infinite-scroll', array( + 'container' => 'main', + 'render' => 'travel_infinite_scroll_render', + 'footer' => 'page', + ) + ); + + // Add theme support for Responsive Videos. + add_theme_support( 'jetpack-responsive-videos' ); + + // Add theme support for Content Options. + add_theme_support( + 'jetpack-content-options', array( + 'post-details' => array( + 'stylesheet' => 'travel-style', + 'date' => '.posted-on', + 'categories' => '.cat-links', + 'tags' => '.tags-links', + 'author' => '.byline', + 'comment' => '.comments-link', + ), + ) + ); +} +add_action( 'after_setup_theme', 'travel_jetpack_setup' ); + +/** + * Custom render function for Infinite Scroll. + */ +function travel_infinite_scroll_render() { + while ( have_posts() ) { + the_post(); + if ( is_search() ) : + get_template_part( 'template-parts/content', 'search' ); + else : + get_template_part( 'template-parts/content', get_post_type() ); + endif; + } +} diff --git a/includes/functions.php b/inc/template-functions.php similarity index 74% rename from includes/functions.php rename to inc/template-functions.php index 3a65f7c..704e240 100644 --- a/includes/functions.php +++ b/inc/template-functions.php @@ -1,20 +1,127 @@ <?php /** - * Theme functions file. + * Functions which enhance the theme by hooking into WordPress * * @package WPAMPTheme */ -define( 'AMP_TRAVEL_LIVE_LIST_POLL_INTERVAL', 15000 ); +/** + * Adds custom classes to the array of body classes. + * + * @param array $classes Classes for the body element. + * @return array + */ +function travel_body_classes( $classes ) { + // Adds a class of hfeed to non-singular pages. + if ( ! is_singular() ) { + $classes[] = 'hfeed'; + } + + if ( is_active_sidebar( 'sidebar-1' ) ) { + global $template; + if ( 'front-page.php' !== basename( $template ) ) { + $classes[] = 'has-sidebar'; + } + } + + return $classes; +} +add_filter( 'body_class', 'travel_body_classes' ); + +/** + * Add a pingback url auto-discovery header for singularly identifiable articles. + */ +function travel_pingback_header() { + if ( is_singular() && pings_open() ) { + echo '<link rel="pingback" href="', esc_url( get_bloginfo( 'pingback_url' ) ), '">'; + } +} +add_action( 'wp_head', 'travel_pingback_header' ); + +/** + * Adds async/defer attributes to enqueued / registered scripts. + * + * If #12009 lands in WordPress, this function can no-op since it would be handled in core. + * + * @link https://core.trac.wordpress.org/ticket/12009 + * @param string $tag The script tag. + * @param string $handle The script handle. + * @return array + */ +function travel_filter_script_loader_tag( $tag, $handle ) { + + foreach ( array( 'async', 'defer' ) as $attr ) { + if ( ! wp_scripts()->get_data( $handle, $attr ) ) { + continue; + } + + // Prevent adding attribute when already added in #12009. + if ( ! preg_match( ":\s$attr(=|>|\s):", $tag ) ) { + $tag = preg_replace( ':(?=></script>):', " $attr", $tag, 1 ); + } + + // Only allow async or defer, not both. + break; + } + + return $tag; +} + +add_filter( 'script_loader_tag', 'travel_filter_script_loader_tag', 10, 2 ); + +/** + * Generate stylesheet URI. + * + * @param object $wp_styles Registered styles. + * @param string $handle The style handle. + */ +function travel_get_preload_stylesheet_uri( $wp_styles, $handle ) { + $preload_uri = $wp_styles->registered[ $handle ]->src . '?ver=' . $wp_styles->registered[ $handle ]->ver; + return $preload_uri; +} /** - * Init theme. + * Adds preload for in-body stylesheets depending on what templates are being used. * - * @return object Theme object + * @link https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content */ -function amp_travel_theme() { - return AMP_Travel_Theme::get_instance(); +function travel_add_body_style() { + + // Get the current template global. + global $template; + + // Get registered styles. + $wp_styles = wp_styles(); + + $prelods = array(); + + // Preload content.css. + $preloads['travel-content'] = travel_get_preload_stylesheet_uri( $wp_styles, 'travel-content' ); + + // Preload sidebar.css and widget.css. + if ( is_active_sidebar( 'sidebar-1' ) ) { + $preloads['travel-sidebar'] = travel_get_preload_stylesheet_uri( $wp_styles, 'travel-sidebar' ); + $preloads['travel-widgets'] = travel_get_preload_stylesheet_uri( $wp_styles, 'travel-widgets' ); + } + + // Preload comments.css. + if ( ! post_password_required() && is_singular() && ( comments_open() || get_comments_number() ) ) { + $preloads['travel-comments'] = travel_get_preload_stylesheet_uri( $wp_styles, 'travel-comments' ); + } + + // Preload front-page.css. + if ( 'front-page.php' === basename( $template ) ) { + $preloads['travel-front-page'] = travel_get_preload_stylesheet_uri( $wp_styles, 'travel-front-page' ); + } + + // Output the preload markup in <head>. + foreach ( $preloads as $handle => $src ) { + echo '<link rel="preload" id="' . esc_attr( $handle ) . '-preload" href="' . esc_url( $src ) . '" as="style" />'; + echo "\n"; + } + } +add_action( 'wp_head', 'travel_add_body_style' ); /** * Display similar adventures. @@ -122,8 +229,8 @@ function amp_travel_get_popular_adventures( $adventures, $attributes ) { $output .= '</div> </div> <span class="travel-results-result-subtext mr1">' . - /* translators: %d: The number of reviews */ - sprintf( esc_html( _n( '%d Review', '%d Reviews', $reviews->approved, 'travel' ) ), esc_html( $reviews->approved ) ) . '</span> + /* translators: %d: The number of reviews */ + sprintf( esc_html( _n( '%d Review', '%d Reviews', $reviews->approved, 'travel' ) ), esc_html( $reviews->approved ) ) . '</span> <span class="travel-results-result-subtext"><svg class="travel-icon" viewBox="0 0 77 100"><g fill="none" fill-rule="evenodd"><path stroke="currentColor" stroke-width="7.5" d="M38.794 93.248C58.264 67.825 68 49.692 68 38.848 68 22.365 54.57 9 38 9S8 22.364 8 38.85c0 10.842 9.735 28.975 29.206 54.398a1 1 0 0 0 1.588 0z"></path><circle cx="38" cy="39" r="10" fill="currentColor"></circle></g></svg> ' . esc_html( $location ) . '</span> </div> @@ -183,7 +290,7 @@ function amp_travel_save_comment_meta_data( $comment_id ) { $comment = get_comment( $comment_id ); if ( current_user_can( 'unfiltered_html' ) ) { if ( ! isset( $_POST['_wp_unfiltered_html_comment'] ) - || ! wp_verify_nonce( $_POST['_wp_unfiltered_html_comment'], 'unfiltered-html-comment_' . $comment->comment_post_ID ) + || ! wp_verify_nonce( $_POST['_wp_unfiltered_html_comment'], 'unfiltered-html-comment_' . $comment->comment_post_ID ) ) { kses_remove_filters(); // Start with a clean slate. kses_init_filters(); // Set up the filters. diff --git a/inc/template-tags.php b/inc/template-tags.php new file mode 100644 index 0000000..d048154 --- /dev/null +++ b/inc/template-tags.php @@ -0,0 +1,249 @@ +<?php +/** + * Custom template tags for this theme + * + * Eventually, some of the functionality here could be replaced by core features. + * + * @package WPAMPTheme + */ + +/** + * Test for AMP support. + */ +function travel_is_amp() { + if ( current_theme_supports( 'amp' ) && function_exists( 'is_amp_endpoint' ) && is_amp_endpoint() ) { + return true; + } else { + return false; + } +} + +if ( ! function_exists( 'travel_index_header' ) ) : + /** + * Prints the header of the current displayed page based on its contents. + */ + function travel_index_header() { + if ( is_home() && ! is_front_page() ) { + ?> + <header> + <h1 class="page-title screen-reader-text"><?php single_post_title(); ?></h1> + </header> + <?php + } elseif ( is_search() ) { + ?> + <header class="page-header"> + <h1 class="page-title"> + <?php + /* translators: %s: search query. */ + printf( esc_html__( 'Search Results for: %s', 'travel' ), '<span>' . get_search_query() . '</span>' ); + ?> + </h1> + </header><!-- .page-header --> + <?php + } elseif ( is_archive() ) { + ?> + <header class="page-header"> + <?php + the_archive_title( '<h1 class="page-title">', '</h1>' ); + the_archive_description( '<div class="archive-description">', '</div>' ); + ?> + </header><!-- .page-header --> + <?php + } + + } + +endif; + +if ( ! function_exists( 'travel_posted_on' ) ) : + /** + * Prints HTML with meta information for the current post-date/time. + */ + function travel_posted_on() { + $time_string = '<time class="entry-date published updated" datetime="%1$s">%2$s</time>'; + if ( get_the_time( 'U' ) !== get_the_modified_time( 'U' ) ) { + $time_string = '<time class="entry-date published" datetime="%1$s">%2$s</time><time class="updated" datetime="%3$s">%4$s</time>'; + } + + $time_string = sprintf( + $time_string, + esc_attr( get_the_date( 'c' ) ), + esc_html( get_the_date() ), + esc_attr( get_the_modified_date( 'c' ) ), + esc_html( get_the_modified_date() ) + ); + + $posted_on = sprintf( + /* translators: %s: post date. */ + esc_html_x( 'Posted on %s', 'post date', 'travel' ), + '<a href="' . esc_url( get_permalink() ) . '" rel="bookmark">' . $time_string . '</a>' + ); + + echo '<span class="posted-on">' . $posted_on . '</span>'; // WPCS: XSS OK. + + } +endif; + +if ( ! function_exists( 'travel_posted_by' ) ) : + /** + * Prints HTML with meta information for the current author. + */ + function travel_posted_by() { + $byline = sprintf( + /* translators: %s: post author. */ + esc_html_x( 'by %s', 'post author', 'travel' ), + '<span class="author vcard"><a class="url fn n" href="' . esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ) . '">' . esc_html( get_the_author() ) . '</a></span>' + ); + + echo '<span class="byline"> ' . $byline . '</span>'; // WPCS: XSS OK. + + } +endif; + +if ( ! function_exists( 'travel_attachment_in' ) ) : + /** + * Prints HTML with title and link to original post where attachment was added. + * + * @param object $post object. + */ + function travel_attachment_in( $post ) { + if ( ! empty( $post->post_parent ) ) : + $postlink = sprintf( + /* translators: %s: original post where attachment was added. */ + esc_html_x( 'in %s', 'original post', 'travel' ), + '<a href="' . esc_url( get_permalink( $post->post_parent ) ) . '">' . esc_html( get_the_title( $post->post_parent ) ) . '</a>' + ); + + echo '<span class="attachment-in"> ' . $postlink . '</span>'; // WPCS: XSS OK. + + endif; + + } +endif; + +if ( ! function_exists( 'travel_the_attachment_navigation' ) ) : + /** + * Prints HTML with for navigation to previous and next attachment if available. + */ + function travel_the_attachment_navigation() { + ?> + <nav class="navigation post-navigation" role="navigation"> + <h2 class="screen-reader-text">Post navigation</h2> + <div class="nav-links"> + <div class="nav-previous"> + <div class="post-navigation-sub"> + <?php echo esc_html__( 'Previous attachment:', 'travel' ); ?> + </div> + <?php previous_image_link( false ); ?> + </div><!-- .nav-previous --> + <div class="nav-next"> + <div class="post-navigation-sub"> + <?php echo esc_html__( 'Next attachment:', 'travel' ); ?> + </div> + <?php next_image_link( false ); ?> + </div><!-- .nav-next --> + </div><!-- .nav-links --> + </nav><!-- .navigation .attachment-navigation --> + <?php + } +endif; + +if ( ! function_exists( 'travel_entry_footer' ) ) : + /** + * Prints HTML with meta information for the categories, tags and comments. + */ + function travel_entry_footer() { + // Hide category and tag text for pages. + if ( 'post' === get_post_type() ) { + /* translators: used between list items, there is a space after the comma */ + $categories_list = get_the_category_list( esc_html__( ', ', 'travel' ) ); + if ( $categories_list ) { + /* translators: 1: list of categories. */ + printf( '<span class="cat-links">' . esc_html__( 'Posted in %1$s', 'travel' ) . '</span>', $categories_list ); // WPCS: XSS OK. + } + + /* translators: used between list items, there is a space after the comma */ + $tags_list = get_the_tag_list( '', esc_html_x( ', ', 'list item separator', 'travel' ) ); + if ( $tags_list ) { + /* translators: 1: list of tags. */ + printf( '<span class="tags-links">' . esc_html__( 'Tagged %1$s', 'travel' ) . '</span>', $tags_list ); // WPCS: XSS OK. + } + } + + if ( ! is_single() && ! post_password_required() && ( comments_open() || get_comments_number() ) ) { + echo '<span class="comments-link">'; + comments_popup_link( + sprintf( + wp_kses( + /* translators: %s: post title */ + __( 'Leave a Comment<span class="screen-reader-text"> on %s</span>', 'travel' ), + array( + 'span' => array( + 'class' => array(), + ), + ) + ), + get_the_title() + ) + ); + echo '</span>'; + } + + edit_post_link( + sprintf( + wp_kses( + /* translators: %s: Name of current post. Only visible to screen readers */ + __( 'Edit <span class="screen-reader-text">%s</span>', 'travel' ), + array( + 'span' => array( + 'class' => array(), + ), + ) + ), + get_the_title() + ), + '<span class="edit-link">', + '</span>' + ); + } +endif; + +if ( ! function_exists( 'travel_post_thumbnail' ) ) : + /** + * Displays an optional post thumbnail. + * + * Wraps the post thumbnail in an anchor element on index views, or a div + * element when on single views. + */ + function travel_post_thumbnail() { + if ( post_password_required() || is_attachment() || ! has_post_thumbnail() ) { + return; + } + + if ( is_singular() ) : + ?> + + <div class="post-thumbnail"> + <?php the_post_thumbnail(); ?> + </div><!-- .post-thumbnail --> + + <?php else : ?> + + <a class="post-thumbnail" href="<?php the_permalink(); ?>" aria-hidden="true"> + <?php + the_post_thumbnail( + 'post-thumbnail', array( + 'alt' => the_title_attribute( + array( + 'echo' => false, + ) + ), + ) + ); + ?> + </a> + + <?php + endif; // End is_singular(). + } +endif; diff --git a/js/customizer.js b/js/customizer.js new file mode 100644 index 0000000..3987c89 --- /dev/null +++ b/js/customizer.js @@ -0,0 +1,44 @@ +'use strict'; + +/** + * File customizer.js. + * + * Theme Customizer enhancements for a better user experience. + * + * Contains handlers to make Theme Customizer preview reload changes asynchronously. + */ + +(function ($) { + + // Site title and description. + wp.customize('blogname', function (value) { + value.bind(function (to) { + $('.site-title a').text(to); + }); + }); + wp.customize('blogdescription', function (value) { + value.bind(function (to) { + $('.site-description').text(to); + }); + }); + + // Header text color. + wp.customize('header_textcolor', function (value) { + value.bind(function (to) { + if ('blank' === to) { + $('.site-title, .site-description').css({ + 'clip': 'rect(1px, 1px, 1px, 1px)', + 'position': 'absolute' + }); + } else { + $('.site-title, .site-description').css({ + 'clip': 'auto', + 'position': 'relative' + }); + $('.site-title a, .site-description').css({ + 'color': to + }); + } + }); + }); +})(jQuery); \ No newline at end of file diff --git a/js/navigation.js b/js/navigation.js new file mode 100644 index 0000000..5880cad --- /dev/null +++ b/js/navigation.js @@ -0,0 +1,127 @@ +'use strict'; + +/** + * File navigation.js. + * + * Handles toggling the navigation menu for small screens and enables TAB key + * navigation support for dropdown menus. + */ + +/** + * Polyfill for feature detection of passive property. + * @link: https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md#feature-detection + */ +var supportsPassive = false; +var opts; +try { + opts = Object.defineProperty({}, 'passive', { + get: function get() { + supportsPassive = true; + } + }); + window.addEventListener('testPassive', null, opts); + window.removeEventListener('testPassive', null, opts); +} catch (e) {} + +(function () { + var container, button, menu, links, i, len; + + container = document.querySelector('#site-navigation'); + if (!container) { + return; + } + + button = container.querySelectorAll('button')[0]; + if ('undefined' === typeof button) { + return; + } + + menu = container.querySelectorAll('ul')[0]; + + // Hide menu toggle button if menu is empty and return early. + if ('undefined' === typeof menu) { + button.style.display = 'none'; + return; + } + + menu.setAttribute('aria-expanded', 'false'); + if (-1 === menu.className.indexOf('nav-menu')) { + menu.className += ' nav-menu'; + } + + button.onclick = function () { + if (-1 !== container.className.indexOf('toggled')) { + container.className = container.className.replace(' toggled', ''); + button.setAttribute('aria-expanded', 'false'); + menu.setAttribute('aria-expanded', 'false'); + } else { + container.className += ' toggled'; + button.setAttribute('aria-expanded', 'true'); + menu.setAttribute('aria-expanded', 'true'); + } + }; + + // Get all the link elements within the menu. + links = menu.querySelectorAll('a'); + + // Each time a menu link is focused or blurred, toggle focus. + for (i = 0, len = links.length; i < len; i++) { + links[i].addEventListener('focus', toggleFocus, true); + links[i].addEventListener('blur', toggleFocus, true); + } + + /** + * Sets or removes .focus class on an element. + */ + function toggleFocus() { + var self = this; + + // Move up through the ancestors of the current link until we hit .nav-menu. + while (-1 === self.className.indexOf('nav-menu')) { + + // On li elements toggle the class .focus. + if ('li' === self.tagName.toLowerCase()) { + if (-1 !== self.className.indexOf('focus')) { + self.className = self.className.replace(' focus', ''); + } else { + self.className += ' focus'; + } + } + + self = self.parentElement; + } + } + + /** + * Toggles `focus` class to allow submenu access on tablets. + */ + (function (container) { + var touchStartFn, + i, + parentLink = container.querySelectorAll('.menu-item-has-children > a, .page_item_has_children > a'); + + if ('ontouchstart' in window) { + touchStartFn = function touchStartFn(e) { + var menuItem = this.parentNode, + i; + + if (!menuItem.classList.contains('focus')) { + e.preventDefault(); + for (i = 0; i < menuItem.parentNode.children.length; ++i) { + if (menuItem === menuItem.parentNode.children[i]) { + continue; + } + menuItem.parentNode.children[i].classList.remove('focus'); + } + menuItem.classList.add('focus'); + } else { + menuItem.classList.remove('focus'); + } + }; + + for (i = 0; i < parentLink.length; ++i) { + parentLink[i].addEventListener('touchstart', touchStartFn, supportsPassive ? { passive: true } : false); + } + } + })(container); +})(); \ No newline at end of file diff --git a/js/skip-link-focus-fix.js b/js/skip-link-focus-fix.js new file mode 100644 index 0000000..9b52b69 --- /dev/null +++ b/js/skip-link-focus-fix.js @@ -0,0 +1,33 @@ +'use strict'; + +/** + * File skip-link-focus-fix.js. + * + * Helps with accessibility for keyboard only users. + * + * Learn more: https://git.io/vWdr2 + */ +(function () { + var isIe = /(trident|msie)/i.test(navigator.userAgent); + + if (isIe && document.getElementById && window.addEventListener) { + window.addEventListener('hashchange', function () { + var id = location.hash.substring(1), + element; + + if (!/^[A-z0-9_-]+$/.test(id)) { + return; + } + + element = document.getElementById(id); + + if (element) { + if (!/^(?:a|select|input|button|textarea)$/i.test(element.tagName)) { + element.tabIndex = -1; + } + + element.focus(); + } + }, false); + } +})(); \ No newline at end of file diff --git a/languages/readme.txt b/languages/readme.txt new file mode 100644 index 0000000..4b1570f --- /dev/null +++ b/languages/readme.txt @@ -0,0 +1,7 @@ +Place your theme language files in this directory. + +Please visit the following links to learn more about translating WordPress themes: + +https://make.wordpress.org/polyglots/teams/ +https://developer.wordpress.org/themes/functionality/localization/ +https://developer.wordpress.org/reference/functions/load_theme_textdomain/ diff --git a/phpcs.xml.dist b/phpcs.xml.dist index abeb9b9..afaf87a 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -8,6 +8,14 @@ <!-- Set a description for this ruleset. --> <description>A custom set of code standard rules to check for WordPress themes.</description> + + <!-- + ############################################################################# + COMMAND LINE ARGUMENTS + https://github.com/squizlabs/PHP_CodeSniffer/wiki/Annotated-ruleset.xml + ############################################################################# + --> + <!-- Pass some flags to PHPCS: p flag: Show progress of the run. s flag: Show sniff codes in all reports. @@ -16,21 +24,31 @@ --> <arg value="psvn"/> + <!-- Check up to 8 files simultanously. --> + <arg name="parallel" value="8"/> + <!-- Only check the PHP, CSS and SCSS files. JS files are checked separately with ESLint. --> <arg name="extensions" value="php,css,scss/css"/> <!-- Check all files in this directory and the directories below it. --> - <file>.</file> + <file>./dev/</file> + <rule ref="WordPress"/> <rule ref="WordPress-Core" /> <rule ref="WordPress-Docs" /> <rule ref="WordPress-Extra" /> + <!-- + ############################################################################# + SNIFF SPECIFIC CONFIGURATION + ############################################################################# + --> + <!-- Verify that the text_domain is set to the desired text-domain. Multiple valid text domains can be provided as a comma-delimited list. --> <rule ref="WordPress.WP.I18n"> <properties> - <property name="text_domain" type="array" value="travel,default" /> + <property name="text_domain" type="array" value="travel"/> </properties> </rule> @@ -39,16 +57,23 @@ <rule ref="WordPress.Files.FileName"> <properties> <property name="strict_class_file_names" value="false" /> - <property name="is_theme" value="true" /> + <property name="is_theme" value="true"/> </properties> </rule> - <!-- Verify that no WP functions are used which are deprecated or have been removed. + <!-- Set the minimum supported WP version. This is used by several sniffs. The minimum version set here should be in line with the minimum WP version as set in the "Requires at least" tag in the readme.txt file. --> - <rule ref="WordPress.WP.DeprecatedFunctions"> + <config name="minimum_supported_wp_version" value="4.5"/> + + <rule ref="WordPress.Arrays.MultipleStatementAlignment"> <properties> - <property name="minimum_supported_version" value="4.0" /> + <!-- No need to adjust alignment of large arrays when the item with the largest key is removed. --> + <property name="exact" value="false"/> + <!-- Don't align multi-line items if ALL items in the array are multi-line. --> + <property name="alignMultilineItems" value="!=100"/> + <!-- Array assignment operator should always be on the same line as the array key. --> + <property name="ignoreNewlines" value="false"/> </properties> </rule> @@ -58,5 +83,42 @@ <exclude-pattern>*/node_modules/*</exclude-pattern> <exclude-pattern>*/vendor/*</exclude-pattern> - <exclude-pattern>*/html/*</exclude-pattern> + + <!-- + ############################################################################# + USE THE PHPCompatibility RULESET + ############################################################################# + --> + + + <config name="testVersion" value="5.2-99.0"/> + <rule ref="PHPCompatibility"> + <!-- Whitelist PHP native classes, interfaces, functions and constants which + are back-filled by WP. + Based on: + * /wp-includes/compat.php + * /wp-includes/random_compat/random.php + --> + <exclude name="PHPCompatibility.PHP.NewClasses.errorFound"/> + <exclude name="PHPCompatibility.PHP.NewClasses.typeerrorFound"/> + + <exclude name="PHPCompatibility.PHP.NewConstants.json_pretty_printFound"/> + <exclude name="PHPCompatibility.PHP.NewConstants.php_version_idFound"/> + + <exclude name="PHPCompatibility.PHP.NewFunctions.hash_equalsFound"/> + <exclude name="PHPCompatibility.PHP.NewFunctions.json_last_error_msgFound"/> + <exclude name="PHPCompatibility.PHP.NewFunctions.random_intFound"/> + <exclude name="PHPCompatibility.PHP.NewFunctions.random_bytesFound"/> + <exclude name="PHPCompatibility.PHP.NewFunctions.array_replace_recursiveFound"/> + + <exclude name="PHPCompatibility.PHP.NewInterfaces.jsonserializableFound"/> + </rule> + + <!-- Whitelist the WP Core mysql_to_rfc3339() function. --> + <rule ref="PHPCompatibility.PHP.RemovedExtensions"> + <properties> + <property name="functionWhitelist" type="array" value="mysql_to_rfc3339"/> + </properties> + </rule> + </ruleset> diff --git a/pluggable/custom-header.php b/pluggable/custom-header.php new file mode 100644 index 0000000..e2f35a2 --- /dev/null +++ b/pluggable/custom-header.php @@ -0,0 +1,76 @@ +<?php +/** + * Sample implementation of the Custom Header feature + * + * You can add an optional custom header image to header.php like so ... + * + * <?php the_header_image_tag(); ?> + * + * @link https://developer.wordpress.org/themes/functionality/custom-headers/ + * + * @package WPAMPTheme + */ + +/** + * Set up the WordPress core custom header feature. + * + * @uses travel_header_style() + */ +function travel_custom_header_setup() { + add_theme_support( + 'custom-header', apply_filters( + 'travel_custom_header_args', array( + 'default-image' => '', + 'default-text-color' => '000000', + 'width' => 1000, + 'height' => 250, + 'flex-height' => true, + 'wp-head-callback' => 'travel_header_style', + ) + ) + ); +} +add_action( 'after_setup_theme', 'travel_custom_header_setup' ); + +if ( ! function_exists( 'travel_header_style' ) ) : + /** + * Styles the header image and text displayed on the blog. + * + * @see travel_custom_header_setup(). + */ + function travel_header_style() { + $header_text_color = get_header_textcolor(); + + /* + * If no custom options for text are set, let's bail. + * get_header_textcolor() options: Any hex value, 'blank' to hide text. Default: add_theme_support( 'custom-header' ). + */ + if ( get_theme_support( 'custom-header', 'default-text-color' ) === $header_text_color ) { + return; + } + + // If we get this far, we have custom styles. Let's do this. + ?> + <style type="text/css"> + <?php + // Has the text been hidden? + if ( ! display_header_text() ) : + ?> + .site-title, + .site-description { + position: absolute; + clip: rect(1px, 1px, 1px, 1px); + } + <?php + // If the user has set a custom color for the text use that. + else : + ?> + .site-title a, + .site-description { + color: #<?php echo esc_attr( $header_text_color ); ?>; + } + <?php endif; ?> + </style> + <?php + } +endif; diff --git a/sidebar.php b/sidebar.php new file mode 100644 index 0000000..ee9bfcf --- /dev/null +++ b/sidebar.php @@ -0,0 +1,19 @@ +<?php +/** + * The sidebar containing the main widget area + * + * @link https://developer.wordpress.org/themes/basics/template-files/#template-partials + * + * @package _s + */ + +if ( ! is_active_sidebar( 'sidebar-1' ) ) { + return; +} +?> + +<?php wp_print_styles( array( 'travel-sidebar' ) ); ?> +<?php wp_print_styles( array( 'travel-widgets' ) ); ?> +<aside id="secondary" class="primary-sidebar widget-area"> + <?php dynamic_sidebar( 'sidebar-1' ); ?> +</aside><!-- #secondary --> diff --git a/style.css b/style.css index d9e443a..d190405 100644 --- a/style.css +++ b/style.css @@ -13,5 +13,893 @@ Tags: custom-background, custom-logo, custom-menu, featured-images, threaded-com This theme, like WordPress, is licensed under the GPL. Use it to make something cool, have fun, and share what you've learned with others. -This stylesheet is intentionally left blank. +CSS normalization based in part on normalize.css by +Nicolas Gallagher and Jonathan Neal http://necolas.github.io/normalize.css/ */ +/*-------------------------------------------------------------- +>>> TABLE OF CONTENTS: +---------------------------------------------------------------- +# Normalize +# Accessibility +# Layout +# Typography +# Elements +# Links +# Forms +# Header + # Main navigation menu +# Content navigation +# Footer +# Infinite scroll +--------------------------------------------------------------*/ +/*-------------------------------------------------------------- +# Normalize +--------------------------------------------------------------*/ +/*! normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */ + +/* Document + ========================================================================== */ + +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in iOS. + */ + + html { + line-height: 1.15; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/* Sections + ========================================================================== */ + +/** + * Remove the margin in all browsers. + */ + +body { + margin: 0; +} + +link { + display: none; +} + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/* Grouping content + ========================================================================== */ + +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ + +hr { + -webkit-box-sizing: content-box; + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +pre { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Remove the gray background on active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * 1. Remove the bottom border in Chrome 57- + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ + +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; /* 2 */ /* phpcs:ignore */ +} + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ + +b, +strong { + font-weight: bolder; +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +code, +kbd, +samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/** + * Add the correct font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove the border on images inside links in IE 10. + */ + +img { + border-style: none; +} + +/* Forms + ========================================================================== */ + +/** + * 1. Change the font styles in all browsers. + * 2. Remove the margin in Firefox and Safari. + */ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ + +button, +input { /* 1 */ + overflow: visible; +} + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ + +button, +select { /* 1 */ + text-transform: none; +} + +/** + * Correct the inability to style clickable types in iOS and Safari. + */ + +button, +[type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; +} + +/** + * Remove the inner border and padding in Firefox. + */ + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** + * Restore the focus styles unset by the previous rule. + */ + +button:-moz-focusring, +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** + * Correct the padding in Firefox. + */ + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ + +legend { + -webkit-box-sizing: border-box; + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} + +/** + * Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ + +progress { + vertical-align: baseline; +} + +/** + * Remove the default vertical scrollbar in IE 10+. + */ + +textarea { + overflow: auto; +} + +/** + * 1. Add the correct box sizing in IE 10. + * 2. Remove the padding in IE 10. + */ + +[type="checkbox"], +[type="radio"] { + -webkit-box-sizing: border-box; + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ + +[type="search"] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/** + * Remove the inner padding in Chrome and Safari on macOS. + */ + +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* Interactive + ========================================================================== */ + +/* + * Add the correct display in Edge, IE 10+, and Firefox. + */ + +details { + display: block; +} + +/* + * Add the correct display in all browsers. + */ + +summary { + display: list-item; +} + +/* Misc + ========================================================================== */ + +/** + * Add the correct display in IE 10+. + */ + +template { + display: none; +} + +/** + * Add the correct display in IE 10. + */ + +[hidden] { + display: none; +} + +/*-------------------------------------------------------------- +# Accessibility +--------------------------------------------------------------*/ +/* Text meant only for screen readers. */ +.screen-reader-text { + clip: rect(1px, 1px, 1px, 1px); + position: absolute !important; + height: 1px; + width: 1px; + overflow: hidden; + word-wrap: normal !important; + /* Many screen reader and browser combinations announce broken words as they would appear visually. */ +} + +.screen-reader-text:focus { + background-color: #f1f1f1; + border-radius: 3px; + -webkit-box-shadow: 0 0 2px 2px rgba(0, 0, 0, .6); + box-shadow: 0 0 2px 2px rgba(0, 0, 0, .6); + clip: auto !important; + color: #21759b; + display: block; + font-size: 14px; + font-size: 0.875rem; + font-weight: bold; + height: auto; + left: 5px; + line-height: normal; + padding: 15px 23px 14px; + text-decoration: none; + top: 5px; + width: auto; + z-index: 100000; + /* Above WP toolbar. */ +} + +/* Do not show the outline on the skip link target. */ +#primary[tabindex="-1"]:focus { + outline: 0; +} + +/*-------------------------------------------------------------- +# Layouts +--------------------------------------------------------------*/ +.site { + margin: 0 auto; + max-width: 100%; +} + +@media screen and (min-width: 60em) { + .has-sidebar .site { + margin: 0 1em; + display: grid; + grid-template-columns: 3fr 1fr; + grid-gap: 2rem; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + } + + .site-header { + grid-column: span 2; + } + + .site-main { + grid-column: 1; + min-width: 0; + } + + .primary-sidebar { + grid-column: 2; + min-width: 0; + } + + .site-footer { + grid-column: span 2; + } +} + +/*-------------------------------------------------------------- +# Typography +--------------------------------------------------------------*/ +body, +button, +input, +select, +optgroup, +textarea { + color: #333; + font-family: 'Crimson Text', serif; + font-size: 20px; + font-size: 1.25rem; + line-height: 1.4; +} + +h1, h2, h3, h4, h5, h6 { + font-family: 'Roboto Condensed', sans-serif; + color: #32373c; + clear: both; +} + +.entry-header h1.entry-title { + font-size: 32px; + font-size: 2rem; + line-height: 1.4; + margin: 1em 0; +} + +dfn, cite, em, i { + font-style: italic; +} + +blockquote { + margin: 0 1.5em; +} + +address { + margin: 0 0 1.5em; +} + +pre { + background: #eee; + font-family: "Courier 10 Pitch", Courier, monospace; + font-size: 15px; + font-size: 0.9375rem; + line-height: 1.6; + margin-bottom: 1.6em; + max-width: 100%; + overflow: auto; + padding: 1.6em; +} + +code, kbd, tt, var { + font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; + font-size: 15px; + font-size: 0.9375rem; +} + +abbr, acronym { + border-bottom: 1px dotted #666; + cursor: help; +} + +mark, ins { + background: #fff9c0; + text-decoration: none; +} + +big { + font-size: 125%; +} + +/*-------------------------------------------------------------- +# Elements +--------------------------------------------------------------*/ +html { + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +*, +*:before, +*:after { + /* Inherit box-sizing to make it easier to change the property for components that leverage other behavior; see http://css-tricks.com/inheriting-box-sizing-probably-slightly-better-best-practice/ */ + -webkit-box-sizing: inherit; + box-sizing: inherit; +} + +body { + background: #fff; + /* Fallback for when there is no custom background color defined. */ } + +blockquote, q { + quotes: "" ""; +} + +hr { + background-color: #ccc; + border: 0; + height: 1px; + margin-bottom: 1.5em; +} + +ul, ol { + margin: 0 0 1.5em 3em; +} + +ul { + list-style: disc; +} + +ol { + list-style: decimal; +} + +li > ul, +li > ol { + margin-bottom: 0; + margin-left: 1.5em; +} + +dt { + font-weight: bold; +} + +dd { + margin: 0 1.5em 1.5em; +} + +img { + display: block; + height: auto; + max-width: 100%; +} + +figure { + /* Extra wide images within figure tags don't overflow the content area. */ + margin: .5em 0; +} + +table { + margin: 0 0 1.5em; + width: 100%; +} + +/*-------------------------------------------------------------- +# Links +--------------------------------------------------------------*/ +a { + color: #0073aa; +} + +a:visited { + color: #333; +} + +a:hover, a:focus, a:active { + color: #00a0d2; +} + +a:focus { + outline: thin dotted; +} + +a:hover, a:active { + outline: 0; +} + +/*-------------------------------------------------------------- +# Forms +--------------------------------------------------------------*/ +button, +input[type="button"], +input[type="reset"], +input[type="submit"] { + border: 1px solid; + border-color: #ccc #ccc #bbb; + border-radius: 3px; + background: #e6e6e6; + color: rgba(0, 0, 0, .8); + font-size: 12px; + font-size: 0.75rem; + line-height: 1; + padding: .6em 1em .4em; +} + +button:hover, +input[type="button"]:hover, +input[type="reset"]:hover, +input[type="submit"]:hover { + border-color: #ccc #bbb #aaa; +} + +button:active, button:focus, +input[type="button"]:active, +input[type="button"]:focus, +input[type="reset"]:active, +input[type="reset"]:focus, +input[type="submit"]:active, +input[type="submit"]:focus { + border-color: #aaa #bbb #bbb; +} + +input[type="text"], +input[type="email"], +input[type="url"], +input[type="password"], +input[type="search"], +input[type="number"], +input[type="tel"], +input[type="range"], +input[type="date"], +input[type="month"], +input[type="week"], +input[type="time"], +input[type="datetime"], +input[type="datetime-local"], +input[type="color"], +textarea { + color: #666; + border: 1px solid #ccc; + border-radius: 3px; + padding: 3px; +} + +input[type="text"]:focus, +input[type="email"]:focus, +input[type="url"]:focus, +input[type="password"]:focus, +input[type="search"]:focus, +input[type="number"]:focus, +input[type="tel"]:focus, +input[type="range"]:focus, +input[type="date"]:focus, +input[type="month"]:focus, +input[type="week"]:focus, +input[type="time"]:focus, +input[type="datetime"]:focus, +input[type="datetime-local"]:focus, +input[type="color"]:focus, +textarea:focus { + color: #111; +} + +select { + border: 1px solid #ccc; +} + +textarea { + width: 100%; +} + +/*-------------------------------------------------------------- +# Header +--------------------------------------------------------------*/ +.site-branding { + text-align: center; + margin: 60px 0 1.75em; +} + +.site-title { + margin: .4375em 1em 0; + font-family: 'Roboto Condensed', sans-serif; + font-size: 38px; + font-weight: bold; + line-height: 1.2; + color: #333332; +} + +.site-title a { + text-decoration: none; + color: inherit; +} + +.site-description { + margin: .4375em 0 0; + font-family: 'Roboto Condensed', sans-serif; + font-size: 17px; + font-weight: inherit; + line-height: 1.4; + word-wrap: break-word; + color: #929292; +} + +/*-------------------------------------------------------------- +## Main navigation menu +--------------------------------------------------------------*/ +.main-navigation { + clear: both; + display: block; + margin: 0 auto; + padding: 0 1em; + max-width: 720px; /* Fallback for older browsers. */ + max-width: 45rem; + font-family: 'Roboto Condensed', sans-serif; +} + +.main-navigation ul { + display: none; + list-style: none; + margin: 0; + padding-left: 0; +} + +.main-navigation ul ul { + -webkit-box-shadow: 0 3px 3px rgba(0, 0, 0, .2); + box-shadow: 0 3px 3px rgba(0, 0, 0, .2); + float: left; + position: absolute; + top: 100%; + left: -999em; + z-index: 99999; +} + +.main-navigation ul ul ul { + left: -999em; + top: 0; +} + +.main-navigation ul ul li:hover > ul, +.main-navigation ul ul li.focus > ul { + left: 100%; +} + +.main-navigation ul ul a { + width: 200px; +} + +.main-navigation ul li:hover > ul, +.main-navigation ul li.focus > ul { + display: block; + left: auto; +} + +.main-navigation li { + position: relative; +} + +.main-navigation a { + display: block; + text-decoration: none; +} + +@media screen and (max-width: 37.5em) { + /* Small menu. */ + .menu-toggle, + .main-navigation.toggled ul { + display: block; + margin: 0 auto; + } +} + +@media screen and (min-width: 37.5em) { + .menu-toggle { + display: none; + } + + .main-navigation ul { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + } + + .main-navigation a { + padding: 0 .5em; + } +} + +/*-------------------------------------------------------------- +# Content navigation +--------------------------------------------------------------*/ +.site-main .comment-navigation, +.site-main .posts-navigation, +.site-main .post-navigation { + border-bottom: 1px solid #111; + margin: 0 auto 60px; + max-width: 720px; + overflow: hidden; + padding-bottom: 60px; +} + +.nav-links { + display: -webkit-box; + display: -ms-flexbox; + display: flex; +} + +.comment-navigation .nav-previous, +.posts-navigation .nav-previous, +.post-navigation .nav-previous { + width: 50%; + -webkit-box-flex: 1; + -ms-flex: 1 0 50%; + flex: 1 0 50%; +} + +.comment-navigation .nav-next, +.posts-navigation .nav-next, +.post-navigation .nav-next { + text-align: end; + -webkit-box-flex: 1; + -ms-flex: 1 0 50%; + flex: 1 0 50%; +} + +.post-navigation-sub span { + color: #333; + text-decoration: none; + display: inline-block; +} + +/*-------------------------------------------------------------- +# Footer +--------------------------------------------------------------*/ +.site-footer { + margin: 1em 0; + opacity: 0.5; +} + +/*-------------------------------------------------------------- +# Infinite scroll +--------------------------------------------------------------*/ +/* Globally hidden elements when Infinite Scroll is supported and in use. */ +.infinite-scroll .posts-navigation, +.infinite-scroll.neverending .site-footer { + /* Theme Footer (when set to scrolling) */ + display: none; +} + +/* When Infinite Scroll has reached its end we need to re-display elements that were hidden (via .neverending) before. */ +.infinity-end.neverending .site-footer { + display: block; +} diff --git a/template-parts/content-attachment.php b/template-parts/content-attachment.php new file mode 100644 index 0000000..8299298 --- /dev/null +++ b/template-parts/content-attachment.php @@ -0,0 +1,60 @@ +<?php +/** + * Template part for displaying attachment posts + * + * @link https://codex.wordpress.org/Template_Hierarchy + * + * @package WPAMPTheme + */ + +?> + +<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>> + + <header class="entry-header"> + <?php + the_title( '<h1 class="entry-title">', '</h1>' ); + ?> + <div class="entry-meta"> + <?php + travel_posted_on(); + travel_posted_by(); + travel_attachment_in( $post ); + ?> + </div><!-- .entry-meta --> + + </header><!-- .entry-header --> + + <div class="entry-content"> + + <figure class="attachment-image"> + <?php echo wp_get_attachment_image( get_the_ID(), 'original' ); ?> + <figcaption> + <?php the_excerpt(); ?> + </figcaption> + </figure><!-- .attachment-image --> + + <?php + remove_filter( 'the_content', 'prepend_attachment' ); + the_content(); + ?> + + </div><!-- .entry-content --> + + <footer class="entry-footer"> + <?php travel_entry_footer(); ?> + </footer><!-- .entry-footer --> +</article><!-- #post-<?php the_ID(); ?> --> + +<?php + + +// If the attachment is attached to a post, try linking to other attachments on the same post. +if ( ! empty( $post->post_parent ) ) : + travel_the_attachment_navigation(); +endif; + +// If comments are open or we have at least one comment, load up the comment template. +if ( comments_open() || get_comments_number() ) : + comments_template(); +endif; diff --git a/template-parts/content-none.php b/template-parts/content-none.php new file mode 100644 index 0000000..b84ecc9 --- /dev/null +++ b/template-parts/content-none.php @@ -0,0 +1,54 @@ +<?php +/** + * Template part for displaying a message that posts cannot be found + * + * @link https://codex.wordpress.org/Template_Hierarchy + * + * @package WPAMPTheme + */ + +?> +<section class="no-results not-found"> + <header class="page-header"> + <h1 class="page-title"><?php esc_html_e( 'Nothing Found', 'travel' ); ?></h1> + </header><!-- .page-header --> + + <div class="page-content"> + <?php + if ( is_home() && current_user_can( 'publish_posts' ) ) : + ?> + + <p> + <?php + printf( + wp_kses( + /* translators: 1: link to WP admin new post page. */ + __( 'Ready to publish your first post? <a href="%1$s">Get started here</a>.', 'travel' ), + array( + 'a' => array( + 'href' => array(), + ), + ) + ), + esc_url( admin_url( 'post-new.php' ) ) + ); + ?> + </p> + + <?php elseif ( is_search() ) : ?> + + <p><?php esc_html_e( 'Sorry, but nothing matched your search terms. Please try again with some different keywords.', 'travel' ); ?></p> + <?php + get_search_form(); + + else : + ?> + + <p><?php esc_html_e( 'It seems we can’t find what you’re looking for. Perhaps searching can help.', 'travel' ); ?></p> + <?php + get_search_form(); + + endif; + ?> + </div><!-- .page-content --> +</section><!-- .no-results --> diff --git a/template-parts/content-page.php b/template-parts/content-page.php new file mode 100644 index 0000000..11f0bf7 --- /dev/null +++ b/template-parts/content-page.php @@ -0,0 +1,62 @@ +<?php +/** + * Template part for displaying page content in page.php + * + * @link https://codex.wordpress.org/Template_Hierarchy + * + * @package WPAMPTheme + */ + +?> + +<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>> + <header class="entry-header"> + <?php the_title( '<h1 class="entry-title">', '</h1>' ); ?> + </header><!-- .entry-header --> + + <?php travel_post_thumbnail(); ?> + + <div class="entry-content"> + <?php + the_content(); + + wp_link_pages( + array( + 'before' => '<div class="page-links">' . esc_html__( 'Pages:', 'travel' ), + 'after' => '</div>', + ) + ); + ?> + </div><!-- .entry-content --> + + <?php if ( get_edit_post_link() ) : ?> + <footer class="entry-footer"> + <?php + edit_post_link( + sprintf( + wp_kses( + /* translators: %s: Name of current post. Only visible to screen readers */ + __( 'Edit <span class="screen-reader-text">%s</span>', 'travel' ), + array( + 'span' => array( + 'class' => array(), + ), + ) + ), + get_the_title() + ), + '<span class="edit-link">', + '</span>' + ); + ?> + </footer><!-- .entry-footer --> + <?php endif; ?> +</article><!-- #post-<?php the_ID(); ?> --> + +<?php +if ( is_singular() ) : + // If comments are open or we have at least one comment, load up the comment template. + if ( comments_open() || get_comments_number() ) : + comments_template(); + endif; +endif; diff --git a/template-parts/content-search.php b/template-parts/content-search.php new file mode 100644 index 0000000..a863011 --- /dev/null +++ b/template-parts/content-search.php @@ -0,0 +1,35 @@ +<?php +/** + * Template part for displaying results in search pages + * + * @link https://codex.wordpress.org/Template_Hierarchy + * + * @package WPAMPTheme + */ + +?> + +<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>> + <header class="entry-header"> + <?php the_title( sprintf( '<h2 class="entry-title"><a href="%s" rel="bookmark">', esc_url( get_permalink() ) ), '</a></h2>' ); ?> + + <?php if ( 'post' === get_post_type() ) : ?> + <div class="entry-meta"> + <?php + travel_posted_on(); + travel_posted_by(); + ?> + </div><!-- .entry-meta --> + <?php endif; ?> + </header><!-- .entry-header --> + + <?php travel_post_thumbnail(); ?> + + <div class="entry-summary"> + <?php the_excerpt(); ?> + </div><!-- .entry-summary --> + + <footer class="entry-footer"> + <?php travel_entry_footer(); ?> + </footer><!-- .entry-footer --> +</article><!-- #post-<?php the_ID(); ?> --> diff --git a/template-parts/content.php b/template-parts/content.php new file mode 100644 index 0000000..df4e3b6 --- /dev/null +++ b/template-parts/content.php @@ -0,0 +1,80 @@ +<?php +/** + * Template part for displaying posts + * + * @link https://codex.wordpress.org/Template_Hierarchy + * + * @package WPAMPTheme + */ + +?> + +<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>> + <header class="entry-header"> + <?php + if ( is_singular() ) : + the_title( '<h1 class="entry-title">', '</h1>' ); + else : + the_title( '<h2 class="entry-title"><a href="' . esc_url( get_permalink() ) . '" rel="bookmark">', '</a></h2>' ); + endif; + + if ( 'post' === get_post_type() ) : + ?> + <div class="entry-meta"> + <?php + travel_posted_on(); + travel_posted_by(); + ?> + </div><!-- .entry-meta --> + <?php + endif; + ?> + </header><!-- .entry-header --> + + <?php travel_post_thumbnail(); ?> + + <div class="entry-content"> + <?php + the_content( + sprintf( + wp_kses( + /* translators: %s: Name of current post. Only visible to screen readers */ + __( 'Continue reading<span class="screen-reader-text"> "%s"</span>', 'travel' ), + array( + 'span' => array( + 'class' => array(), + ), + ) + ), + get_the_title() + ) + ); + + wp_link_pages( + array( + 'before' => '<div class="page-links">' . esc_html__( 'Pages:', 'travel' ), + 'after' => '</div>', + ) + ); + ?> + </div><!-- .entry-content --> + + <footer class="entry-footer"> + <?php travel_entry_footer(); ?> + </footer><!-- .entry-footer --> +</article><!-- #post-<?php the_ID(); ?> --> + +<?php +if ( is_singular() ) : + the_post_navigation( + array( + 'prev_text' => '<div class="post-navigation-sub"><span>' . esc_html__( 'Previous:', 'travel' ) . '</span></div>%title', + 'next_text' => '<div class="post-navigation-sub"><span>' . esc_html__( 'Next:', 'travel' ) . '</span></div>%title', + ) + ); + + // If comments are open or we have at least one comment, load up the comment template. + if ( comments_open() || get_comments_number() ) : + comments_template(); + endif; +endif;