should_render() ) { return; } wp_enqueue_style( 'birchtoad', BIRCHTOAD_URL . 'assets/css/birchtoad.css', array(), self::asset_version( 'assets/css/birchtoad.css' ) ); wp_enqueue_script( 'birchtoad', BIRCHTOAD_URL . 'assets/js/birchtoad.js', array(), self::asset_version( 'assets/js/birchtoad.js' ), true ); wp_add_inline_script( 'birchtoad', 'window.birchtoadConfig = ' . wp_json_encode( $this->config() ) . ';', 'before' ); /** * Fires after the core assets are enqueued, for the paid build to add its own. */ do_action( 'birchtoad_enqueued' ); } /** * A file's modification time, as a version string. * * Uses file_exists rather than a silenced filemtime: no silenced-error suppression ships. * * @param string $relative Path relative to the plugin root. * @return string */ public static function asset_version( $relative ) { $path = BIRCHTOAD_DIR . $relative; if ( file_exists( $path ) ) { return (string) filemtime( $path ); } return BIRCHTOAD_VERSION; } /** * The configuration object the engine reads. * * @return array */ public function config() { $features = array(); foreach ( BirchToad_Features::available() as $key => $feature ) { if ( ! BirchToad_Settings::feature_on( $key ) ) { continue; } $entry = array( 'k' => $key, 'g' => $feature['group'], 't' => $feature['type'], 'l' => $feature['label'], ); if ( ! empty( $feature['desc'] ) ) { $entry['d'] = $feature['desc']; } if ( ! empty( $feature['range'] ) ) { $entry['r'] = $feature['range']; } if ( ! empty( $feature['choices'] ) ) { $entry['c'] = $feature['choices']; $entry['def'] = isset( $feature['default'] ) ? $feature['default'] : ''; } if ( ! empty( $feature['links'] ) ) { $entry['links'] = $feature['links']; } $features[] = $entry; } $groups = array(); foreach ( BirchToad_Features::group_labels() as $key => $labels ) { $groups[] = array( 'k' => $key, 'l' => $labels['title'], 'd' => $labels['desc'], ); } $title = BirchToad_Settings::get( 'widget', 'header_title', '' ); $config = array( // Direction is a top-level flag on purpose. Anything appended to outside the // panel root must carry its own dir attribute, or logical CSS properties resolve // against the page's direction instead of the panel's. 'rtl' => is_rtl(), 'accent' => BirchToad_Settings::get( 'widget', 'accent', '#2F57F0' ), 'pos' => BirchToad_Settings::get( 'widget', 'position', 'bottom-right' ), 'ox' => (int) BirchToad_Settings::get( 'widget', 'offset_x', 20 ), 'oy' => (int) BirchToad_Settings::get( 'widget', 'offset_y', 20 ), 'size' => BirchToad_Settings::get( 'widget', 'size', 'medium' ), 'shape' => BirchToad_Settings::get( 'widget', 'shape', 'circle' ), 'icon' => BirchToad_Settings::get( 'widget', 'icon', 'birchtoad' ), 'title' => $title ? $title : __( 'Accessibility Adjustments', 'birchtoad' ), 'openOnLoad' => (bool) BirchToad_Settings::get( 'widget', 'open_on_load', false ), 'hideMobile' => (bool) BirchToad_Settings::get( 'widget', 'hide_on_mobile', false ), 'shortcut' => (bool) BirchToad_Settings::get( 'widget', 'shortcut', true ), 'credit' => (bool) BirchToad_Settings::get( 'widget', 'credit', false ), 'statement' => BirchToad_Statement::url(), 'groups' => $groups, 'features' => $features, 'i18n' => self::strings(), ); /** * Filters the engine configuration. * * @param array $config The config object. */ return apply_filters( 'birchtoad_js_config', $config ); } /** * Visitor-facing strings that are not feature labels. * * Every string here is visitor facing, so every one of them must also exist in the seed list * in tools/seed-visitor-po.py. A string added here and not there shows in English in every * bundled language. * * @return array */ public static function strings() { return array( 'open' => __( 'Open the accessibility toolbar', 'birchtoad' ), 'close' => __( 'Close', 'birchtoad' ), 'reset' => __( 'Reset Settings', 'birchtoad' ), 'statement' => __( 'Statement', 'birchtoad' ), 'hide' => __( 'Hide Interface', 'birchtoad' ), 'hideConfirm' => __( 'Hide the accessibility toolbar for this visit?', 'birchtoad' ), 'hideHint' => __( 'You can bring it back with Alt + Shift + A, or by reloading the page.', 'birchtoad' ), 'yes' => __( 'Yes, hide it', 'birchtoad' ), 'cancel' => __( 'Cancel', 'birchtoad' ), 'search' => __( 'Search an adjustment', 'birchtoad' ), 'noResults' => __( 'Nothing matches that search.', 'birchtoad' ), 'on' => __( 'On', 'birchtoad' ), 'off' => __( 'Off', 'birchtoad' ), 'default' => __( 'Default', 'birchtoad' ), 'language' => __( 'Language', 'birchtoad' ), 'creditText' => __( 'Accessibility by BirchToad', 'birchtoad' ), 'resetDone' => __( 'All adjustments were reset.', 'birchtoad' ), 'increase' => __( 'Increase', 'birchtoad' ), 'decrease' => __( 'Decrease', 'birchtoad' ), ); } /** * Prints the trigger button and the empty panel root. * * The trigger is real markup rather than something the engine creates, so it is a focusable * button in the tab order from the first paint. * * @return void */ public function render() { if ( ! $this->should_render() ) { return; } $classes = array( 'birchtoad-trigger', 'birchtoad-pos-' . BirchToad_Settings::get( 'widget', 'position', 'bottom-right' ), 'birchtoad-size-' . BirchToad_Settings::get( 'widget', 'size', 'medium' ), 'birchtoad-shape-' . BirchToad_Settings::get( 'widget', 'shape', 'circle' ), ); $label = BirchToad_Settings::get( 'widget', 'trigger_label', '' ); if ( ! $label ) { $label = __( 'Open the accessibility toolbar', 'birchtoad' ); } printf( '', esc_attr( implode( ' ', $classes ) ), esc_attr( $label ), esc_attr( is_rtl() ? 'rtl' : 'ltr' ), esc_attr( BirchToad_Settings::get( 'widget', 'accent', '#2F57F0' ) ), (int) BirchToad_Settings::get( 'widget', 'offset_x', 20 ), (int) BirchToad_Settings::get( 'widget', 'offset_y', 20 ), wp_kses( self::icon_svg(), self::svg_allowed() ) ); printf( '
', esc_attr( is_rtl() ? 'rtl' : 'ltr' ), esc_attr( BirchToad_Settings::get( 'widget', 'accent', '#2F57F0' ) ) ); } /** * The path data behind each built-in glyph. * * The BirchToad mark is not here: it lives in assets/img/mark.svg so the real brand asset * stays the single source. * * @return array Icon key to inner SVG markup. */ public static function icon_paths() { return array( // No stick figure. The person glyph is the one piece of accessibility // iconography that reads as "disabled people over there" rather than // "controls for you", and every overlay on the market uses it. 'contrast' => '', 'sliders' => '', 'text' => '', 'wheelchair' => '', 'eye' => '', ); } /** * One named glyph, whichever one is asked for. * * Separate from icon_svg() so the settings screen can draw every choice, not only the saved * one. A picker that cannot draw the options is a list of words. * * @param string $icon Icon key. * @return string */ public static function icon_svg_for( $icon ) { if ( 'none' === $icon ) { return ''; } $icons = self::icon_paths(); if ( isset( $icons[ $icon ] ) ) { return ''; } // The BirchToad mark. Kept as its own file so the real brand asset stays the source. $mark = BIRCHTOAD_DIR . 'assets/img/mark.svg'; if ( file_exists( $mark ) ) { $svg = file_get_contents( $mark ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- Reading a bundled static asset, not a remote request. if ( $svg ) { return str_replace( '