initial
This commit is contained in:
+652
@@ -0,0 +1,652 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [0.14.34] - 2026-06-29
|
||||
### Changed
|
||||
- Update dependencies. [#50001]
|
||||
|
||||
## [0.14.33] - 2026-06-25
|
||||
### Changed
|
||||
- Update package dependencies. [#49831]
|
||||
|
||||
## [0.14.32] - 2026-06-22
|
||||
### Changed
|
||||
- Update package dependencies. [#49631] [#49691] [#49757]
|
||||
|
||||
## [0.14.31] - 2026-06-15
|
||||
### Changed
|
||||
- Update package dependencies. [#49273]
|
||||
|
||||
## [0.14.30] - 2026-06-08
|
||||
### Changed
|
||||
- Update dependencies. [#49354]
|
||||
|
||||
## [0.14.29] - 2026-06-01
|
||||
### Fixed
|
||||
- Prevent various PHP warnings. [#49293]
|
||||
|
||||
## [0.14.28] - 2026-05-25
|
||||
### Changed
|
||||
- Update package dependencies. [#48405]
|
||||
|
||||
## [0.14.27] - 2026-05-19
|
||||
### Changed
|
||||
- Update package dependencies. [#48695]
|
||||
|
||||
## [0.14.26] - 2026-05-11
|
||||
### Changed
|
||||
- Update dependencies. [#46383]
|
||||
|
||||
## [0.14.25] - 2026-05-04
|
||||
### Changed
|
||||
- Internal: No longer require automattic/jetpack-changelogger as a per-project dev dependency. [#48225]
|
||||
|
||||
## [0.14.24] - 2026-04-27
|
||||
### Changed
|
||||
- Update package dependencies. [#48302]
|
||||
|
||||
## [0.14.23] - 2026-04-20
|
||||
### Changed
|
||||
- Update package dependencies. [#48106]
|
||||
|
||||
## [0.14.22] - 2026-04-09
|
||||
### Changed
|
||||
- Update package dependencies. [#47890]
|
||||
|
||||
## [0.14.21] - 2026-04-06
|
||||
### Changed
|
||||
- Update dependencies. [#46383]
|
||||
|
||||
## [0.14.20] - 2026-03-30
|
||||
### Changed
|
||||
- Update package dependencies. [#47818]
|
||||
|
||||
## [0.14.19] - 2026-03-23
|
||||
### Changed
|
||||
- Update package dependencies. [#47684]
|
||||
|
||||
## [0.14.18] - 2026-03-16
|
||||
### Changed
|
||||
- Update dependencies. [#47472]
|
||||
|
||||
## [0.14.17] - 2026-03-09
|
||||
### Changed
|
||||
- Update package dependencies. [#47496]
|
||||
|
||||
## [0.14.16] - 2026-02-26
|
||||
### Changed
|
||||
- Update package dependencies. [#47288] [#47300]
|
||||
- Use the new `Post_Media` `Images` class instead of `Jetpack_PostImages` for featured image fallbacks. [#47249]
|
||||
|
||||
## [0.14.15] - 2026-02-23
|
||||
### Changed
|
||||
- Update package dependencies. [#47173]
|
||||
|
||||
### Fixed
|
||||
- Social Menu: Remove Pocket sharing button. [#46879]
|
||||
|
||||
## [0.14.14] - 2026-02-16
|
||||
### Changed
|
||||
- Update package dependencies. [#47099]
|
||||
|
||||
## [0.14.13] - 2026-02-10
|
||||
### Changed
|
||||
- Update package dependencies. [#46936] [#47002]
|
||||
|
||||
## [0.14.12] - 2026-02-02
|
||||
### Changed
|
||||
- Update package dependencies. [#46854]
|
||||
|
||||
## [0.14.11] - 2026-01-26
|
||||
### Changed
|
||||
- Update dependencies. [#46383]
|
||||
|
||||
## [0.14.10] - 2026-01-19
|
||||
### Changed
|
||||
- Update package dependencies. [#46552] [#46647]
|
||||
|
||||
## [0.14.9] - 2026-01-12
|
||||
### Fixed
|
||||
- Add missing jetpack-blocks dependency required for `Blocks::is_fse_theme()` usage. [#46489]
|
||||
|
||||
## [0.14.8] - 2026-01-09
|
||||
### Changed
|
||||
- Update package dependencies. [#46456]
|
||||
|
||||
## [0.14.7] - 2025-12-22
|
||||
### Changed
|
||||
- Update dependencies. [#46381]
|
||||
|
||||
## [0.14.6] - 2025-12-15
|
||||
### Changed
|
||||
- Update dependencies. [#46271]
|
||||
|
||||
## [0.14.5] - 2025-12-08
|
||||
### Fixed
|
||||
- Ensure proper flags are used with `json_encode()`. [#46092]
|
||||
|
||||
## [0.14.4] - 2025-12-01
|
||||
### Changed
|
||||
- Update package dependencies. [#46143]
|
||||
|
||||
## [0.14.3] - 2025-11-18
|
||||
### Changed
|
||||
- Update package dependencies. [#45961]
|
||||
|
||||
## [0.14.2] - 2025-11-17
|
||||
### Changed
|
||||
- Update package dependencies. [#45915]
|
||||
|
||||
## [0.14.1] - 2025-11-03
|
||||
### Changed
|
||||
- Update dependencies. [#45664]
|
||||
|
||||
## [0.14.0] - 2025-10-20
|
||||
### Added
|
||||
- Add new Apple Podcasts logo. [#45436]
|
||||
- Add new Pocket Casts logo. [#45438] [#45485]
|
||||
|
||||
### Changed
|
||||
- Custom post types: Ensure features remain available when theme support is added. [#45407]
|
||||
- Reddit: Update logo to match new design. [#45437]
|
||||
- WooCommerce: Update logo to match recent redesign. [#45435]
|
||||
|
||||
## [0.13.22] - 2025-10-07
|
||||
### Fixed
|
||||
- Testimonials: Prevent warning when custom post type is not registered.
|
||||
|
||||
## [0.13.21] - 2025-10-06
|
||||
### Changed
|
||||
- Update package dependencies. [#45334]
|
||||
|
||||
## [0.13.20] - 2025-09-22
|
||||
### Changed
|
||||
- Update dependencies. [#44300]
|
||||
|
||||
## [0.13.19] - 2025-09-19
|
||||
### Changed
|
||||
- Update package dependencies. [#45173] [#45229]
|
||||
|
||||
## [0.13.18] - 2025-09-15
|
||||
### Changed
|
||||
- Update package dependencies. [#45127] [#45128]
|
||||
|
||||
### Fixed
|
||||
- Featured images: Fix disabling featured images in post preview [#45036]
|
||||
|
||||
## [0.13.17] - 2025-09-08
|
||||
### Changed
|
||||
- Update package dependencies. [#45027]
|
||||
|
||||
## [0.13.16] - 2025-08-25
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.13.15] - 2025-08-14
|
||||
### Changed
|
||||
- Update package dependencies. [#44701]
|
||||
|
||||
## [0.13.14] - 2025-08-11
|
||||
### Changed
|
||||
- Update package dependencies. [#44677]
|
||||
|
||||
### Fixed
|
||||
- Prevent PHP errors when directly accessing various files. [#44646]
|
||||
|
||||
## [0.13.13] - 2025-08-04
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.13.12] - 2025-07-28
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.13.11] - 2025-07-21
|
||||
### Changed
|
||||
- Update package dependencies. [#44356]
|
||||
|
||||
## [0.13.10] - 2025-07-14
|
||||
### Changed
|
||||
- Update dependencies. [#44229]
|
||||
|
||||
## [0.13.9] - 2025-07-07
|
||||
### Changed
|
||||
- Update package dependencies. [#44148] [#44151]
|
||||
|
||||
## [0.13.8] - 2025-06-30
|
||||
### Changed
|
||||
- Update dependencies. [#44061]
|
||||
|
||||
## [0.13.7] - 2025-06-23
|
||||
### Changed
|
||||
- Update dependencies. [#44002]
|
||||
- Update package dependencies. [#44020]
|
||||
|
||||
## [0.13.6] - 2025-06-16
|
||||
### Changed
|
||||
- Settings: Open support links in Help Center. [#43930]
|
||||
- Update package dependencies. [#43914]
|
||||
|
||||
## [0.13.5] - 2025-06-05
|
||||
### Changed
|
||||
- Update dependencies. [#43785]
|
||||
|
||||
## [0.13.4] - 2025-06-03
|
||||
### Changed
|
||||
- Update package dependencies. [#43734]
|
||||
|
||||
## [0.13.3] - 2025-06-02
|
||||
### Changed
|
||||
- Update dependencies. [#42876]
|
||||
|
||||
## [0.13.2] - 2025-05-26
|
||||
### Changed
|
||||
- Update package dependencies. [#43516] [#43578]
|
||||
|
||||
### Fixed
|
||||
- Featured Content: Prevent error if invalid taxonomy data is provided. [#43553]
|
||||
|
||||
## [0.13.1] - 2025-05-19
|
||||
### Changed
|
||||
- Update package dependencies. [#43398]
|
||||
|
||||
## [0.13.0] - 2025-05-12
|
||||
### Changed
|
||||
- Update package dependencies. [#43400]
|
||||
|
||||
### Removed
|
||||
- Remove Skype since the service no longer exists. [#43375]
|
||||
|
||||
## [0.12.1] - 2025-05-05
|
||||
### Changed
|
||||
- Update package dependencies. [#43326]
|
||||
|
||||
### Fixed
|
||||
- Linting: Do additional stylesheet cleanup. [#43247]
|
||||
|
||||
## [0.12.0] - 2025-04-28
|
||||
### Added
|
||||
- Featured Content: Add messaging to clarify that the tag name is case sensitive. [#43165]
|
||||
|
||||
### Changed
|
||||
- Update Phan baseline. [#43085]
|
||||
|
||||
### Fixed
|
||||
- Code: Remove unneeded `data:` URI components. [#43227]
|
||||
- Linting: Fix more Stylelint violations. [#43213]
|
||||
- Linting: Remove outdated vendor prefixes in stylesheets. [#43219]
|
||||
- Social Menus: Reorder SVGs to be alphabetic. [#41134]
|
||||
|
||||
## [0.11.8] - 2025-04-14
|
||||
### Changed
|
||||
- Social Menus: Update the Twitter sharing button to use the X logo. [#42813]
|
||||
|
||||
### Fixed
|
||||
- Linting: Update stylesheets to use WordPress rules for fonts. [#42928]
|
||||
- Linting: Use double colon notation for pseudo-element selectors. [#43019]
|
||||
|
||||
## [0.11.7] - 2025-04-07
|
||||
### Changed
|
||||
- Linting: First pass of style coding standards. [#42734]
|
||||
|
||||
## [0.11.6] - 2025-04-02
|
||||
### Changed
|
||||
- Update dependencies. [#42820]
|
||||
- Update package dependencies. [#42809]
|
||||
|
||||
## [0.11.5] - 2025-03-24
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.11.4] - 2025-03-18
|
||||
### Changed
|
||||
- Update package dependencies. [#42511]
|
||||
|
||||
## [0.11.3] - 2025-03-12
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.11.2] - 2025-03-10
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.11.1] - 2025-03-03
|
||||
### Added
|
||||
- Custom Content Types: Ensure script with initial state value is only added on Jetpack admin pages. [#42138]
|
||||
|
||||
### Changed
|
||||
- Update package dependencies. [#42163]
|
||||
|
||||
## [0.11.0] - 2025-02-24
|
||||
### Added
|
||||
- Theme tools: Load theme compat functionality relevant to features in Classic Theme Helper package from this package. [#41598]
|
||||
|
||||
### Changed
|
||||
- Custom Post Types: Do not display testimonials and portfolios on block themes where they are not in use. [#41714]
|
||||
|
||||
## [0.10.1] - 2025-02-17
|
||||
### Changed
|
||||
- Update dependencies.
|
||||
|
||||
## [0.10.0] - 2025-02-10
|
||||
### Changed
|
||||
- Custom Content Types: Ensure feature works on Jetpack settings page without using module functionality. [#41349]
|
||||
- Update package dependencies. [#41491]
|
||||
|
||||
## [0.9.3] - 2025-02-03
|
||||
### Added
|
||||
- Theme compat: Move relevant functionality to the package. [#41394]
|
||||
|
||||
### Changed
|
||||
- Update package dependencies. [#41286]
|
||||
|
||||
## [0.9.2] - 2025-01-27
|
||||
### Fixed
|
||||
- Classic Theme Helper: Fix Fatal in Jetpack_Portfolio. [#41304]
|
||||
|
||||
## [0.9.1] - 2025-01-20
|
||||
### Changed
|
||||
- Code: Use function-style exit() and die() with a default status code of 0. [#41167]
|
||||
- Updated package dependencies. [#41099]
|
||||
|
||||
## [0.9.0] - 2025-01-13
|
||||
### Added
|
||||
- Nova Restaurant: ensuring the custom post type is now being required via the package. [#40782]
|
||||
|
||||
## [0.8.3] - 2025-01-10
|
||||
### Fixed
|
||||
- Testimonials: Fix a shortcode-related bug which occurs if the column attribute is added and set to 0. [#40896]
|
||||
|
||||
## [0.8.2] - 2025-01-06
|
||||
### Changed
|
||||
- Updated package dependencies. [#40784] [#40831]
|
||||
|
||||
## [0.8.1] - 2024-12-23
|
||||
### Added
|
||||
- Custom Post Types: Added Restaurant Menu CPT files. [#40668]
|
||||
|
||||
## [0.8.0] - 2024-12-16
|
||||
### Added
|
||||
- Jetpack Testimonials: Ensuring functionality runs via the Classic Theme Helper package. [#40388]
|
||||
|
||||
### Changed
|
||||
- Updated package dependencies. [#40564]
|
||||
|
||||
### Fixed
|
||||
- Testimonials: Include shortcode CSS file. [#40592]
|
||||
|
||||
## [0.7.4] - 2024-12-09
|
||||
### Fixed
|
||||
- Content Options: Ensure excerpt_length is cast to an int if it is not already, to prevent fatal errors. [#40389]
|
||||
- Customizer: Fix spacing issue in Content Options. [#40445]
|
||||
|
||||
## [0.7.3] - 2024-12-04
|
||||
### Changed
|
||||
- Updated package dependencies. [#40363]
|
||||
|
||||
## [0.7.2] - 2024-12-02
|
||||
### Added
|
||||
- Add Testimonial custom post type content. [#40295]
|
||||
|
||||
## [0.7.1] - 2024-11-25
|
||||
### Changed
|
||||
- Updated package dependencies. [#40286] [#40288]
|
||||
|
||||
## [0.7.0] - 2024-11-18
|
||||
### Removed
|
||||
- General: Update minimum PHP version to 7.2. [#40147]
|
||||
|
||||
## [0.6.7] - 2024-11-11
|
||||
### Changed
|
||||
- Updated package dependencies. [#39999] [#40060]
|
||||
|
||||
## [0.6.6] - 2024-11-04
|
||||
### Added
|
||||
- Enable test coverage. [#39961]
|
||||
|
||||
## [0.6.5] - 2024-10-28
|
||||
### Changed
|
||||
- Updated package dependencies. [#39910]
|
||||
|
||||
## [0.6.4] - 2024-10-14
|
||||
### Changed
|
||||
- Updated package dependencies. [#39707]
|
||||
|
||||
## [0.6.3] - 2024-10-07
|
||||
### Changed
|
||||
- Updated package dependencies. [#39594]
|
||||
|
||||
## [0.6.2] - 2024-09-30
|
||||
### Added
|
||||
- Admin dashboard: Disable portfolio toggle if theme supports portfolio and site is WoA [#39508]
|
||||
|
||||
## [0.6.1] - 2024-09-23
|
||||
### Fixed
|
||||
- Portfolios: Ensure these are enabled and working properly on themes that support portfolios [#39431]
|
||||
|
||||
## [0.6.0] - 2024-09-16
|
||||
### Added
|
||||
- Content Options: Ensuring feature is now required. [#39210]
|
||||
|
||||
### Changed
|
||||
- Custom Content Types: Require feature along with portfolios from the package [#39268]
|
||||
|
||||
## [0.5.6] - 2024-09-10
|
||||
### Changed
|
||||
- Updated package dependencies. [#39302]
|
||||
|
||||
## [0.5.5] - 2024-09-09
|
||||
### Added
|
||||
- Site Breadcrumbs: Ensure main function is not created when host is WordPress.com. [#39235]
|
||||
|
||||
### Changed
|
||||
- Updated package dependencies. [#39176]
|
||||
|
||||
### Fixed
|
||||
- Content Options: Add back value to filter in package version of Content Options file. [#39200]
|
||||
|
||||
## [0.5.4] - 2024-08-30
|
||||
### Security
|
||||
- Social Menu: Switch to more appropriate method of calling the SVG icon file. [#39136]
|
||||
|
||||
### Added
|
||||
- Classic Theme Helper: Adding Portfolio custom post type content [#39134]
|
||||
- Content Options: Moving content to Classic Theme Helper package. [#39028]
|
||||
|
||||
### Changed
|
||||
- Updated package dependencies. [#39111]
|
||||
|
||||
## [0.5.3] - 2024-08-26
|
||||
### Changed
|
||||
- Site Breadcrumbs: Requiring the feature from the Classic Theme Helper package [#38931]
|
||||
|
||||
## [0.5.2] - 2024-08-23
|
||||
### Changed
|
||||
- Updated package dependencies. [#39004]
|
||||
|
||||
## [0.5.1] - 2024-08-21
|
||||
### Fixed
|
||||
- Revert recent SVG image optimizations. [#38981]
|
||||
- Social Menus: fix SVG format. [#38966]
|
||||
|
||||
## [0.5.0] - 2024-08-19
|
||||
### Added
|
||||
- Site Breadcrumbs: Copying functionality file into Classic Theme Helper package. [#38880]
|
||||
- Social Links: Requiring feature from Classic Theme Helper package instead of Jetpack module. [#38730]
|
||||
|
||||
### Changed
|
||||
- Updated package dependencies. [#38662]
|
||||
|
||||
### Fixed
|
||||
- Lossless image optimization for images (should improve performance with no visible changes). [#38750]
|
||||
|
||||
## [0.4.5] - 2024-08-12
|
||||
### Changed
|
||||
- Social Links: Modified package file - new functions, modified function types, added imports [#38738]
|
||||
|
||||
## [0.4.4] - 2024-08-05
|
||||
### Added
|
||||
- Social Links: Added feature to Classic Theme Helper package. [#38593]
|
||||
|
||||
## [0.4.3] - 2024-07-25
|
||||
### Changed
|
||||
- Social Menus: Requiring the feature from the Classic Theme Helper package. [#38297]
|
||||
|
||||
## [0.4.2] - 2024-07-22
|
||||
### Added
|
||||
- Added Jetpack_Color class. [#38357]
|
||||
|
||||
## [0.4.1] - 2024-07-15
|
||||
### Added
|
||||
- Theme Tools: Adding Social Menu to Classic Theme Helper package [#38243]
|
||||
|
||||
## [0.4.0] - 2024-07-08
|
||||
### Changed
|
||||
- Classic Theme Helper - Featured Content: Moved check for plugins page to init since setup is used now externally [#38215]
|
||||
- Classic Theme Helper - Requiring Responsive Videos and Featured Content files. [#37969]
|
||||
- Updated package dependencies. [#38132]
|
||||
|
||||
### Removed
|
||||
- Classic Theme Helper: Remove wpcom only code for featured content [#38154]
|
||||
|
||||
## [0.3.1] - 2024-06-13
|
||||
### Changed
|
||||
- Updated package dependencies. [#37796]
|
||||
|
||||
## [0.3.0] - 2024-06-10
|
||||
### Changed
|
||||
- Classic Theme Helper: Move code from module to package [#37260]
|
||||
|
||||
## [0.2.1] - 2024-06-06
|
||||
### Changed
|
||||
- Updated package dependencies. [#37669]
|
||||
|
||||
### Fixed
|
||||
- Classic Theme Helper: Added dist folder to gitattributes so mirror repo picks it. [#37677]
|
||||
|
||||
## [0.2.0] - 2024-05-27
|
||||
### Added
|
||||
- Classic Theme Helper: Add responsive videos. [#37406]
|
||||
- Classic Theme Helper: Copied featured content code from module. [#37515]
|
||||
|
||||
## 0.1.0 - 2024-05-09
|
||||
### Added
|
||||
- Classic Theme Helper: Added Featured content code to the package. [#37202]
|
||||
- Initial version. [#37175]
|
||||
|
||||
### Changed
|
||||
- Add wordpress folder on gitignore. [#37177]
|
||||
|
||||
[0.14.34]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.33...v0.14.34
|
||||
[0.14.33]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.32...v0.14.33
|
||||
[0.14.32]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.31...v0.14.32
|
||||
[0.14.31]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.30...v0.14.31
|
||||
[0.14.30]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.29...v0.14.30
|
||||
[0.14.29]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.28...v0.14.29
|
||||
[0.14.28]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.27...v0.14.28
|
||||
[0.14.27]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.26...v0.14.27
|
||||
[0.14.26]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.25...v0.14.26
|
||||
[0.14.25]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.24...v0.14.25
|
||||
[0.14.24]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.23...v0.14.24
|
||||
[0.14.23]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.22...v0.14.23
|
||||
[0.14.22]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.21...v0.14.22
|
||||
[0.14.21]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.20...v0.14.21
|
||||
[0.14.20]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.19...v0.14.20
|
||||
[0.14.19]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.18...v0.14.19
|
||||
[0.14.18]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.17...v0.14.18
|
||||
[0.14.17]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.16...v0.14.17
|
||||
[0.14.16]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.15...v0.14.16
|
||||
[0.14.15]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.14...v0.14.15
|
||||
[0.14.14]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.13...v0.14.14
|
||||
[0.14.13]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.12...v0.14.13
|
||||
[0.14.12]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.11...v0.14.12
|
||||
[0.14.11]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.10...v0.14.11
|
||||
[0.14.10]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.9...v0.14.10
|
||||
[0.14.9]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.8...v0.14.9
|
||||
[0.14.8]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.7...v0.14.8
|
||||
[0.14.7]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.6...v0.14.7
|
||||
[0.14.6]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.5...v0.14.6
|
||||
[0.14.5]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.4...v0.14.5
|
||||
[0.14.4]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.3...v0.14.4
|
||||
[0.14.3]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.2...v0.14.3
|
||||
[0.14.2]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.1...v0.14.2
|
||||
[0.14.1]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.14.0...v0.14.1
|
||||
[0.14.0]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.13.22...v0.14.0
|
||||
[0.13.22]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.13.21...v0.13.22
|
||||
[0.13.21]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.13.20...v0.13.21
|
||||
[0.13.20]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.13.19...v0.13.20
|
||||
[0.13.19]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.13.18...v0.13.19
|
||||
[0.13.18]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.13.17...v0.13.18
|
||||
[0.13.17]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.13.16...v0.13.17
|
||||
[0.13.16]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.13.15...v0.13.16
|
||||
[0.13.15]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.13.14...v0.13.15
|
||||
[0.13.14]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.13.13...v0.13.14
|
||||
[0.13.13]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.13.12...v0.13.13
|
||||
[0.13.12]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.13.11...v0.13.12
|
||||
[0.13.11]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.13.10...v0.13.11
|
||||
[0.13.10]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.13.9...v0.13.10
|
||||
[0.13.9]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.13.8...v0.13.9
|
||||
[0.13.8]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.13.7...v0.13.8
|
||||
[0.13.7]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.13.6...v0.13.7
|
||||
[0.13.6]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.13.5...v0.13.6
|
||||
[0.13.5]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.13.4...v0.13.5
|
||||
[0.13.4]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.13.3...v0.13.4
|
||||
[0.13.3]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.13.2...v0.13.3
|
||||
[0.13.2]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.13.1...v0.13.2
|
||||
[0.13.1]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.13.0...v0.13.1
|
||||
[0.13.0]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.12.1...v0.13.0
|
||||
[0.12.1]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.12.0...v0.12.1
|
||||
[0.12.0]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.11.8...v0.12.0
|
||||
[0.11.8]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.11.7...v0.11.8
|
||||
[0.11.7]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.11.6...v0.11.7
|
||||
[0.11.6]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.11.5...v0.11.6
|
||||
[0.11.5]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.11.4...v0.11.5
|
||||
[0.11.4]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.11.3...v0.11.4
|
||||
[0.11.3]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.11.2...v0.11.3
|
||||
[0.11.2]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.11.1...v0.11.2
|
||||
[0.11.1]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.11.0...v0.11.1
|
||||
[0.11.0]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.10.1...v0.11.0
|
||||
[0.10.1]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.10.0...v0.10.1
|
||||
[0.10.0]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.9.3...v0.10.0
|
||||
[0.9.3]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.9.2...v0.9.3
|
||||
[0.9.2]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.9.1...v0.9.2
|
||||
[0.9.1]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.9.0...v0.9.1
|
||||
[0.9.0]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.8.3...v0.9.0
|
||||
[0.8.3]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.8.2...v0.8.3
|
||||
[0.8.2]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.8.1...v0.8.2
|
||||
[0.8.1]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.8.0...v0.8.1
|
||||
[0.8.0]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.7.4...v0.8.0
|
||||
[0.7.4]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.7.3...v0.7.4
|
||||
[0.7.3]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.7.2...v0.7.3
|
||||
[0.7.2]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.7.1...v0.7.2
|
||||
[0.7.1]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.7.0...v0.7.1
|
||||
[0.7.0]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.6.7...v0.7.0
|
||||
[0.6.7]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.6.6...v0.6.7
|
||||
[0.6.6]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.6.5...v0.6.6
|
||||
[0.6.5]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.6.4...v0.6.5
|
||||
[0.6.4]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.6.3...v0.6.4
|
||||
[0.6.3]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.6.2...v0.6.3
|
||||
[0.6.2]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.6.1...v0.6.2
|
||||
[0.6.1]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.6.0...v0.6.1
|
||||
[0.6.0]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.5.6...v0.6.0
|
||||
[0.5.6]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.5.5...v0.5.6
|
||||
[0.5.5]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.5.4...v0.5.5
|
||||
[0.5.4]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.5.3...v0.5.4
|
||||
[0.5.3]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.5.2...v0.5.3
|
||||
[0.5.2]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.5.1...v0.5.2
|
||||
[0.5.1]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.5.0...v0.5.1
|
||||
[0.5.0]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.4.5...v0.5.0
|
||||
[0.4.5]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.4.4...v0.4.5
|
||||
[0.4.4]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.4.3...v0.4.4
|
||||
[0.4.3]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.4.2...v0.4.3
|
||||
[0.4.2]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.4.1...v0.4.2
|
||||
[0.4.1]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.4.0...v0.4.1
|
||||
[0.4.0]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.3.1...v0.4.0
|
||||
[0.3.1]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.3.0...v0.3.1
|
||||
[0.3.0]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.2.1...v0.3.0
|
||||
[0.2.1]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.2.0...v0.2.1
|
||||
[0.2.0]: https://github.com/Automattic/jetpack-classic-theme-helper/compare/v0.1.0...v0.2.0
|
||||
+911
@@ -0,0 +1,911 @@
|
||||
<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
|
||||
/**
|
||||
* Color utility and conversion
|
||||
*
|
||||
* Represents a color value, and converts between RGB/HSV/XYZ/Lab/HSL
|
||||
*
|
||||
* Example:
|
||||
* $color = new Jetpack_Color(0xFFFFFF);
|
||||
*
|
||||
* @author Harold Asbridge <hasbridge@gmail.com>
|
||||
* @author Matt Wiebe <wiebe@automattic.com>
|
||||
* @license https://www.opensource.org/licenses/MIT
|
||||
*
|
||||
* @package automattic/jetpack
|
||||
*/
|
||||
|
||||
// phpcs:disable WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid
|
||||
|
||||
if ( ! class_exists( 'Jetpack_Color' ) ) {
|
||||
/**
|
||||
* Color utilities
|
||||
*/
|
||||
class Jetpack_Color {
|
||||
/**
|
||||
* Color code (later array or string, depending on type)
|
||||
*
|
||||
* @var int|array|string
|
||||
*/
|
||||
protected $color = 0;
|
||||
|
||||
/**
|
||||
* Initialize object
|
||||
*
|
||||
* @param string|array $color A color of the type $type.
|
||||
* @param string $type The type of color we will construct from.
|
||||
* One of hex (default), rgb, hsl, int.
|
||||
*/
|
||||
public function __construct( $color = null, $type = 'hex' ) {
|
||||
if ( $color ) {
|
||||
switch ( $type ) {
|
||||
case 'hex':
|
||||
$this->fromHex( $color );
|
||||
break;
|
||||
case 'rgb':
|
||||
if ( is_array( $color ) && count( $color ) === 3 ) {
|
||||
list( $r, $g, $b ) = array_values( $color );
|
||||
$this->fromRgbInt( $r, $g, $b );
|
||||
}
|
||||
break;
|
||||
case 'hsl':
|
||||
if ( is_array( $color ) && count( $color ) === 3 ) {
|
||||
list( $h, $s, $l ) = array_values( $color );
|
||||
$this->fromHsl( $h, $s, $l );
|
||||
}
|
||||
break;
|
||||
case 'int':
|
||||
// @phan-suppress-next-line PhanTypeMismatchArgument
|
||||
$this->fromInt( $color );
|
||||
break;
|
||||
default:
|
||||
// there is no default.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Init color from hex value
|
||||
*
|
||||
* @param string $hex_value Color hex value.
|
||||
*
|
||||
* @return $this
|
||||
* @throws RangeException Invalid color code range error.
|
||||
*/
|
||||
public function fromHex( $hex_value ) {
|
||||
$hex_value = str_replace( '#', '', $hex_value );
|
||||
// handle short hex codes like #fff.
|
||||
if ( 3 === strlen( $hex_value ) ) {
|
||||
$hex_value = $hex_value[0] . $hex_value[0] . $hex_value[1] . $hex_value[1] . $hex_value[2] . $hex_value[2];
|
||||
}
|
||||
return $this->fromInt( hexdec( $hex_value ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Init color from integer RGB values
|
||||
*
|
||||
* @param int $red Red color code.
|
||||
* @param int $green Green color code.
|
||||
* @param int $blue Blue color code.
|
||||
*
|
||||
* @return $this
|
||||
* @throws RangeException Invalid color code range error.
|
||||
*/
|
||||
public function fromRgbInt( $red, $green, $blue ) {
|
||||
if ( $red < 0 || $red > 255 ) {
|
||||
throw new RangeException( 'Red value ' . $red . ' out of valid color code range' );
|
||||
}
|
||||
|
||||
if ( $green < 0 || $green > 255 ) {
|
||||
throw new RangeException( 'Green value ' . $green . ' out of valid color code range' );
|
||||
}
|
||||
|
||||
if ( $blue < 0 || $blue > 255 ) {
|
||||
throw new RangeException( 'Blue value ' . $blue . ' out of valid color code range' );
|
||||
}
|
||||
|
||||
$this->color = ( intval( $red ) << 16 ) + ( intval( $green ) << 8 ) + intval( $blue );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Init color from hex RGB values
|
||||
*
|
||||
* @param string $red Red color code.
|
||||
* @param string $green Green color code.
|
||||
* @param string $blue Blue color code.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function fromRgbHex( $red, $green, $blue ) {
|
||||
return $this->fromRgbInt( hexdec( $red ), hexdec( $green ), hexdec( $blue ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an HSL color value to RGB. Conversion formula
|
||||
* adapted from https://en.wikipedia.org/wiki/HSL_color_space.
|
||||
*
|
||||
* @param int $h Hue. [0-360].
|
||||
* @param int $s Saturation [0, 100].
|
||||
* @param int $l Lightness [0, 100].
|
||||
*/
|
||||
public function fromHsl( $h, $s, $l ) {
|
||||
$h /= 360;
|
||||
$s /= 100;
|
||||
$l /= 100;
|
||||
|
||||
if ( 0 === $s ) {
|
||||
// achromatic.
|
||||
$r = $l;
|
||||
$g = $l;
|
||||
$b = $l;
|
||||
} else {
|
||||
$q = $l < 0.5 ? $l * ( 1 + $s ) : $l + $s - $l * $s;
|
||||
$p = 2 * $l - $q;
|
||||
$r = $this->hue2rgb( $p, $q, $h + 1 / 3 );
|
||||
$g = $this->hue2rgb( $p, $q, $h );
|
||||
$b = $this->hue2rgb( $p, $q, $h - 1 / 3 );
|
||||
}
|
||||
|
||||
return $this->fromRgbInt( $r * 255, $g * 255, $b * 255 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for Jetpack_Color::fromHsl()
|
||||
*
|
||||
* @param float $p Minimum of R/G/B [0, 1].
|
||||
* @param float $q Maximum of R/G/B [0, 1].
|
||||
* @param float $t Adjusted hue [0, 1].
|
||||
*/
|
||||
private function hue2rgb( $p, $q, $t ) {
|
||||
if ( $t < 0 ) {
|
||||
++$t;
|
||||
}
|
||||
if ( $t > 1 ) {
|
||||
--$t;
|
||||
}
|
||||
if ( $t < 1 / 6 ) {
|
||||
return $p + ( $q - $p ) * 6 * $t;
|
||||
}
|
||||
if ( $t < 1 / 2 ) {
|
||||
return $q;
|
||||
}
|
||||
if ( $t < 2 / 3 ) {
|
||||
return $p + ( $q - $p ) * ( 2 / 3 - $t ) * 6;
|
||||
}
|
||||
return $p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Init color from integer value
|
||||
*
|
||||
* @param int $int_value Color code.
|
||||
*
|
||||
* @return $this
|
||||
* @throws RangeException Invalid color code range error.
|
||||
*/
|
||||
public function fromInt( $int_value ) {
|
||||
if ( $int_value < 0 || $int_value > 16777215 ) {
|
||||
throw new RangeException( $int_value . ' out of valid color code range' );
|
||||
}
|
||||
|
||||
$this->color = $int_value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert color to hex
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function toHex() {
|
||||
return sprintf( '%06x', $this->color );
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert color to RGB array (integer values)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toRgbInt() {
|
||||
return array(
|
||||
'red' => (int) ( 255 & ( $this->color >> 16 ) ),
|
||||
'green' => (int) ( 255 & ( $this->color >> 8 ) ),
|
||||
'blue' => (int) ( 255 & ( $this->color ) ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert color to RGB array (hex values)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toRgbHex() {
|
||||
$r = array();
|
||||
foreach ( $this->toRgbInt() as $item ) {
|
||||
$r[] = dechex( $item );
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Hue/Saturation/Value for the current color
|
||||
* (float values, slow but accurate)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toHsvFloat() {
|
||||
$rgb = $this->toRgbInt();
|
||||
|
||||
$rgb_min = min( $rgb );
|
||||
$rgb_max = max( $rgb );
|
||||
|
||||
$hsv = array(
|
||||
'hue' => 0,
|
||||
'sat' => 0,
|
||||
'val' => $rgb_max,
|
||||
);
|
||||
|
||||
// If v is 0, color is black.
|
||||
if ( 0 === $hsv['val'] ) {
|
||||
return $hsv;
|
||||
}
|
||||
|
||||
// Normalize RGB values to 1.
|
||||
$rgb['red'] /= $hsv['val'];
|
||||
$rgb['green'] /= $hsv['val'];
|
||||
$rgb['blue'] /= $hsv['val'];
|
||||
$rgb_min = min( $rgb );
|
||||
$rgb_max = max( $rgb );
|
||||
|
||||
// Calculate saturation.
|
||||
$hsv['sat'] = $rgb_max - $rgb_min;
|
||||
if ( 0 === $hsv['sat'] ) {
|
||||
$hsv['hue'] = 0;
|
||||
return $hsv;
|
||||
}
|
||||
|
||||
// Normalize saturation to 1.
|
||||
$rgb['red'] = ( $rgb['red'] - $rgb_min ) / ( $rgb_max - $rgb_min );
|
||||
$rgb['green'] = ( $rgb['green'] - $rgb_min ) / ( $rgb_max - $rgb_min );
|
||||
$rgb['blue'] = ( $rgb['blue'] - $rgb_min ) / ( $rgb_max - $rgb_min );
|
||||
$rgb_min = min( $rgb );
|
||||
$rgb_max = max( $rgb );
|
||||
|
||||
// Calculate hue.
|
||||
if ( $rgb_max === $rgb['red'] ) {
|
||||
$hsv['hue'] = 0.0 + 60 * ( $rgb['green'] - $rgb['blue'] );
|
||||
if ( $hsv['hue'] < 0 ) {
|
||||
$hsv['hue'] += 360;
|
||||
}
|
||||
} elseif ( $rgb_max === $rgb['green'] ) {
|
||||
$hsv['hue'] = 120 + ( 60 * ( $rgb['blue'] - $rgb['red'] ) );
|
||||
} else {
|
||||
$hsv['hue'] = 240 + ( 60 * ( $rgb['red'] - $rgb['green'] ) );
|
||||
}
|
||||
|
||||
return $hsv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get HSV values for color
|
||||
* (integer values from 0-255, fast but less accurate)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toHsvInt() {
|
||||
$rgb = $this->toRgbInt();
|
||||
|
||||
$rgb_min = min( $rgb );
|
||||
$rgb_max = max( $rgb );
|
||||
|
||||
$hsv = array(
|
||||
'hue' => 0,
|
||||
'sat' => 0,
|
||||
'val' => $rgb_max,
|
||||
);
|
||||
|
||||
// If value is 0, color is black.
|
||||
if ( 0 === $hsv['val'] ) {
|
||||
return $hsv;
|
||||
}
|
||||
|
||||
// Calculate saturation.
|
||||
$hsv['sat'] = round( 255 * ( $rgb_max - $rgb_min ) / $hsv['val'] );
|
||||
// @phan-suppress-next-line PhanImpossibleTypeComparison
|
||||
if ( 0 === $hsv['sat'] ) {
|
||||
$hsv['hue'] = 0;
|
||||
return $hsv;
|
||||
}
|
||||
|
||||
// Calculate hue.
|
||||
if ( $rgb_max === $rgb['red'] ) {
|
||||
$hsv['hue'] = round( 0 + 43 * ( $rgb['green'] - $rgb['blue'] ) / ( $rgb_max - $rgb_min ) );
|
||||
} elseif ( $rgb_max === $rgb['green'] ) {
|
||||
$hsv['hue'] = round( 85 + 43 * ( $rgb['blue'] - $rgb['red'] ) / ( $rgb_max - $rgb_min ) );
|
||||
} else {
|
||||
$hsv['hue'] = round( 171 + 43 * ( $rgb['red'] - $rgb['green'] ) / ( $rgb_max - $rgb_min ) );
|
||||
}
|
||||
if ( $hsv['hue'] < 0 ) {
|
||||
$hsv['hue'] += 255;
|
||||
}
|
||||
|
||||
return $hsv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an RGB color value to HSL. Conversion formula
|
||||
* adapted from https://en.wikipedia.org/wiki/HSL_color_space.
|
||||
* Assumes r, g, and b are contained in the set [0, 255] and
|
||||
* returns h in [0, 360], s in [0, 100], l in [0, 100]
|
||||
*
|
||||
* @return Array The HSL representation
|
||||
*/
|
||||
public function toHsl() {
|
||||
list( $r, $g, $b ) = array_values( $this->toRgbInt() );
|
||||
$r /= 255;
|
||||
$g /= 255;
|
||||
$b /= 255;
|
||||
$max = max( $r, $g, $b );
|
||||
$min = min( $r, $g, $b );
|
||||
$l = ( $max + $min ) / 2;
|
||||
|
||||
if ( $max === $min ) {
|
||||
// achromatic.
|
||||
$s = 0;
|
||||
$h = 0;
|
||||
} else {
|
||||
$d = $max - $min;
|
||||
$s = $l > 0.5 ? $d / ( 2 - $max - $min ) : $d / ( $max + $min );
|
||||
switch ( $max ) {
|
||||
case $r:
|
||||
$h = ( $g - $b ) / $d + ( $g < $b ? 6 : 0 );
|
||||
break;
|
||||
case $g:
|
||||
$h = ( $b - $r ) / $d + 2;
|
||||
break;
|
||||
case $b:
|
||||
$h = ( $r - $g ) / $d + 4;
|
||||
break;
|
||||
}
|
||||
$h /= 6;
|
||||
}
|
||||
$h = (int) round( $h * 360 );
|
||||
$s = (int) round( $s * 100 );
|
||||
$l = (int) round( $l * 100 );
|
||||
return compact( 'h', 's', 'l' );
|
||||
}
|
||||
|
||||
/**
|
||||
* From a color code to a string to be used in CSS declaration.
|
||||
*
|
||||
* @param string $type Color code type.
|
||||
* @param int $alpha Transparency.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function toCSS( $type = 'hex', $alpha = 1 ) {
|
||||
switch ( $type ) {
|
||||
case 'hex':
|
||||
return $this->toString();
|
||||
case 'rgb':
|
||||
case 'rgba':
|
||||
list( $r, $g, $b ) = array_values( $this->toRgbInt() );
|
||||
if ( is_numeric( $alpha ) && $alpha < 1 ) {
|
||||
return "rgba( {$r}, {$g}, {$b}, $alpha )";
|
||||
} else {
|
||||
return "rgb( {$r}, {$g}, {$b} )";
|
||||
}
|
||||
case 'hsl':
|
||||
case 'hsla':
|
||||
list( $h, $s, $l ) = array_values( $this->toHsl() );
|
||||
if ( is_numeric( $alpha ) && $alpha < 1 ) {
|
||||
return "hsla( {$h}, {$s}, {$l}, $alpha )";
|
||||
} else {
|
||||
return "hsl( {$h}, {$s}, {$l} )";
|
||||
}
|
||||
default:
|
||||
return $this->toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current color in XYZ format
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toXyz() {
|
||||
$rgb = $this->toRgbInt();
|
||||
|
||||
// Normalize RGB values to 1.
|
||||
$rgb_new = array();
|
||||
foreach ( $rgb as $item ) {
|
||||
$rgb_new[] = $item / 255;
|
||||
}
|
||||
$rgb = $rgb_new;
|
||||
|
||||
$rgb_new = array();
|
||||
foreach ( $rgb as $item ) {
|
||||
if ( $item > 0.04045 ) {
|
||||
$item = pow( ( ( $item + 0.055 ) / 1.055 ), 2.4 );
|
||||
} else {
|
||||
$item /= 12.92;
|
||||
}
|
||||
$rgb_new[] = $item * 100;
|
||||
}
|
||||
$rgb = $rgb_new;
|
||||
|
||||
// Observer. = 2°, Illuminant = D65.
|
||||
$xyz = array(
|
||||
// @phan-suppress-next-line PhanTypeInvalidDimOffset,PhanTypeInvalidLeftOperandOfNumericOp
|
||||
'x' => ( $rgb['red'] * 0.4124 ) + ( $rgb['green'] * 0.3576 ) + ( $rgb['blue'] * 0.1805 ),
|
||||
// @phan-suppress-next-line PhanTypeInvalidDimOffset,PhanTypeInvalidLeftOperandOfNumericOp
|
||||
'y' => ( $rgb['red'] * 0.2126 ) + ( $rgb['green'] * 0.7152 ) + ( $rgb['blue'] * 0.0722 ),
|
||||
// @phan-suppress-next-line PhanTypeInvalidDimOffset,PhanTypeInvalidLeftOperandOfNumericOp
|
||||
'z' => ( $rgb['red'] * 0.0193 ) + ( $rgb['green'] * 0.1192 ) + ( $rgb['blue'] * 0.9505 ),
|
||||
);
|
||||
|
||||
return $xyz;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get color CIE-Lab values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toLabCie() {
|
||||
$xyz = $this->toXyz();
|
||||
|
||||
// Ovserver = 2*, Iluminant=D65.
|
||||
$xyz['x'] /= 95.047;
|
||||
$xyz['y'] /= 100;
|
||||
$xyz['z'] /= 108.883;
|
||||
|
||||
$xyz_new = array();
|
||||
foreach ( $xyz as $item ) {
|
||||
if ( $item > 0.008856 ) {
|
||||
$xyz_new[] = pow( $item, 1 / 3 );
|
||||
} else {
|
||||
$xyz_new[] = ( 7.787 * $item ) + ( 16 / 116 );
|
||||
}
|
||||
}
|
||||
$xyz = $xyz_new;
|
||||
|
||||
$lab = array(
|
||||
// @phan-suppress-next-line PhanTypeInvalidDimOffset,PhanTypeInvalidRightOperandOfNumericOp
|
||||
'l' => ( 116 * $xyz['y'] ) - 16,
|
||||
// @phan-suppress-next-line PhanTypeInvalidDimOffset,PhanTypeInvalidLeftOperandOfNumericOp,PhanTypeInvalidRightOperandOfNumericOp
|
||||
'a' => 500 * ( $xyz['x'] - $xyz['y'] ),
|
||||
// @phan-suppress-next-line PhanTypeInvalidDimOffset,PhanTypeInvalidLeftOperandOfNumericOp,PhanTypeInvalidRightOperandOfNumericOp
|
||||
'b' => 200 * ( $xyz['y'] - $xyz['z'] ),
|
||||
);
|
||||
|
||||
return $lab;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert color to integer
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function toInt() {
|
||||
return $this->color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias of toString()
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString() {
|
||||
return $this->toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get color as string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function toString() {
|
||||
$str = $this->toHex();
|
||||
return strtoupper( "#{$str}" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the distance between this color and the given color
|
||||
*
|
||||
* @param Jetpack_Color $color Color code.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getDistanceRgbFrom( Jetpack_Color $color ) {
|
||||
$rgb1 = $this->toRgbInt();
|
||||
$rgb2 = $color->toRgbInt();
|
||||
|
||||
$r_diff = abs( $rgb1['red'] - $rgb2['red'] );
|
||||
$g_diff = abs( $rgb1['green'] - $rgb2['green'] );
|
||||
$b_diff = abs( $rgb1['blue'] - $rgb2['blue'] );
|
||||
|
||||
// Sum of RGB differences.
|
||||
$diff = $r_diff + $g_diff + $b_diff;
|
||||
return $diff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get distance from the given color using the Delta E method
|
||||
*
|
||||
* @param Jetpack_Color $color Color code.
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getDistanceLabFrom( Jetpack_Color $color ) {
|
||||
$lab1 = $this->toLabCie();
|
||||
$lab2 = $color->toLabCie();
|
||||
|
||||
$l_diff = abs( $lab2['l'] - $lab1['l'] );
|
||||
$a_diff = abs( $lab2['a'] - $lab1['a'] );
|
||||
$b_diff = abs( $lab2['b'] - $lab1['b'] );
|
||||
|
||||
$delta = sqrt( $l_diff + $a_diff + $b_diff );
|
||||
|
||||
return $delta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate luminosity.
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function toLuminosity() {
|
||||
$lum = array();
|
||||
foreach ( $this->toRgbInt() as $slot => $value ) {
|
||||
$chan = $value / 255;
|
||||
$lum[ $slot ] = ( $chan <= 0.03928 ) ? $chan / 12.92 : pow( ( ( $chan + 0.055 ) / 1.055 ), 2.4 );
|
||||
}
|
||||
return 0.2126 * $lum['red'] + 0.7152 * $lum['green'] + 0.0722 * $lum['blue'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get distance between colors using luminance.
|
||||
* Should be more than 5 for readable contrast
|
||||
*
|
||||
* @param Jetpack_Color $color Another color.
|
||||
* @return float
|
||||
*/
|
||||
public function getDistanceLuminosityFrom( Jetpack_Color $color ) {
|
||||
$l1 = $this->toLuminosity();
|
||||
$l2 = $color->toLuminosity();
|
||||
if ( $l1 > $l2 ) {
|
||||
return ( $l1 + 0.05 ) / ( $l2 + 0.05 );
|
||||
} else {
|
||||
return ( $l2 + 0.05 ) / ( $l1 + 0.05 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get maximum contrast color.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function getMaxContrastColor() {
|
||||
$with_black = $this->getDistanceLuminosityFrom( new Jetpack_Color( '#000' ) );
|
||||
$with_white = $this->getDistanceLuminosityFrom( new Jetpack_Color( '#fff' ) );
|
||||
$color = new Jetpack_Color();
|
||||
$hex = ( $with_black >= $with_white ) ? '#000000' : '#ffffff';
|
||||
return $color->fromHex( $hex );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get grayscale contrasting color.
|
||||
*
|
||||
* @param bool|int $contrast Contrast.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function getGrayscaleContrastingColor( $contrast = false ) {
|
||||
if ( ! $contrast ) {
|
||||
return $this->getMaxContrastColor();
|
||||
}
|
||||
// don't allow less than 5.
|
||||
$target_contrast = ( $contrast < 5 ) ? 5 : $contrast;
|
||||
$color = $this->getMaxContrastColor();
|
||||
$contrast = $color->getDistanceLuminosityFrom( $this );
|
||||
|
||||
// if current max contrast is less than the target contrast, we had wishful thinking.
|
||||
if ( $contrast <= $target_contrast ) {
|
||||
return $color;
|
||||
}
|
||||
|
||||
$incr = ( '#000000' === $color->toString() ) ? 1 : -1;
|
||||
while ( $contrast > $target_contrast ) {
|
||||
$color = $color->incrementLightness( $incr );
|
||||
$contrast = $color->getDistanceLuminosityFrom( $this );
|
||||
}
|
||||
|
||||
return $color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a readable contrasting color. $this is assumed to be the text and $color the background color.
|
||||
*
|
||||
* @param object $bg_color A Color object that will be compared against $this.
|
||||
* @param integer $min_contrast The minimum contrast to achieve, if possible.
|
||||
* @return object A Color object, an increased contrast $this compared against $bg_color
|
||||
*/
|
||||
public function getReadableContrastingColor( $bg_color = null, $min_contrast = 5 ) {
|
||||
if ( ! $bg_color || ! is_a( $bg_color, 'Jetpack_Color' ) ) {
|
||||
return $this;
|
||||
}
|
||||
// you shouldn't use less than 5, but you might want to.
|
||||
$target_contrast = $min_contrast;
|
||||
// working things.
|
||||
$contrast = $bg_color->getDistanceLuminosityFrom( $this );
|
||||
$max_contrast_color = $bg_color->getMaxContrastColor();
|
||||
$max_contrast = $max_contrast_color->getDistanceLuminosityFrom( $bg_color );
|
||||
|
||||
// if current max contrast is less than the target contrast, we had wishful thinking.
|
||||
// still, go max.
|
||||
if ( $max_contrast <= $target_contrast ) {
|
||||
return $max_contrast_color;
|
||||
}
|
||||
// or, we might already have sufficient contrast.
|
||||
if ( $contrast >= $target_contrast ) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$incr = ( 0 === $max_contrast_color->toInt() ) ? -1 : 1;
|
||||
while ( $contrast < $target_contrast ) {
|
||||
$this->incrementLightness( $incr );
|
||||
$contrast = $bg_color->getDistanceLuminosityFrom( $this );
|
||||
// infininite loop prevention: you never know.
|
||||
if ( 0 === $this->color || 16777215 === $this->color ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect if color is grayscale
|
||||
*
|
||||
* @param int $threshold Max difference between colors.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isGrayscale( $threshold = 16 ) {
|
||||
$rgb = $this->toRgbInt();
|
||||
|
||||
// Get min and max rgb values, then difference between them.
|
||||
$rgb_min = min( $rgb );
|
||||
$rgb_max = max( $rgb );
|
||||
$diff = $rgb_max - $rgb_min;
|
||||
|
||||
return $diff < $threshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the closest matching color from the given array of colors
|
||||
*
|
||||
* @param array $colors array of integers or Jetpack_Color objects.
|
||||
*
|
||||
* @return mixed the array key of the matched color
|
||||
*/
|
||||
public function getClosestMatch( array $colors ) {
|
||||
$match_dist = 10000;
|
||||
$match_key = null;
|
||||
foreach ( $colors as $key => $color ) {
|
||||
if ( ! ( $color instanceof Jetpack_Color ) ) {
|
||||
$c = new Jetpack_Color( $color );
|
||||
}
|
||||
// @phan-suppress-next-line PhanPossiblyUndeclaredVariable,PhanTypeMismatchArgumentNullable
|
||||
$dist = $this->getDistanceLabFrom( $c );
|
||||
if ( $dist < $match_dist ) {
|
||||
$match_dist = $dist;
|
||||
$match_key = $key;
|
||||
}
|
||||
}
|
||||
|
||||
return $match_key;
|
||||
}
|
||||
|
||||
/* TRANSFORMS */
|
||||
|
||||
/**
|
||||
* Transform -- Darken color.
|
||||
*
|
||||
* @param int $amount Amount. Default to 5.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function darken( $amount = 5 ) {
|
||||
return $this->incrementLightness( - $amount );
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform -- Lighten color.
|
||||
*
|
||||
* @param int $amount Amount. Default to 5.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function lighten( $amount = 5 ) {
|
||||
return $this->incrementLightness( $amount );
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform -- Increment lightness.
|
||||
*
|
||||
* @param int $amount Amount.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function incrementLightness( $amount ) {
|
||||
$hsl = $this->toHsl();
|
||||
|
||||
$h = $hsl['h'] ?? 0;
|
||||
$s = $hsl['s'] ?? 0;
|
||||
$l = $hsl['l'] ?? 0;
|
||||
|
||||
$l += $amount;
|
||||
if ( $l < 0 ) {
|
||||
$l = 0;
|
||||
}
|
||||
if ( $l > 100 ) {
|
||||
$l = 100;
|
||||
}
|
||||
return $this->fromHsl( $h, $s, $l );
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform -- Saturate color.
|
||||
*
|
||||
* @param int $amount Amount. Default to 15.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function saturate( $amount = 15 ) {
|
||||
return $this->incrementSaturation( $amount );
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform -- Desaturate color.
|
||||
*
|
||||
* @param int $amount Amount. Default to 15.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function desaturate( $amount = 15 ) {
|
||||
return $this->incrementSaturation( - $amount );
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform -- Increment saturation.
|
||||
*
|
||||
* @param int $amount Amount.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function incrementSaturation( $amount ) {
|
||||
$hsl = $this->toHsl();
|
||||
|
||||
$h = $hsl['h'] ?? 0;
|
||||
$s = $hsl['s'] ?? 0;
|
||||
$l = $hsl['l'] ?? 0;
|
||||
|
||||
$s += $amount;
|
||||
if ( $s < 0 ) {
|
||||
$s = 0;
|
||||
}
|
||||
if ( $s > 100 ) {
|
||||
$s = 100;
|
||||
}
|
||||
return $this->fromHsl( $h, $s, $l );
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform -- To grayscale.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function toGrayscale() {
|
||||
$hsl = $this->toHsl();
|
||||
|
||||
$h = $hsl['h'] ?? 0;
|
||||
$s = 0;
|
||||
$l = $hsl['l'] ?? 0;
|
||||
|
||||
return $this->fromHsl( $h, $s, $l );
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform -- To the complementary color.
|
||||
*
|
||||
* The complement is the color on the opposite side of the color wheel, 180° away.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function getComplement() {
|
||||
return $this->incrementHue( 180 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform -- To an analogous color of the complement.
|
||||
*
|
||||
* @param int $step Pass `1` or `-1` to choose which direction around the color wheel.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function getSplitComplement( $step = 1 ) {
|
||||
$incr = 180 + ( $step * 30 );
|
||||
return $this->incrementHue( $incr );
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform -- To an analogous color.
|
||||
*
|
||||
* Analogous colors are those adjacent on the color wheel, separated by 30°.
|
||||
*
|
||||
* @param int $step Pass `1` or `-1` to choose which direction around the color wheel.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function getAnalog( $step = 1 ) {
|
||||
$incr = $step * 30;
|
||||
return $this->incrementHue( $incr );
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform -- To a tetradic (rectangular) color.
|
||||
*
|
||||
* A rectangular color scheme uses a color, its complement, and the colors 60° from each.
|
||||
* This transforms the color to its 60° "tetrad".
|
||||
*
|
||||
* @param int $step Pass `1` or `-1` to choose which direction around the color wheel.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function getTetrad( $step = 1 ) {
|
||||
$incr = $step * 60;
|
||||
return $this->incrementHue( $incr );
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform -- To a triadic color.
|
||||
*
|
||||
* A triadic color scheme uses three colors evenly spaced (120°) around the color wheel.
|
||||
* This transforms the color to one of its triadic colors.
|
||||
*
|
||||
* @param int $step Pass `1` or `-1` to choose which direction around the color wheel.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function getTriad( $step = 1 ) {
|
||||
$incr = $step * 120;
|
||||
return $this->incrementHue( $incr );
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform -- Increment hue.
|
||||
*
|
||||
* @param int $amount Amount.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function incrementHue( $amount ) {
|
||||
$hsl = $this->toHsl();
|
||||
|
||||
$h = $hsl['h'] ?? 0;
|
||||
$s = $hsl['s'] ?? 0;
|
||||
$l = $hsl['l'] ?? 0;
|
||||
|
||||
$h = ( $h + $amount ) % 360;
|
||||
if ( $h < 0 ) {
|
||||
$h += 360;
|
||||
}
|
||||
return $this->fromHsl( $h, $s, $l );
|
||||
}
|
||||
}
|
||||
}
|
||||
+280
@@ -0,0 +1,280 @@
|
||||
<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
|
||||
/**
|
||||
* Tonesque
|
||||
* Grab an average color representation from an image.
|
||||
*
|
||||
* @author Automattic
|
||||
* @author Matias Ventura
|
||||
* @package automattic/jetpack
|
||||
*/
|
||||
|
||||
if ( ! class_exists( 'Tonesque' ) ) {
|
||||
/**
|
||||
* Color representation class.
|
||||
*/
|
||||
class Tonesque {
|
||||
/**
|
||||
* Image URL.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $image_url = '';
|
||||
/**
|
||||
* Image identifier representing the image.
|
||||
*
|
||||
* @var null|object
|
||||
*/
|
||||
private $image_obj = null;
|
||||
/**
|
||||
* Color code.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $color = '';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $image_url Image URL.
|
||||
*/
|
||||
public function __construct( $image_url ) {
|
||||
if ( ! class_exists( 'Jetpack_Color' ) ) {
|
||||
require_once __DIR__ . '/class.color.php';
|
||||
}
|
||||
|
||||
$this->image_url = esc_url_raw( $image_url );
|
||||
$this->image_url = trim( $this->image_url );
|
||||
/**
|
||||
* Allows any image URL to be passed in for $this->image_url.
|
||||
*
|
||||
* @module theme-tools
|
||||
*
|
||||
* @since 2.5.0
|
||||
*
|
||||
* @param string $image_url The URL to any image
|
||||
*/
|
||||
$this->image_url = apply_filters( 'tonesque_image_url', $this->image_url );
|
||||
|
||||
$this->image_obj = self::imagecreatefromurl( $this->image_url );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an image object from a URL.
|
||||
*
|
||||
* @param string $image_url Image URL.
|
||||
*
|
||||
* @return object|bool Image object or false if the image could not be loaded.
|
||||
*/
|
||||
public static function imagecreatefromurl( $image_url ) {
|
||||
$data = null;
|
||||
|
||||
// If it's a URL.
|
||||
if ( preg_match( '#^https?://#i', $image_url ) ) {
|
||||
// If it's a url pointing to a local media library url.
|
||||
$content_url = content_url();
|
||||
$_image_url = set_url_scheme( $image_url );
|
||||
if ( str_starts_with( $_image_url, $content_url ) ) {
|
||||
$_image_path = str_replace( $content_url, WP_CONTENT_DIR, $_image_url );
|
||||
if ( file_exists( $_image_path ) ) {
|
||||
$filetype = wp_check_filetype( $_image_path );
|
||||
$type = $filetype['type'];
|
||||
|
||||
if ( str_starts_with( $type, 'image/' ) ) {
|
||||
$data = file_get_contents( $_image_path ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty( $data ) ) {
|
||||
$response = wp_safe_remote_get( $image_url );
|
||||
$response_code = wp_remote_retrieve_response_code( $response );
|
||||
if (
|
||||
is_wp_error( $response )
|
||||
|| ! $response_code
|
||||
|| $response_code < 200
|
||||
|| $response_code >= 300
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
$data = wp_remote_retrieve_body( $response );
|
||||
}
|
||||
}
|
||||
|
||||
// If it's a local path in our WordPress install.
|
||||
if ( file_exists( $image_url ) ) {
|
||||
$filetype = wp_check_filetype( $image_url );
|
||||
$type = $filetype['type'];
|
||||
|
||||
if ( str_starts_with( $type, 'image/' ) ) {
|
||||
$data = file_get_contents( $image_url ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
|
||||
}
|
||||
}
|
||||
|
||||
if ( null === $data ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now turn it into an image and return it.
|
||||
return imagecreatefromstring( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct object from image.
|
||||
*
|
||||
* @param string $type Type (hex, rgb, hsv) (optional).
|
||||
*
|
||||
* @return string|bool color as a string formatted as $type or false if the image could not be loaded.
|
||||
*/
|
||||
public function color( $type = 'hex' ) {
|
||||
// Bail if there is no image to work with.
|
||||
if ( ! $this->image_obj ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Finds dominant color.
|
||||
$color = self::grab_color();
|
||||
// Passes value to Color class.
|
||||
return self::get_color( $color, $type );
|
||||
}
|
||||
|
||||
/**
|
||||
* Grabs the color index for each of five sample points of the image
|
||||
*
|
||||
* @param string $type can be 'index' or 'hex'.
|
||||
*
|
||||
* @return array|false color indices or false if the image could not be loaded.
|
||||
*/
|
||||
public function grab_points( $type = 'index' ) {
|
||||
$img = $this->image_obj;
|
||||
if ( ! $img ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$height = imagesy( $img );
|
||||
$width = imagesx( $img );
|
||||
|
||||
/*
|
||||
* Sample five points in the image
|
||||
* based on rule of thirds and center.
|
||||
*/
|
||||
$topy = (int) round( $height / 3 );
|
||||
$bottomy = (int) round( ( $height / 3 ) * 2 );
|
||||
$leftx = (int) round( $width / 3 );
|
||||
$rightx = (int) round( ( $width / 3 ) * 2 );
|
||||
$centery = (int) round( $height / 2 );
|
||||
$centerx = (int) round( $width / 2 );
|
||||
|
||||
// Cast those colors into an array.
|
||||
$points = array(
|
||||
imagecolorat( $img, $leftx, $topy ),
|
||||
imagecolorat( $img, $rightx, $topy ),
|
||||
imagecolorat( $img, $leftx, $bottomy ),
|
||||
imagecolorat( $img, $rightx, $bottomy ),
|
||||
imagecolorat( $img, $centerx, $centery ),
|
||||
);
|
||||
|
||||
if ( 'hex' === $type ) {
|
||||
foreach ( $points as $i => $p ) {
|
||||
$c = imagecolorsforindex( $img, $p );
|
||||
$points[ $i ] = self::get_color(
|
||||
array(
|
||||
'r' => $c['red'],
|
||||
'g' => $c['green'],
|
||||
'b' => $c['blue'],
|
||||
),
|
||||
'hex'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $points;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the average color of the image based on five sample points
|
||||
*
|
||||
* @return array|bool array with rgb color or false if the image could not be loaded.
|
||||
*/
|
||||
public function grab_color() {
|
||||
$img = $this->image_obj;
|
||||
if ( ! $img ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$rgb = self::grab_points();
|
||||
|
||||
$r = array();
|
||||
$g = array();
|
||||
$b = array();
|
||||
|
||||
/*
|
||||
* Process the color points
|
||||
* Find the average representation
|
||||
*/
|
||||
foreach ( $rgb as $color ) {
|
||||
$index = imagecolorsforindex( $img, $color );
|
||||
$r[] = $index['red'];
|
||||
$g[] = $index['green'];
|
||||
$b[] = $index['blue'];
|
||||
}
|
||||
$red = round( array_sum( $r ) / 5 );
|
||||
$green = round( array_sum( $g ) / 5 );
|
||||
$blue = round( array_sum( $b ) / 5 );
|
||||
|
||||
// The average color of the image as rgb array.
|
||||
$color = array(
|
||||
'r' => $red,
|
||||
'g' => $green,
|
||||
'b' => $blue,
|
||||
);
|
||||
|
||||
return $color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Color object using /lib class.color
|
||||
* Convert to appropriate type
|
||||
*
|
||||
* @param string $color Color code.
|
||||
* @param string $type Color type (rgb, hex, hsv).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_color( $color, $type ) {
|
||||
$c = new Jetpack_Color( $color, 'rgb' );
|
||||
$this->color = $c;
|
||||
|
||||
switch ( $type ) {
|
||||
case 'rgb':
|
||||
$color = implode( ',', $c->toRgbInt() );
|
||||
break;
|
||||
case 'hex':
|
||||
$color = $c->toHex();
|
||||
break;
|
||||
case 'hsv':
|
||||
$color = implode( ',', $c->toHsvInt() );
|
||||
break;
|
||||
default:
|
||||
return $c->toHex();
|
||||
}
|
||||
|
||||
return $color;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Checks contrast against main color
|
||||
* Gives either black or white for using with opacity
|
||||
*
|
||||
* @return string|bool Returns black or white or false if the image could not be loaded.
|
||||
*/
|
||||
public function contrast() {
|
||||
if ( ! $this->color ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$c = $this->color->getMaxContrastColor();
|
||||
return implode( ',', $c->toRgbInt() );
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
<?php return array('dependencies' => array('wp-polyfill'), 'version' => 'ec92cd5bc86cbed278e8');
|
||||
+1
@@ -0,0 +1 @@
|
||||
(()=>{function t(t,e){document.querySelectorAll(t).forEach(t=>{for(const[o,c]of Object.entries(e))t.style[o]=c})}function e(t,e,o){document.querySelectorAll(t).forEach(t=>{!1===e?(t.style.clip="rect(1px, 1px, 1px, 1px)",t.style.height="1px",t.style.overflow="hidden",t.style.position="absolute",t.style.width="1px",document.body.classList.add(o)):(t.style.clip="auto",t.style.height="auto",t.style.overflow="visible",t.style.position="relative",t.style.width="auto",document.body.classList.remove(o))})}wp.customize("jetpack_content_blog_display",function(e){function o(e){const o=".jetpack-blog-display.jetpack-the-content",c=".jetpack-blog-display.jetpack-the-excerpt",n=".featured-content .jetpack-blog-display";if("content"===e?(t(`${c}, ${n}.jetpack-the-excerpt`,{clip:"rect(1px, 1px, 1px, 1px)",position:"absolute"}),t(`${o}, ${n}.jetpack-the-content`,{clip:"auto",position:"relative"})):"excerpt"===e?(t(`${o}, ${n}.jetpack-the-content`,{clip:"rect(1px, 1px, 1px, 1px)",position:"absolute"}),t(`${c}, ${n}.jetpack-the-excerpt`,{clip:"auto",position:"relative"})):"mixed"===e&&(t(`${o}.output-the-content, ${n}.jetpack-the-content.output-the-content`,{clip:"auto",position:"relative"}),t(`${c}.output-the-content, ${o}.output-the-excerpt, ${n}.jetpack-the-excerpt.output-the-content, ${n}.jetpack-the-content.output-the-excerpt`,{clip:"rect(1px, 1px, 1px, 1px)",position:"absolute"}),t(`${c}.output-the-excerpt, ${n}.jetpack-the-excerpt.output-the-excerpt`,{clip:"auto",position:"relative"})),blogDisplay.masonry){const t=document.querySelector(blogDisplay.masonry);t&&t.masonry()}}o(blogDisplay.display),e.bind(o)}),wp.customize("jetpack_content_post_details_date",function(t){t.bind(function(t){e(postDetails.date,t,"date-hidden")})}),wp.customize("jetpack_content_post_details_categories",function(t){t.bind(function(t){e(postDetails.categories,t,"categories-hidden")})}),wp.customize("jetpack_content_post_details_tags",function(t){t.bind(function(t){e(postDetails.tags,t,"tags-hidden")})}),wp.customize("jetpack_content_post_details_author",function(t){t.bind(function(t){e(postDetails.author,t,"author-hidden")})}),wp.customize("jetpack_content_post_details_comment",function(t){t.bind(function(t){e(postDetails.comment,t,"comment-hidden")})})})();
|
||||
+1
@@ -0,0 +1 @@
|
||||
<?php return array('dependencies' => array('wp-polyfill'), 'version' => 'c2430c688e89dabcc444');
|
||||
+1
@@ -0,0 +1 @@
|
||||
!function(){let e,t;const n=new Set,a={init:function(o){let r=o.lastElementChild;for(;r&&"TBODY"!==r.tagName;)r=r.previousElementSibling;const c=r.querySelector("tr:first-child").cloneNode(!0);return o.dataset.form=o.closest("form"),o.dataset.tbody=r,o.dataset.row=c,o.dataset.currentRow=c,e=document.getElementById("nova-menu-tax"),t=document.getElementById("_wpnonce"),o.addEventListener("keypress",function(e){13===e.which&&(e.preventDefault(),"function"==typeof FormData&&a.submitRow.call(o),a.addRow.call(o))}),o.addEventListener("focusin",function(e){"INPUT"!==e.target.tagName&&"TEXTAREA"!==e.target.tagName||(o.dataset.currentRow=e.target.closest("tr"))}),n.add(o),o},destroy:function(e){return e.removeEventListener("keypress",a.keypressHandler),e.removeEventListener("focusin",a.focusinHandler),n.delete(e),e},submitRow:function(n){const a=n.dataset.currentRow,o=a.querySelectorAll("input, textarea, select"),r=document.querySelector(n.dataset.form),c=Array.from(r.querySelectorAll("input, textarea, select"));o.forEach(e=>e.disabled=!0),c.filter(e=>!o.includes(e)).forEach(e=>e.disabled=!0);const s=new FormData(r);return s.append("ajax","1"),s.append("nova_menu_tax",e.value),s.append("_wpnonce",t.value),fetch("",{method:"POST",body:s}).then(e=>e.text()).then(e=>{a.innerHTML=e}),c.forEach(e=>e.disabled=!1),n},addRow:function(e){const t=e.dataset.row.cloneNode(!0);e.dataset.tbody.appendChild(t);const n=t.querySelector("input, textarea, select");return n&&n.focus(),e},clickAddRow:function(e){let t=e.lastElementChild;for(;t&&"TBODY"!==t.tagName;)t=t.previousElementSibling;const n=t.querySelector("tr:first-child").cloneNode(!0);n.querySelectorAll("input, textarea").forEach(e=>{e.value=""}),t.appendChild(n)}};document.addEventListener("focusin",e=>{const t=e.target.closest(".many-items-table");t&&!n.has(t)&&a.init(t)}),document.addEventListener("click",e=>{if(e.target.matches("a.nova-new-row")){const t=e.target.closest(".many-items-table");t&&(e.preventDefault(),a.clickAddRow(t))}}),new MutationObserver(e=>{e.forEach(e=>{e.removedNodes.forEach(e=>{e.matches&&e.matches(".many-items-table")&&a.destroy(e)})})}).observe(document.body,{childList:!0,subtree:!0})}();
|
||||
+1
@@ -0,0 +1 @@
|
||||
<?php return array('dependencies' => array('wp-polyfill'), 'version' => 'f46bf3b337b2918909f5');
|
||||
+1
@@ -0,0 +1 @@
|
||||
!function(){const e={inputs:null,popInputs:null,initialize:function(){e.popInputs=document.querySelectorAll('#nova_menuchecklist-pop input[type="checkbox"]'),e.inputs=document.querySelectorAll('#nova_menuchecklist input[type="checkbox"]'),e.inputs.forEach(c=>{c.addEventListener("change",e.checkOne),c.addEventListener("change",e.syncPop)}),e.isChecked()||e.checkFirst(),e.syncPop()},syncPop:function(){e.popInputs.forEach(e=>{const c=document.querySelector(`#in-nova_menu-${e.value}`);e.checked=!!c&&c.checked})},isChecked:function(){return Array.from(e.inputs).some(e=>e.checked)},checkFirst:function(){const c=e.inputs[0];c&&(c.checked=!0)},checkOne:function(){const c=this;c.checked?e.inputs.forEach(e=>{e!==c&&(e.checked=!1)}):document.querySelector("#nova_menuchecklist").querySelectorAll('input[type="checkbox"]:checked').length>0?c.checked=!1:e.checkFirst()}};document.addEventListener("DOMContentLoaded",e.initialize)}();
|
||||
+1
@@ -0,0 +1 @@
|
||||
<?php return array('dependencies' => array('wp-polyfill'), 'version' => 'e0795360b42bfd5b9cf3');
|
||||
+1
@@ -0,0 +1 @@
|
||||
!function(e){let n;e(document).ready(function(){n=e("#the-list"),n.sortable({cancel:".no-items, .inline-edit-row",stop:function(t,r){if(r.item.is(":first-child"))return n.sortable("cancel");n.find(".menu-label-row").each(function(){const n=e(this).data("term_id");e(this).nextUntil(".menu-label-row").each(function(t){const r=e(this);r.find(".menu-order-value").val(t),r.find(".nova-menu-term").val(n)})})}}),e("#posts-filter").append('<input type="hidden" name="'+_novaDragDrop.nonceName+'" value="'+_novaDragDrop.nonce+'" />'),e(".tablenav").prepend('<input type="submit" class="button-primary button-reorder alignright" value="'+_novaDragDrop.reorder+'" name="'+_novaDragDrop.reorderName+'" />'),e("#posts-filter").attr("method","post")})}(jQuery);
|
||||
+1
@@ -0,0 +1 @@
|
||||
<?php return array('dependencies' => array(), 'version' => '63aaeb55a4d4b3de1a88');
|
||||
+1
@@ -0,0 +1 @@
|
||||
jQuery(function(a){a("#customize-control-featured-content-tag-name input").suggest(ajaxurl+"?action=ajax-tag-search&tax=post_tag",{delay:500,minchars:2})});
|
||||
+1
@@ -0,0 +1 @@
|
||||
<?php return array('dependencies' => array('wp-polyfill'), 'version' => '1a16f71f21c6d197f51b');
|
||||
+1
@@ -0,0 +1 @@
|
||||
.jetpack-video-wrapper{margin-bottom:1.6em}.jetpack-video-wrapper>.wp-video,.jetpack-video-wrapper>embed,.jetpack-video-wrapper>iframe,.jetpack-video-wrapper>object{margin-bottom:0}
|
||||
+1
@@ -0,0 +1 @@
|
||||
(()=>{"use strict";var t={687(){}},e={};(function i(r){var n=e[r];if(void 0!==n)return n.exports;var o=e[r]={exports:{}};return t[r](o,o.exports,i),o.exports})(687);let i;function r(){document.querySelectorAll(".jetpack-video-wrapper").forEach(function(t){t.querySelectorAll("embed, iframe, object").forEach(function(e){let i=0;const r=t.previousElementSibling;r&&"P"===r.nodeName&&"center"===getComputedStyle(r)["text-align"]&&(i="0 auto"),e.hasAttribute("data-ratio")||(e.setAttribute("data-ratio",(e.height||0)/(e.width||0)),e.setAttribute("data-width",e.width),e.setAttribute("data-height",e.height),e.style.display="block",e.style.margin=i);const n=e.getAttribute("data-height"),o=e.getAttribute("data-ratio"),a=e.parentElement.clientWidth;if(e.removeAttribute("height"),e.removeAttribute("width"),"Infinity"===o)return e.style.width="100%",void(e.style.height=n+"px");const d=e.getAttribute("data-width");parseInt(d,10)>a?(e.style.width=a+"px",e.style.height=a*parseFloat(o)+"px"):(e.style.width=d+"px",e.style.height=n+"px")})})}function n(){window.addEventListener("load",r),window.addEventListener("resize",function(){clearTimeout(i),i=setTimeout(r,500)}),window.addEventListener("is.post-load",r),setTimeout(r)}"loading"!==document.readyState?n():document.addEventListener("DOMContentLoaded",n)})();
|
||||
+1
@@ -0,0 +1 @@
|
||||
.jetpack-video-wrapper{margin-bottom:1.6em}.jetpack-video-wrapper>.wp-video,.jetpack-video-wrapper>embed,.jetpack-video-wrapper>iframe,.jetpack-video-wrapper>object{margin-bottom:0}
|
||||
+779
@@ -0,0 +1,779 @@
|
||||
<?php
|
||||
/**
|
||||
* Theme Tools: functions for Featured Content enhancements.
|
||||
*
|
||||
* @package automattic/jetpack-classic-theme-helper
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Classic_Theme_Helper;
|
||||
|
||||
use Automattic\Jetpack\Assets;
|
||||
use WP_Customize_Manager;
|
||||
use WP_Query;
|
||||
if ( ! class_exists( __NAMESPACE__ . '\Featured_Content' ) ) {
|
||||
|
||||
/**
|
||||
* Featured Content.
|
||||
*
|
||||
* This module will allow users to define a subset of posts to be displayed in a
|
||||
* theme-designated featured content area.
|
||||
*
|
||||
* This feature will only be activated for themes that declare that they support
|
||||
* it. This can be done by adding code similar to the following during the
|
||||
* "after_setup_theme" action:
|
||||
*
|
||||
* add_theme_support( 'featured-content', array(
|
||||
* 'filter' => 'mytheme_get_featured_content',
|
||||
* 'max_posts' => 20,
|
||||
* 'post_types' => array( 'post', 'page' ),
|
||||
* ) );
|
||||
*
|
||||
* For maximum compatibility with different methods of posting users will
|
||||
* designate a featured post tag to associate posts with. Since this tag now has
|
||||
* special meaning beyond that of a normal tags, users will have the ability to
|
||||
* hide it from the front-end of their site.
|
||||
*/
|
||||
class Featured_Content {
|
||||
|
||||
/**
|
||||
* The maximum number of posts that a Featured Content area can contain. We
|
||||
* define a default value here but themes can override this by defining a
|
||||
* "max_posts" entry in the second parameter passed in the call to
|
||||
* add_theme_support( 'featured-content' ).
|
||||
*
|
||||
* @see Featured_Content::init()
|
||||
* @var int
|
||||
*/
|
||||
public static $max_posts = 15;
|
||||
|
||||
/**
|
||||
* The registered post types supported by Featured Content. Themes can add
|
||||
* Featured Content support for registered post types by defining a
|
||||
* 'post_types' argument (string|array) in the call to
|
||||
* add_theme_support( 'featured-content' ).
|
||||
*
|
||||
* @see Featured_Content::init()
|
||||
* @var array
|
||||
*/
|
||||
public static $post_types = array( 'post' );
|
||||
|
||||
/**
|
||||
* The tag that is used to mark featured content. Users can define
|
||||
* a custom tag name that will be stored in this variable.
|
||||
*
|
||||
* @see Featured_Content::hide_featured_term
|
||||
* @var string
|
||||
*/
|
||||
public static $tag;
|
||||
|
||||
/**
|
||||
* Instantiate.
|
||||
*
|
||||
* All custom functionality will be hooked into the "init" action.
|
||||
*/
|
||||
public static function setup() {
|
||||
add_action( 'init', array( __CLASS__, 'init' ), 30 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Conditionally hook into WordPress.
|
||||
*
|
||||
* Themes must declare that they support this module by adding
|
||||
* add_theme_support( 'featured-content' ); during after_setup_theme.
|
||||
*
|
||||
* If no theme support is found there is no need to hook into WordPress. We'll
|
||||
* just return early instead.
|
||||
*
|
||||
* @uses Featured_Content::$max_posts
|
||||
*/
|
||||
public static function init() {
|
||||
|
||||
if ( isset( $GLOBALS['pagenow'] ) && 'plugins.php' === $GLOBALS['pagenow'] ) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Array variable to store theme support.
|
||||
*
|
||||
* @var array[] $theme_support
|
||||
*/
|
||||
$theme_support = get_theme_support( 'featured-content' );
|
||||
|
||||
// Return early if theme does not support featured content.
|
||||
if ( ! $theme_support ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* An array of named arguments must be passed as the second parameter
|
||||
* of add_theme_support().
|
||||
*/
|
||||
if ( ! isset( $theme_support[0] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( isset( $theme_support[0]['featured_content_filter'] ) ) {
|
||||
$theme_support[0]['filter'] = $theme_support[0]['featured_content_filter'];
|
||||
unset( $theme_support[0]['featured_content_filter'] );
|
||||
}
|
||||
|
||||
// Return early if "filter" has not been defined.
|
||||
if ( ! isset( $theme_support[0]['filter'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Theme can override the number of max posts.
|
||||
if ( isset( $theme_support[0]['max_posts'] ) ) {
|
||||
self::$max_posts = absint( $theme_support[0]['max_posts'] );
|
||||
}
|
||||
|
||||
add_filter( $theme_support[0]['filter'], array( __CLASS__, 'get_featured_posts' ) );
|
||||
if ( ! wp_is_block_theme() ) {
|
||||
add_action( 'customize_register', array( __CLASS__, 'customize_register' ), 9 );
|
||||
}
|
||||
add_action( 'admin_init', array( __CLASS__, 'register_setting' ) );
|
||||
add_action( 'save_post', array( __CLASS__, 'delete_transient' ) );
|
||||
add_action( 'delete_post_tag', array( __CLASS__, 'delete_post_tag' ) );
|
||||
add_action( 'customize_controls_enqueue_scripts', array( __CLASS__, 'enqueue_scripts' ) );
|
||||
add_action( 'pre_get_posts', array( __CLASS__, 'pre_get_posts' ) );
|
||||
add_action( 'switch_theme', array( __CLASS__, 'switch_theme' ) );
|
||||
add_action( 'switch_theme', array( __CLASS__, 'delete_transient' ) );
|
||||
add_action( 'wp_loaded', array( __CLASS__, 'wp_loaded' ) );
|
||||
add_action( 'update_option_featured-content', array( __CLASS__, 'flush_post_tag_cache' ), 10, 2 );
|
||||
add_action( 'delete_option_featured-content', array( __CLASS__, 'flush_post_tag_cache' ), 10, 2 );
|
||||
add_action( 'split_shared_term', array( __CLASS__, 'jetpack_update_featured_content_for_split_terms' ), 10, 4 );
|
||||
|
||||
if ( isset( $theme_support[0]['additional_post_types'] ) ) {
|
||||
$theme_support[0]['post_types'] = array_merge( array( 'post' ), (array) $theme_support[0]['additional_post_types'] );
|
||||
unset( $theme_support[0]['additional_post_types'] );
|
||||
}
|
||||
|
||||
// Themes can allow Featured Content pages.
|
||||
if ( isset( $theme_support[0]['post_types'] ) ) {
|
||||
self::$post_types = array_merge( self::$post_types, (array) $theme_support[0]['post_types'] );
|
||||
self::$post_types = array_unique( self::$post_types );
|
||||
|
||||
// register post_tag support for each post type.
|
||||
foreach ( self::$post_types as $post_type ) {
|
||||
register_taxonomy_for_object_type( 'post_tag', $post_type );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide "featured" tag from the front-end.
|
||||
*
|
||||
* Has to run on wp_loaded so that the preview filters of the customizer
|
||||
* have a chance to alter the value.
|
||||
*/
|
||||
public static function wp_loaded() {
|
||||
if ( self::get_setting( 'hide-tag' ) ) {
|
||||
$settings = self::get_setting();
|
||||
|
||||
// This is done before setting filters for get_terms in order to avoid an infinite filter loop.
|
||||
self::$tag = get_term_by( 'name', $settings['tag-name'], 'post_tag' );
|
||||
|
||||
add_filter( 'get_terms', array( __CLASS__, 'hide_featured_term' ), 10, 3 );
|
||||
add_filter( 'get_the_terms', array( __CLASS__, 'hide_the_featured_term' ), 10, 3 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get featured posts
|
||||
*
|
||||
* This method is not intended to be called directly. Theme developers should
|
||||
* place a filter directly in their theme and then pass its name as a value of
|
||||
* the "filter" key in the array passed as the $args parameter during the call
|
||||
* to: add_theme_support( 'featured-content', $args ).
|
||||
*
|
||||
* @uses Featured_Content::get_featured_post_ids()
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_featured_posts() {
|
||||
$post_ids = self::get_featured_post_ids();
|
||||
|
||||
// No need to query if there is are no featured posts.
|
||||
if ( empty( $post_ids ) ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$featured_posts = get_posts(
|
||||
array(
|
||||
'include' => $post_ids,
|
||||
'posts_per_page' => count( $post_ids ),
|
||||
'post_type' => self::$post_types,
|
||||
'suppress_filters' => false,
|
||||
)
|
||||
);
|
||||
|
||||
return $featured_posts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get featured post IDs
|
||||
*
|
||||
* This function will return the an array containing the post IDs of all
|
||||
* featured posts.
|
||||
*
|
||||
* Sets the "featured_content_ids" transient.
|
||||
*
|
||||
* @return array Array of post IDs.
|
||||
*/
|
||||
public static function get_featured_post_ids() {
|
||||
// Return array of cached results if they exist.
|
||||
$featured_ids = get_transient( 'featured_content_ids' );
|
||||
if ( ! empty( $featured_ids ) ) {
|
||||
return array_map(
|
||||
'absint',
|
||||
/**
|
||||
* Filter the list of Featured Posts IDs.
|
||||
*
|
||||
* @module theme-tools
|
||||
*
|
||||
* @since 2.7.0
|
||||
*
|
||||
* @param array $featured_ids Array of post IDs.
|
||||
*/
|
||||
apply_filters( 'featured_content_post_ids', (array) $featured_ids )
|
||||
);
|
||||
}
|
||||
|
||||
$settings = self::get_setting();
|
||||
|
||||
// Return empty array if no tag name is set.
|
||||
$term = get_term_by( 'name', $settings['tag-name'], 'post_tag' );
|
||||
if ( ! $term ) {
|
||||
$term = get_term_by( 'id', $settings['tag-id'], 'post_tag' );
|
||||
}
|
||||
if ( $term ) {
|
||||
$tag = $term->term_id;
|
||||
} else {
|
||||
/** This action is documented in modules/theme-tools/featured-content.php */
|
||||
return apply_filters( 'featured_content_post_ids', array() );
|
||||
}
|
||||
|
||||
// Back compat for installs that have the quantity option still set.
|
||||
$quantity = $settings['quantity'] ?? self::$max_posts;
|
||||
|
||||
// Query for featured posts.
|
||||
$featured = get_posts(
|
||||
array(
|
||||
'numberposts' => $quantity,
|
||||
'post_type' => self::$post_types,
|
||||
'suppress_filters' => false,
|
||||
'tax_query' => array(
|
||||
array(
|
||||
'field' => 'term_id',
|
||||
'taxonomy' => 'post_tag',
|
||||
'terms' => $tag,
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
// Return empty array if no featured content exists.
|
||||
if ( ! $featured ) {
|
||||
/** This action is documented in modules/theme-tools/featured-content.php */
|
||||
return apply_filters( 'featured_content_post_ids', array() );
|
||||
}
|
||||
|
||||
// Ensure correct format before save/return.
|
||||
$featured_ids = wp_list_pluck( (array) $featured, 'ID' );
|
||||
$featured_ids = array_map( 'absint', $featured_ids );
|
||||
|
||||
set_transient( 'featured_content_ids', $featured_ids );
|
||||
|
||||
/** This action is documented in modules/theme-tools/featured-content.php */
|
||||
return apply_filters( 'featured_content_post_ids', $featured_ids );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete Transient.
|
||||
*
|
||||
* Hooks in the "save_post" action.
|
||||
*
|
||||
* @see Featured_Content::validate_settings().
|
||||
*/
|
||||
public static function delete_transient() {
|
||||
delete_transient( 'featured_content_ids' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the Post Tag relationships cache.
|
||||
*
|
||||
* Hooks in the "update_option_featured-content" action.
|
||||
*
|
||||
* @param array $prev Previous option data.
|
||||
* @param array $opts New option data.
|
||||
*/
|
||||
public static function flush_post_tag_cache( $prev, $opts ) {
|
||||
if ( ! empty( $opts ) && ! empty( $opts['tag-id'] ) ) {
|
||||
$query = new WP_Query(
|
||||
array(
|
||||
'tag_id' => (int) $opts['tag-id'],
|
||||
'posts_per_page' => -1,
|
||||
)
|
||||
);
|
||||
foreach ( $query->posts as $post ) {
|
||||
wp_cache_delete( $post->ID, 'post_tag_relationships' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exclude featured posts from the blog query when the blog is the front-page,
|
||||
* and user has not checked the "Also display tagged posts outside the Featured Content area" checkbox.
|
||||
*
|
||||
* Filter the home page posts, and remove any featured post ID's from it.
|
||||
* Hooked onto the 'pre_get_posts' action, this changes the parameters of the
|
||||
* query before it gets any posts.
|
||||
*
|
||||
* @uses Featured_Content::get_featured_post_ids();
|
||||
* @uses Featured_Content::get_setting();
|
||||
* @param WP_Query $query WP_Query object.
|
||||
* @return WP_Query|null Possibly modified WP_Query
|
||||
*/
|
||||
public static function pre_get_posts( $query ) {
|
||||
|
||||
// Bail if not home or not main query.
|
||||
if ( ! $query->is_home() || ! $query->is_main_query() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Bail if the blog page is not the front page.
|
||||
if ( 'posts' !== get_option( 'show_on_front' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$featured = self::get_featured_post_ids();
|
||||
|
||||
// Bail if no featured posts.
|
||||
if ( ! $featured ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$settings = self::get_setting();
|
||||
|
||||
// Bail if the user wants featured posts always displayed.
|
||||
if ( $settings['show-all'] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We need to respect post ids already in the blocklist.
|
||||
$post__not_in = $query->get( 'post__not_in' );
|
||||
|
||||
if ( ! empty( $post__not_in ) ) {
|
||||
$featured = array_merge( (array) $post__not_in, $featured );
|
||||
$featured = array_unique( $featured );
|
||||
}
|
||||
|
||||
$query->set( 'post__not_in', $featured );
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset tag option when the saved tag is deleted.
|
||||
*
|
||||
* It's important to mention that the transient needs to be deleted, too.
|
||||
* While it may not be obvious by looking at the function alone, the transient
|
||||
* is deleted by Featured_Content::validate_settings().
|
||||
*
|
||||
* Hooks in the "delete_post_tag" action.
|
||||
*
|
||||
* @see Featured_Content::validate_settings().
|
||||
*
|
||||
* @param int $tag_id The term_id of the tag that has been deleted.
|
||||
* @return void
|
||||
*/
|
||||
public static function delete_post_tag( $tag_id ) {
|
||||
$settings = self::get_setting();
|
||||
|
||||
if ( empty( $settings['tag-id'] ) || $tag_id != $settings['tag-id'] ) { // phpcs:ignore Universal.Operators.StrictComparisons.LooseNotEqual
|
||||
return;
|
||||
}
|
||||
|
||||
$settings['tag-id'] = 0;
|
||||
$settings = self::validate_settings( $settings );
|
||||
update_option( 'featured-content', $settings );
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide featured tag from displaying when global terms are queried from
|
||||
* the front-end.
|
||||
*
|
||||
* Hooks into the "get_terms" filter.
|
||||
*
|
||||
* @uses Featured_Content::get_setting()
|
||||
*
|
||||
* @param array $terms A list of term objects. This is the return value of get_terms().
|
||||
* @param array $taxonomies An array of taxonomy slugs.
|
||||
* @param array $args Array of get_terms() arguments.
|
||||
* @return array $terms
|
||||
*/
|
||||
public static function hide_featured_term( $terms, $taxonomies, $args ) {
|
||||
|
||||
// This filter is only appropriate on the front-end.
|
||||
if ( is_admin() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) || ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) ) {
|
||||
return $terms;
|
||||
}
|
||||
|
||||
// WordPress defines the parameter as `array`, but it passes null if `get_terms( $args )` was called
|
||||
// without a 'taxonomy' in $args.
|
||||
if ( ! is_array( $taxonomies ) ) {
|
||||
return $terms;
|
||||
}
|
||||
|
||||
// We only want to hide the featured tag.
|
||||
if ( ! in_array( 'post_tag', $taxonomies, true ) ) {
|
||||
return $terms;
|
||||
}
|
||||
|
||||
// Bail if no terms were returned.
|
||||
if ( empty( $terms ) ) {
|
||||
return $terms;
|
||||
}
|
||||
|
||||
// Bail if term objects are unavailable.
|
||||
if ( 'all' !== $args['fields'] ) {
|
||||
return $terms;
|
||||
}
|
||||
|
||||
$settings = self::get_setting();
|
||||
|
||||
if ( false !== self::$tag ) {
|
||||
foreach ( $terms as $order => $term ) {
|
||||
if (
|
||||
is_object( $term )
|
||||
&& (
|
||||
$settings['tag-id'] === $term->term_id
|
||||
|| $settings['tag-name'] === $term->name
|
||||
)
|
||||
) {
|
||||
unset( $terms[ $order ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $terms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide featured tag from displaying when terms associated with a post object
|
||||
* are queried from the front-end.
|
||||
*
|
||||
* Hooks into the "get_the_terms" filter.
|
||||
*
|
||||
* @uses Featured_Content::get_setting()
|
||||
*
|
||||
* @param \WP_Term[]|\WP_Error $terms A list of term objects. This is the return value of get_the_terms().
|
||||
* @param int $id The ID field for the post object that terms are associated with.
|
||||
* @param string $taxonomy The slug of the taxonomy.
|
||||
* @return \WP_Term[]|\WP_Error $terms
|
||||
*/
|
||||
public static function hide_the_featured_term( $terms, $id, $taxonomy ) {
|
||||
|
||||
// This filter is only appropriate on the front-end.
|
||||
if ( is_admin() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) || ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) ) {
|
||||
return $terms;
|
||||
}
|
||||
|
||||
// This could be a WP_Error or something invalid from another hook function.
|
||||
if ( ! is_array( $terms ) ) {
|
||||
return $terms;
|
||||
}
|
||||
|
||||
// Make sure we are in the correct taxonomy.
|
||||
if ( 'post_tag' !== $taxonomy ) {
|
||||
return $terms;
|
||||
}
|
||||
|
||||
// No terms? Return early!
|
||||
if ( empty( $terms ) ) {
|
||||
return $terms;
|
||||
}
|
||||
|
||||
$settings = self::get_setting();
|
||||
$tag = get_term_by( 'name', $settings['tag-name'], 'post_tag' );
|
||||
|
||||
if ( false !== $tag ) {
|
||||
foreach ( $terms as $order => $term ) {
|
||||
if ( ! $term ) {
|
||||
continue;
|
||||
}
|
||||
if ( $settings['tag-id'] === $term->term_id || $settings['tag-name'] === $term->name ) {
|
||||
unset( $terms[ $order ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $terms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register custom setting on the Settings -> Reading screen.
|
||||
*
|
||||
* @uses Featured_Content::render_form()
|
||||
* @uses Featured_Content::validate_settings()
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function register_setting() {
|
||||
add_settings_field( 'featured-content', __( 'Featured Content', 'jetpack-classic-theme-helper' ), array( __CLASS__, 'render_form' ), 'reading' );
|
||||
|
||||
// Register sanitization callback for the Customizer.
|
||||
register_setting( 'featured-content', 'featured-content', array( __CLASS__, 'validate_settings' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add settings to the Customizer.
|
||||
*
|
||||
* @param WP_Customize_Manager $wp_customize Theme Customizer object.
|
||||
*/
|
||||
public static function customize_register( $wp_customize ) {
|
||||
$wp_customize->add_section(
|
||||
'featured_content',
|
||||
array(
|
||||
'title' => esc_html__( 'Featured Content', 'jetpack-classic-theme-helper' ),
|
||||
'description' => wp_kses(
|
||||
sprintf(
|
||||
/* translators: %1$s: Link to 'featured' admin tag view. %2$s: Max number of posts shown by theme in featured content area. */
|
||||
__( 'Easily feature all posts with the <a href="%1$s">"featured" tag</a> or a tag of your choice. Your theme supports up to %2$s posts in its featured content area.<br><br>Please note: The featured tag name is case sensitive.', 'jetpack-classic-theme-helper' ),
|
||||
esc_url( admin_url( '/edit.php?tag=featured' ) ),
|
||||
absint( self::$max_posts )
|
||||
),
|
||||
array(
|
||||
'a' => array(
|
||||
'href' => array(),
|
||||
),
|
||||
'br' => array(),
|
||||
)
|
||||
),
|
||||
'priority' => 130,
|
||||
'theme_supports' => 'featured-content',
|
||||
)
|
||||
);
|
||||
|
||||
/*
|
||||
Add Featured Content settings.
|
||||
*
|
||||
* Sanitization callback registered in Featured_Content::validate_settings().
|
||||
* See https://themeshaper.com/2013/04/29/validation-sanitization-in-customizer/comment-page-1/#comment-12374
|
||||
*/
|
||||
$wp_customize->add_setting(
|
||||
'featured-content[tag-name]',
|
||||
array(
|
||||
'type' => 'option',
|
||||
'sanitize_js_callback' => array( __CLASS__, 'delete_transient' ),
|
||||
)
|
||||
);
|
||||
$wp_customize->add_setting(
|
||||
'featured-content[hide-tag]',
|
||||
array(
|
||||
'default' => true,
|
||||
'type' => 'option',
|
||||
'sanitize_js_callback' => array( __CLASS__, 'delete_transient' ),
|
||||
)
|
||||
);
|
||||
$wp_customize->add_setting(
|
||||
'featured-content[show-all]',
|
||||
array(
|
||||
'default' => false,
|
||||
'type' => 'option',
|
||||
'sanitize_js_callback' => array( __CLASS__, 'delete_transient' ),
|
||||
)
|
||||
);
|
||||
|
||||
// Add Featured Content controls.
|
||||
$wp_customize->add_control(
|
||||
'featured-content[tag-name]',
|
||||
array(
|
||||
'label' => esc_html__( 'Tag name', 'jetpack-classic-theme-helper' ),
|
||||
'section' => 'featured_content',
|
||||
'theme_supports' => 'featured-content',
|
||||
'priority' => 20,
|
||||
)
|
||||
);
|
||||
$wp_customize->add_control(
|
||||
'featured-content[hide-tag]',
|
||||
array(
|
||||
'label' => esc_html__( 'Do not display tag in post details and tag clouds.', 'jetpack-classic-theme-helper' ),
|
||||
'section' => 'featured_content',
|
||||
'theme_supports' => 'featured-content',
|
||||
'type' => 'checkbox',
|
||||
'priority' => 30,
|
||||
)
|
||||
);
|
||||
$wp_customize->add_control(
|
||||
'featured-content[show-all]',
|
||||
array(
|
||||
'label' => esc_html__( 'Also display tagged posts outside the Featured Content area.', 'jetpack-classic-theme-helper' ),
|
||||
'section' => 'featured_content',
|
||||
'theme_supports' => 'featured-content',
|
||||
'type' => 'checkbox',
|
||||
'priority' => 40,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue the tag suggestion script.
|
||||
*/
|
||||
public static function enqueue_scripts() {
|
||||
Assets::register_script(
|
||||
'featured-content-suggest',
|
||||
'../dist/featured-content/suggest.js',
|
||||
__FILE__,
|
||||
array(
|
||||
'dependencies' => array(
|
||||
'jquery',
|
||||
'suggest',
|
||||
),
|
||||
'in_footer' => true,
|
||||
'enqueue' => true,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders all form fields on the Settings -> Reading screen.
|
||||
*/
|
||||
public static function render_form() {
|
||||
printf(
|
||||
wp_kses(
|
||||
/* translators: %s: Link to the Featured Content settings in the Customizer. */
|
||||
__( 'The settings for Featured Content have <a href="%s">moved to Appearance → Customize</a>.', 'jetpack-classic-theme-helper' ),
|
||||
array(
|
||||
'a' => array( 'href' => array() ),
|
||||
)
|
||||
),
|
||||
esc_url( admin_url( 'customize.php?#accordion-section-featured_content' ) )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get settings
|
||||
*
|
||||
* Get all settings recognized by this module. This function will return all
|
||||
* settings whether or not they have been stored in the database yet. This
|
||||
* ensures that all keys are available at all times.
|
||||
*
|
||||
* In the event that you only require one setting, you may pass its name as the
|
||||
* first parameter to the function and only that value will be returned.
|
||||
*
|
||||
* @param string $key The key of a recognized setting.
|
||||
* @return mixed Array of all settings by default. A single value if passed as first parameter.
|
||||
*/
|
||||
public static function get_setting( $key = 'all' ) {
|
||||
$saved = (array) get_option( 'featured-content' );
|
||||
|
||||
/**
|
||||
* Filter Featured Content's default settings.
|
||||
*
|
||||
* @module theme-tools
|
||||
*
|
||||
* @since 2.7.0
|
||||
*
|
||||
* @param array $args {
|
||||
* Array of Featured Content Settings
|
||||
*
|
||||
* @type int hide-tag Default is 1.
|
||||
* @type int tag-id Default is 0.
|
||||
* @type string tag-name Default is empty.
|
||||
* @type int show-all Default is 0.
|
||||
* }
|
||||
*/
|
||||
$defaults = apply_filters(
|
||||
'featured_content_default_settings',
|
||||
array(
|
||||
'hide-tag' => 1,
|
||||
'tag-id' => 0,
|
||||
'tag-name' => '',
|
||||
'show-all' => 0,
|
||||
)
|
||||
);
|
||||
|
||||
$options = wp_parse_args( $saved, $defaults );
|
||||
$options = array_intersect_key( $options, $defaults );
|
||||
|
||||
if ( 'all' !== $key ) {
|
||||
return $options[ $key ] ?? false;
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate settings
|
||||
*
|
||||
* Make sure that all user supplied content is in an expected format before
|
||||
* saving to the database. This function will also delete the transient set in
|
||||
* Featured_Content::get_featured_content().
|
||||
*
|
||||
* @uses Featured_Content::delete_transient()
|
||||
*
|
||||
* @param array $input Array of settings input.
|
||||
* @return array $output
|
||||
*/
|
||||
public static function validate_settings( $input ) {
|
||||
$output = array();
|
||||
|
||||
if ( empty( $input['tag-name'] ) ) {
|
||||
$output['tag-id'] = 0;
|
||||
} else {
|
||||
$term = get_term_by( 'name', $input['tag-name'], 'post_tag' );
|
||||
|
||||
if ( $term ) {
|
||||
$output['tag-id'] = $term->term_id;
|
||||
} else {
|
||||
$new_tag = wp_create_tag( $input['tag-name'] );
|
||||
|
||||
if ( ! is_wp_error( $new_tag ) && isset( $new_tag['term_id'] ) ) {
|
||||
$output['tag-id'] = $new_tag['term_id'];
|
||||
}
|
||||
}
|
||||
|
||||
$output['tag-name'] = $input['tag-name'];
|
||||
}
|
||||
|
||||
$output['hide-tag'] = isset( $input['hide-tag'] ) && $input['hide-tag'] ? 1 : 0;
|
||||
|
||||
$output['show-all'] = isset( $input['show-all'] ) && $input['show-all'] ? 1 : 0;
|
||||
|
||||
self::delete_transient();
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the quantity setting from the options array.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function switch_theme() {
|
||||
$option = (array) get_option( 'featured-content' );
|
||||
|
||||
if ( isset( $option['quantity'] ) ) {
|
||||
unset( $option['quantity'] );
|
||||
update_option( 'featured-content', $option );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Featured Content term data as necessary when a shared term is split.
|
||||
*
|
||||
* @param int $old_term_id ID of the formerly shared term.
|
||||
* @param int $new_term_id ID of the new term created for the $term_taxonomy_id.
|
||||
* @param int $term_taxonomy_id ID for the term_taxonomy row affected by the split.
|
||||
* @param string $taxonomy Taxonomy for the split term.
|
||||
*/
|
||||
public static function jetpack_update_featured_content_for_split_terms( $old_term_id, $new_term_id, $term_taxonomy_id, $taxonomy ) {
|
||||
$featured_content_settings = get_option( 'featured-content', array() );
|
||||
|
||||
// Check to see whether the stored tag ID is the one that's just been split.
|
||||
if ( isset( $featured_content_settings['tag-id'] ) && $old_term_id == $featured_content_settings['tag-id'] && 'post_tag' === $taxonomy ) { // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual
|
||||
// We have a match, so we swap out the old tag ID for the new one and resave the option.
|
||||
$featured_content_settings['tag-id'] = $new_term_id;
|
||||
update_option( 'featured-content', $featured_content_settings );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
/**
|
||||
* Package description here
|
||||
*
|
||||
* @package automattic/jetpack-classic-theme-helper
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Classic_Theme_Helper;
|
||||
|
||||
use WP_Error;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Classic Theme Helper Loader.
|
||||
*/
|
||||
class Main {
|
||||
|
||||
const PACKAGE_VERSION = '0.14.34';
|
||||
|
||||
/**
|
||||
* Modules to include.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $modules = array(
|
||||
'custom-content-types.php',
|
||||
'responsive-videos.php',
|
||||
'site-breadcrumbs.php',
|
||||
'social-menu.php',
|
||||
'jetpack-color.php',
|
||||
'content-options.php',
|
||||
);
|
||||
|
||||
/** Holds the singleton instance of the Loader
|
||||
*
|
||||
* @var Main
|
||||
*/
|
||||
public static $instance = null;
|
||||
|
||||
/**
|
||||
* Initialize the Loader.
|
||||
*/
|
||||
public static function init() {
|
||||
if ( ! self::$instance ) {
|
||||
self::$instance = new Main();
|
||||
self::$instance->load_modules();
|
||||
add_action( 'init', array( __CLASS__, 'jetpack_load_theme_tools' ), 30 );
|
||||
add_action( 'after_setup_theme', array( __CLASS__, 'classic_theme_helper_load_theme_compat' ), -1 );
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load modules.
|
||||
*/
|
||||
public function load_modules() {
|
||||
|
||||
// Filter the modules to include.
|
||||
// $since = 0.1.0
|
||||
// @param array $modules Array of modules to include.
|
||||
$modules = apply_filters( 'jetpack_classic_theme_helper_modules', $this->modules );
|
||||
foreach ( $modules as $module ) {
|
||||
require_once __DIR__ . '/' . $module;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Conditionally require the Tonesque lib depending on theme support.
|
||||
*/
|
||||
public static function jetpack_load_theme_tools() {
|
||||
if ( current_theme_supports( 'tonesque' ) ) {
|
||||
require_once __DIR__ . '/../_inc/lib/tonesque.php';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load theme compat file if it exists.
|
||||
*/
|
||||
public static function classic_theme_helper_load_theme_compat() {
|
||||
|
||||
/**
|
||||
* Filter theme compat files.
|
||||
*
|
||||
* Themes can add their own compat files here if they like. For example:
|
||||
*
|
||||
* add_filter( 'classic_theme_helper_theme_compat_files', 'mytheme_classic_theme_helper_theme_compat_file' );
|
||||
* function mytheme_classic_theme_helper_theme_compat_file( $files ) {
|
||||
* $files['mytheme'] = locate_template( 'jetpack-compat.php' );
|
||||
* return $files;
|
||||
* }
|
||||
*
|
||||
* @since 0.2.0
|
||||
*
|
||||
* @param array Associative array of theme compat files to load.
|
||||
*/
|
||||
$compat_files = apply_filters(
|
||||
'classic_theme_helper_theme_compat_files',
|
||||
array(
|
||||
'twentyfourteen' => __DIR__ . '/compat/twentyfourteen.php',
|
||||
'twentyfifteen' => __DIR__ . '/compat/twentyfifteen.php',
|
||||
'twentysixteen' => __DIR__ . '/compat/twentysixteen.php',
|
||||
'twentynineteen' => __DIR__ . '/compat/twentynineteen.php',
|
||||
'twentytwenty' => __DIR__ . '/compat/twentytwenty.php',
|
||||
'twentytwentyone' => __DIR__ . '/compat/twentytwentyone.php',
|
||||
)
|
||||
);
|
||||
|
||||
self::classic_theme_helper_require_compat_file( get_stylesheet(), $compat_files );
|
||||
|
||||
if ( is_child_theme() ) {
|
||||
self::classic_theme_helper_require_compat_file( get_template(), $compat_files );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Requires a file once, if the passed key exists in the files array.
|
||||
*
|
||||
* @param string $key The key to check.
|
||||
* @param array $files Array of files to check in.
|
||||
* @return void|WP_Error
|
||||
*/
|
||||
private static function classic_theme_helper_require_compat_file( $key, $files ) {
|
||||
if ( ! is_string( $key ) ) {
|
||||
return new WP_Error( 'key_not_string', 'The specified key is not actually a string.', compact( 'key' ) );
|
||||
}
|
||||
|
||||
if ( array_key_exists( $key, $files ) && is_readable( $files[ $key ] ) ) {
|
||||
require_once $files[ $key ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Main::init();
|
||||
+272
@@ -0,0 +1,272 @@
|
||||
<?php
|
||||
/**
|
||||
* Theme Tools: Social Links.
|
||||
*
|
||||
* This feature will only be activated for themes that declare their support.
|
||||
* This can be done by adding code similar to the following during the
|
||||
* 'after_setup_theme' action:
|
||||
*
|
||||
* add_theme_support( 'social-links', array(
|
||||
* 'facebook', 'twitter', 'linkedin', 'tumblr',
|
||||
* ) );
|
||||
*
|
||||
* @package automattic/jetpack-classic-theme-helper
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Classic_Theme_Helper;
|
||||
|
||||
use Automattic\Jetpack\Publicize\Publicize;
|
||||
use Jetpack_Options;
|
||||
use WP_Customize_Manager;
|
||||
|
||||
if ( ! class_exists( __NAMESPACE__ . '\Social_Links' ) ) {
|
||||
|
||||
/**
|
||||
* Social_Links main class.
|
||||
*
|
||||
* @phan-constructor-used-for-side-effects
|
||||
*/
|
||||
class Social_Links {
|
||||
|
||||
/**
|
||||
* The links the user set for each service.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $links;
|
||||
|
||||
/**
|
||||
* A Publicize object.
|
||||
*
|
||||
* @var Publicize
|
||||
*/
|
||||
private $publicize;
|
||||
|
||||
/**
|
||||
* An array with all services that are supported by both Publicize and the
|
||||
* currently active theme.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $services = array();
|
||||
|
||||
/**
|
||||
* An array of the services the theme supports
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $theme_supported_services = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
if ( ! ( ! wp_is_block_theme() && current_theme_supports( 'social-links' ) && function_exists( 'publicize_init' ) ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$theme_support = get_theme_support( 'social-links' );
|
||||
|
||||
/*
|
||||
An array of named arguments must be passed as the second parameter
|
||||
* of add_theme_support().
|
||||
*/
|
||||
if ( empty( $theme_support[0] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->theme_supported_services = $theme_support[0];
|
||||
$this->links = class_exists( Jetpack_Options::class ) ? Jetpack_Options::get_option( 'social_links', array() ) : '';
|
||||
|
||||
$this->admin_setup();
|
||||
|
||||
add_filter( 'jetpack_has_social_links', array( $this, 'has_social_links' ) );
|
||||
add_filter( 'jetpack_get_social_links', array( $this, 'get_social_links' ) );
|
||||
|
||||
foreach ( $theme_support[0] as $service ) {
|
||||
add_filter( "pre_option_jetpack-$service", array( $this, 'get_social_link_filter' ) ); // - `get_option( 'jetpack-service' );`
|
||||
add_filter( "theme_mod_jetpack-$service", array( $this, 'get_social_link_filter' ) ); // - `get_theme_mod( 'jetpack-service' );`
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Init the admin setup.
|
||||
*/
|
||||
public function admin_setup() {
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! is_admin() && ! $this->is_customize_preview() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// @phan-suppress-next-line PhanUndeclaredFunction -- See __construct() for the condition that ensures this function exists.
|
||||
$this->publicize = publicize_init();
|
||||
$publicize_services = $this->publicize->get_services( 'connected' );
|
||||
$this->services = array_intersect( array_keys( $publicize_services ), $this->theme_supported_services );
|
||||
|
||||
add_action( 'publicize_connected', array( $this, 'check_links' ), 20 );
|
||||
add_action( 'publicize_disconnected', array( $this, 'check_links' ), 20 );
|
||||
add_action( 'customize_register', array( $this, 'customize_register' ) );
|
||||
add_filter( 'sanitize_option_jetpack_options', array( $this, 'sanitize_link' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the currently saved links with the connected services and removes
|
||||
* links from services that are no longer connected.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function check_links() {
|
||||
$active_links = array_intersect_key( $this->links, array_flip( $this->services ) );
|
||||
|
||||
if ( $active_links !== $this->links ) {
|
||||
$this->links = $active_links;
|
||||
if ( class_exists( Jetpack_Options::class ) ) {
|
||||
Jetpack_Options::update_option( 'social_links', $active_links );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add social link dropdown to the Customizer.
|
||||
*
|
||||
* @param WP_Customize_Manager $wp_customize Theme Customizer object.
|
||||
*/
|
||||
public function customize_register( $wp_customize ) {
|
||||
$wp_customize->add_section(
|
||||
'jetpack_social_links',
|
||||
array(
|
||||
'title' => esc_html__( 'Connect', 'jetpack-classic-theme-helper' ),
|
||||
'priority' => 35,
|
||||
)
|
||||
);
|
||||
|
||||
if ( class_exists( Publicize::class ) ) {
|
||||
foreach ( array_keys( $this->publicize->get_services( 'all' ) ) as $service ) {
|
||||
$choices = $this->get_customize_select( $service );
|
||||
|
||||
if ( empty( $choices ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$wp_customize->add_setting(
|
||||
"jetpack_options[social_links][$service]",
|
||||
array(
|
||||
'type' => 'option',
|
||||
'default' => '',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
"jetpack-$service",
|
||||
array(
|
||||
'label' => $this->publicize->get_service_label( $service ),
|
||||
'section' => 'jetpack_social_links',
|
||||
'settings' => "jetpack_options[social_links][$service]",
|
||||
'type' => 'select',
|
||||
'choices' => $choices,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes social links.
|
||||
*
|
||||
* @param array $option The incoming values to be sanitized.
|
||||
* @return array
|
||||
*/
|
||||
public function sanitize_link( $option ) {
|
||||
foreach ( $this->services as $service ) {
|
||||
if ( ! empty( $option['social_links'][ $service ] ) ) {
|
||||
$option['social_links'][ $service ] = esc_url_raw( $option['social_links'][ $service ] );
|
||||
} else {
|
||||
unset( $option['social_links'][ $service ] );
|
||||
}
|
||||
}
|
||||
|
||||
return $option;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether there are any social links set.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has_social_links() {
|
||||
return ! empty( $this->links );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return available social links.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_social_links() {
|
||||
return $this->links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Short-circuits get_option and get_theme_mod calls.
|
||||
*
|
||||
* @param string $link The incoming value to be replaced.
|
||||
* @return string $link The social link that we've got.
|
||||
*/
|
||||
public function get_social_link_filter( $link ) {
|
||||
if ( preg_match( '/_jetpack-(.+)$/i', current_filter(), $matches ) && ! empty( $this->links[ $matches[1] ] ) ) {
|
||||
return $this->links[ $matches[1] ];
|
||||
}
|
||||
|
||||
return $link;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts together an array of choices for a specific service.
|
||||
*
|
||||
* @param string $service The social service.
|
||||
* @return array An associative array with profile links and display names.
|
||||
*/
|
||||
private function get_customize_select( $service ) {
|
||||
$choices = array(
|
||||
'' => __( '— Select —', 'jetpack-classic-theme-helper' ),
|
||||
);
|
||||
|
||||
if ( isset( $this->links[ $service ] ) ) {
|
||||
$choices[ $this->links[ $service ] ] = $this->links[ $service ];
|
||||
}
|
||||
|
||||
if ( class_exists( Publicize::class ) ) {
|
||||
$connected_services = $this->publicize->get_services( 'connected' );
|
||||
if ( isset( $connected_services[ $service ] ) ) {
|
||||
foreach ( $connected_services[ $service ] as $c ) {
|
||||
$profile_link = $this->publicize->get_profile_link( $service, $c );
|
||||
|
||||
if ( false === $profile_link ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$choices[ $profile_link ] = $this->publicize->get_display_name( $service, $c );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( 1 === count( $choices ) ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
return $choices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Back-compat function for versions prior to 4.0.
|
||||
*/
|
||||
private function is_customize_preview() {
|
||||
global $wp_customize;
|
||||
return is_a( $wp_customize, 'WP_Customize_Manager' ) && $wp_customize->is_preview();
|
||||
}
|
||||
}
|
||||
|
||||
} // - end if ( ! class_exists( 'Social_Links' )
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/**
|
||||
* Jetpack Compatibility File
|
||||
* See: https://jetpack.com/
|
||||
*
|
||||
* @package automattic/jetpack-classic-theme-helper
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Jetpack theme supports for Twenty Fifteen.
|
||||
*/
|
||||
function twentyfifteen__jetpack_setup() {
|
||||
/**
|
||||
* Add theme support for Responsive Videos.
|
||||
*/
|
||||
add_theme_support( 'jetpack-responsive-videos' );
|
||||
}
|
||||
add_action( 'after_setup_theme', 'twentyfifteen__jetpack_setup' );
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/**
|
||||
* Jetpack Compatibility File
|
||||
* See: https://jetpack.com/
|
||||
*
|
||||
* @package automattic/jetpack-classic-theme-helper
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'twentyfourteen_featured_content_post_ids' ) ) {
|
||||
/**
|
||||
* A last try to show posts, in case the Featured Content plugin returns no IDs.
|
||||
*
|
||||
* @param array $featured_ids Array of 'featured' post IDs.
|
||||
* @return array
|
||||
*/
|
||||
function twentyfourteen_featured_content_post_ids( $featured_ids ) {
|
||||
if ( empty( $featured_ids ) ) {
|
||||
$featured_ids = array_slice( get_option( 'sticky_posts', array() ), 0, 6 );
|
||||
}
|
||||
|
||||
return $featured_ids;
|
||||
}
|
||||
add_action( 'featured_content_post_ids', 'twentyfourteen_featured_content_post_ids' );
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'twentyfourteen_customizer_default' ) ) {
|
||||
/**
|
||||
* Set the default tag name for Featured Content.
|
||||
*
|
||||
* @param WP_Customize_Manager $wp_customize Theme Customizer object.
|
||||
* @return void
|
||||
*/
|
||||
function twentyfourteen_customizer_default( $wp_customize ) {
|
||||
$wp_customize->get_setting( 'featured-content[tag-name]' )->default = 'featured';
|
||||
}
|
||||
add_action( 'customize_register', 'twentyfourteen_customizer_default' );
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'twentyfourteen_featured_content_default_settings' ) ) {
|
||||
/**
|
||||
* Sets a default tag of 'featured' for Featured Content.
|
||||
*
|
||||
* @param array $settings Featured content settings.
|
||||
* @return array
|
||||
*/
|
||||
function twentyfourteen_featured_content_default_settings( $settings ) {
|
||||
$settings['tag-name'] = 'featured';
|
||||
|
||||
return $settings;
|
||||
}
|
||||
add_action( 'featured_content_default_settings', 'twentyfourteen_featured_content_default_settings' );
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
/**
|
||||
* Jetpack Compatibility File
|
||||
* See: https://jetpack.com/
|
||||
*
|
||||
* @package automattic/jetpack-classic-theme-helper
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Jetpack theme supports for Twenty Nineteen.
|
||||
*/
|
||||
function twentynineteen__jetpack_setup() {
|
||||
|
||||
/**
|
||||
* 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(
|
||||
'blog-display' => array( 'content', 'excerpt' ),
|
||||
'post-details' => array(
|
||||
'stylesheet' => 'twentynineteen-style',
|
||||
'date' => '.posted-on',
|
||||
'categories' => '.cat-links',
|
||||
'tags' => '.tags-links',
|
||||
'author' => '.byline',
|
||||
'comment' => '.comments-link',
|
||||
),
|
||||
'featured-images' => array(
|
||||
'archive' => true,
|
||||
'post' => true,
|
||||
'page' => true,
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
add_action( 'after_setup_theme', 'twentynineteen__jetpack_setup' );
|
||||
|
||||
if ( ! function_exists( 'twentynineteen_override_post_thumbnail' ) ) {
|
||||
/**
|
||||
* Alter featured-image default visibility for content-options.
|
||||
*/
|
||||
function twentynineteen_override_post_thumbnail() {
|
||||
$options = get_theme_support( 'jetpack-content-options' );
|
||||
$featured_images = ( ! empty( $options[0]['featured-images'] ) ) ? $options[0]['featured-images'] : null;
|
||||
|
||||
$settings = array(
|
||||
'post-default' => ( isset( $featured_images['post-default'] ) && false === $featured_images['post-default'] ) ? '' : 1,
|
||||
'page-default' => ( isset( $featured_images['page-default'] ) && false === $featured_images['page-default'] ) ? '' : 1,
|
||||
);
|
||||
|
||||
$settings = array_merge(
|
||||
$settings,
|
||||
array(
|
||||
'post-option' => get_option( 'jetpack_content_featured_images_post', $settings['post-default'] ),
|
||||
'page-option' => get_option( 'jetpack_content_featured_images_page', $settings['page-default'] ),
|
||||
)
|
||||
);
|
||||
|
||||
if ( ( ! $settings['post-option'] && is_single() )
|
||||
|| ( ! $settings['page-option'] && is_singular() && is_page() ) ) {
|
||||
return false;
|
||||
} else {
|
||||
return ! post_password_required() && ! is_attachment() && has_post_thumbnail();
|
||||
}
|
||||
}
|
||||
add_filter( 'twentynineteen_can_show_post_thumbnail', 'twentynineteen_override_post_thumbnail', 10, 2 );
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/**
|
||||
* Jetpack Compatibility File
|
||||
* See: https://jetpack.com/
|
||||
*
|
||||
* @package automattic/jetpack-classic-theme-helper
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Jetpack theme supports for Twenty Sixteen.
|
||||
*/
|
||||
function twentysixteen__jetpack_setup() {
|
||||
/**
|
||||
* Add theme support for Responsive Videos.
|
||||
*/
|
||||
add_theme_support( 'jetpack-responsive-videos' );
|
||||
}
|
||||
add_action( 'after_setup_theme', 'twentysixteen__jetpack_setup' );
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* Jetpack Compatibility File
|
||||
* See: https://jetpack.com/
|
||||
*
|
||||
* @package automattic/jetpack-classic-theme-helper
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Jetpack extra functionality to Twenty Twenty.
|
||||
*
|
||||
* See: https://jetpack.com/support/infinite-scroll/
|
||||
* See: https://jetpack.com/support/responsive-videos/
|
||||
* See: https://jetpack.com/support/content-options/
|
||||
*/
|
||||
function twentytwenty__jetpack_setup() {
|
||||
|
||||
// Add theme support for Content Options.
|
||||
add_theme_support(
|
||||
'jetpack-content-options',
|
||||
array(
|
||||
'post-details' => array(
|
||||
'stylesheet' => 'twentytwenty-style',
|
||||
'date' => '.post-date',
|
||||
'categories' => '.entry-categories',
|
||||
'tags' => '.post-tags',
|
||||
'author' => '.post-author',
|
||||
),
|
||||
'featured-images' => array(
|
||||
'archive' => true,
|
||||
'post' => true,
|
||||
'page' => true,
|
||||
'fallback' => false,
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
add_action( 'after_setup_theme', 'twentytwenty__jetpack_setup' );
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
/**
|
||||
* Jetpack Compatibility File
|
||||
* See: https://jetpack.com/
|
||||
*
|
||||
* @package automattic/jetpack-classic-theme-helper
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Jetpack extra functionality to Twenty Twenty One.
|
||||
*/
|
||||
function twentytwentyone__jetpack_setup() {
|
||||
|
||||
/**
|
||||
* Add theme support for Content Options.
|
||||
*/
|
||||
add_theme_support(
|
||||
'jetpack-content-options',
|
||||
array(
|
||||
'blog-display' => array( 'content', 'excerpt' ),
|
||||
'post-details' => array(
|
||||
'stylesheet' => 'twenty-twenty-one-style',
|
||||
'date' => '.posted-on',
|
||||
'categories' => '.cat-links',
|
||||
),
|
||||
'featured-images' => array(
|
||||
'archive' => true,
|
||||
'post' => true,
|
||||
'page' => true,
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
add_action( 'after_setup_theme', 'twentytwentyone__jetpack_setup' );
|
||||
+174
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
/**
|
||||
* Jetpack Compatibility File
|
||||
* See: https://jetpack.com/
|
||||
*
|
||||
* @package automattic/jetpack-classic-theme-helper
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Content Options.
|
||||
*
|
||||
* This feature will only be activated for themes that declare their support.
|
||||
* This can be done by adding code similar to the following during the
|
||||
* 'after_setup_theme' action:
|
||||
*
|
||||
add_theme_support( 'jetpack-content-options', array(
|
||||
'blog-display' => 'content', // the default setting of the theme: 'content', 'excerpt' or array( 'content', 'excerpt' ) for themes mixing both display.
|
||||
'author-bio' => true, // display or not the author bio: true or false.
|
||||
'author-bio-default' => false, // the default setting of the author bio, if it's being displayed or not: true or false (only required if false).
|
||||
'avatar-default' => true, // display or not the default avatar for the author bio: true or false.
|
||||
'masonry' => '.site-main', // a CSS selector matching the elements that triggers a masonry refresh if the theme is using a masonry layout.
|
||||
'post-details' => array(
|
||||
'stylesheet' => 'themeslug-style', // name of the theme's stylesheet.
|
||||
'date' => '.posted-on', // a CSS selector matching the elements that display the post date.
|
||||
'categories' => '.cat-links', // a CSS selector matching the elements that display the post categories.
|
||||
'tags' => '.tags-links', // a CSS selector matching the elements that display the post tags.
|
||||
'author' => '.byline', // a CSS selector matching the elements that display the post author.
|
||||
'comment' => '.comments-link', // a CSS selector matching the elements that display the comment link.
|
||||
),
|
||||
'featured-images' => array(
|
||||
'archive' => true, // enable or not the featured image check for archive pages: true or false.
|
||||
'archive-default' => false, // the default setting of the featured image on archive pages, if it's being displayed or not: true or false (only required if false).
|
||||
'post' => true, // enable or not the featured image check for single posts: true or false.
|
||||
'post-default' => false, // the default setting of the featured image on single posts, if it's being displayed or not: true or false (only required if false).
|
||||
'page' => true, // enable or not the featured image check for single pages: true or false.
|
||||
'page-default' => false, // the default setting of the featured image on single pages, if it's being displayed or not: true or false (only required if false).
|
||||
'portfolio' => true, // enable or not the featured image check for single projects: true or false.
|
||||
'portfolio-default' => false, // the default setting of the featured image on single projects, if it's being displayed or not: true or false (only required if false).
|
||||
'fallback' => true, // enable or not the featured image fallback: true or false.
|
||||
'fallback-default' => true, // the default setting for featured image fallbacks: true or false (only required if false)
|
||||
),
|
||||
) );
|
||||
*/
|
||||
|
||||
if ( ! function_exists( 'jetpack_content_options_init' ) ) {
|
||||
|
||||
/**
|
||||
* Activate the Content Options plugin.
|
||||
*
|
||||
* @uses current_theme_supports()
|
||||
*/
|
||||
function jetpack_content_options_init() {
|
||||
// If the theme doesn't support 'jetpack-content-options', don't continue.
|
||||
if ( ! current_theme_supports( 'jetpack-content-options' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Load the Customizer options.
|
||||
require __DIR__ . '/content-options/customizer.php';
|
||||
|
||||
// Load Blog Display function.
|
||||
require __DIR__ . '/content-options/blog-display.php';
|
||||
|
||||
// Load Author Bio function.
|
||||
require __DIR__ . '/content-options/author-bio.php';
|
||||
|
||||
// Load Post Details function.
|
||||
require __DIR__ . '/content-options/post-details.php';
|
||||
|
||||
// Load Featured Images function.
|
||||
if ( jetpack_featured_images_should_load() ) {
|
||||
require __DIR__ . '/content-options/featured-images.php';
|
||||
}
|
||||
|
||||
// Load Featured Images Fallback function.
|
||||
if ( jetpack_featured_images_fallback_should_load() ) {
|
||||
require __DIR__ . '/content-options/featured-images-fallback.php';
|
||||
}
|
||||
}
|
||||
add_action( 'init', 'jetpack_content_options_init' );
|
||||
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_featured_images_get_settings' ) ) {
|
||||
|
||||
/**
|
||||
* Get featured images settings using the jetpack-content-options theme support.
|
||||
*/
|
||||
function jetpack_featured_images_get_settings() {
|
||||
$options = get_theme_support( 'jetpack-content-options' );
|
||||
|
||||
$featured_images = ( ! empty( $options[0]['featured-images'] ) ) ? $options[0]['featured-images'] : null;
|
||||
|
||||
$settings = array(
|
||||
'archive' => ( ! empty( $featured_images['archive'] ) ) ? $featured_images['archive'] : null,
|
||||
'post' => ( ! empty( $featured_images['post'] ) ) ? $featured_images['post'] : null,
|
||||
'page' => ( ! empty( $featured_images['page'] ) ) ? $featured_images['page'] : null,
|
||||
'portfolio' => ( ! empty( $featured_images['portfolio'] ) ) ? $featured_images['portfolio'] : null,
|
||||
'archive-default' => ( isset( $featured_images['archive-default'] ) && false === $featured_images['archive-default'] ) ? '' : 1,
|
||||
'post-default' => ( isset( $featured_images['post-default'] ) && false === $featured_images['post-default'] ) ? '' : 1,
|
||||
'page-default' => ( isset( $featured_images['page-default'] ) && false === $featured_images['page-default'] ) ? '' : 1,
|
||||
'portfolio-default' => ( isset( $featured_images['portfolio-default'] ) && false === $featured_images['portfolio-default'] ) ? '' : 1,
|
||||
'fallback' => ( ! empty( $featured_images['fallback'] ) ) ? $featured_images['fallback'] : null,
|
||||
'fallback-default' => ( isset( $featured_images['fallback-default'] ) && false === $featured_images['fallback-default'] ) ? '' : 1,
|
||||
);
|
||||
|
||||
$settings = array_merge(
|
||||
$settings,
|
||||
array(
|
||||
'archive-option' => get_option( 'jetpack_content_featured_images_archive', $settings['archive-default'] ),
|
||||
'post-option' => get_option( 'jetpack_content_featured_images_post', $settings['post-default'] ),
|
||||
'page-option' => get_option( 'jetpack_content_featured_images_page', $settings['page-default'] ),
|
||||
'portfolio-option' => get_option( 'jetpack_content_featured_images_portfolio', $settings['portfolio-default'] ),
|
||||
'fallback-option' => get_option( 'jetpack_content_featured_images_fallback', $settings['fallback-default'] ),
|
||||
)
|
||||
);
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_featured_images_should_load' ) ) {
|
||||
|
||||
/**
|
||||
* Determine if the Jetpack Featured Images should be load.
|
||||
*/
|
||||
function jetpack_featured_images_should_load() {
|
||||
// If the theme doesn't support post thumbnails, don't continue.
|
||||
if ( ! current_theme_supports( 'post-thumbnails' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$opts = jetpack_featured_images_get_settings();
|
||||
|
||||
// If the theme doesn't support archive, post and page or if all the options are ticked and we aren't in the customizer, don't continue.
|
||||
if (
|
||||
( true !== $opts['archive'] && true !== $opts['post'] && true !== $opts['page'] )
|
||||
|| ( 1 === $opts['archive-option'] && 1 === $opts['post-option'] && 1 === $opts['page-option'] && ! is_customize_preview() )
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_featured_images_fallback_should_load' ) ) {
|
||||
|
||||
/**
|
||||
* Determine if the Jetpack Featured Images fallback should load.
|
||||
*/
|
||||
function jetpack_featured_images_fallback_should_load() {
|
||||
// If the theme doesn't support post thumbnails, don't continue.
|
||||
if ( ! current_theme_supports( 'post-thumbnails' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$opts = jetpack_featured_images_get_settings();
|
||||
|
||||
// If the theme doesn't support fallback, don't continue.
|
||||
if ( true !== $opts['fallback'] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
/**
|
||||
* Theme Tools: Author Bio functions.
|
||||
*
|
||||
* @package automattic/jetpack-classic-theme-helper
|
||||
*/
|
||||
|
||||
if ( ! function_exists( 'jetpack_author_bio' ) ) {
|
||||
|
||||
/**
|
||||
* The function to display Author Bio in a theme.
|
||||
*/
|
||||
function jetpack_author_bio() {
|
||||
// If the theme doesn't support 'jetpack-content-options', don't continue.
|
||||
if ( ! current_theme_supports( 'jetpack-content-options' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$options = get_theme_support( 'jetpack-content-options' );
|
||||
$author_bio = ( ! empty( $options[0]['author-bio'] ) ) ? $options[0]['author-bio'] : null;
|
||||
$author_bio_default = ( isset( $options[0]['author-bio-default'] ) && false === $options[0]['author-bio-default'] ) ? '' : 1;
|
||||
$avatar_default = ( isset( $options[0]['avatar-default'] ) && false === $options[0]['avatar-default'] ) ? '' : 1;
|
||||
|
||||
// If the theme doesn't support 'jetpack-content-options[ 'author-bio' ]', don't continue.
|
||||
if ( true !== $author_bio ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If 'jetpack_content_author_bio' is false, don't continue.
|
||||
if ( ! get_option( 'jetpack_content_author_bio', $author_bio_default ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we aren't on a single post, don't continue.
|
||||
if ( ! is_single() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Define class for entry-author.
|
||||
if ( ! $avatar_default && ! jetpack_has_gravatar( get_the_author_meta( 'user_email' ) ) ) {
|
||||
$class = 'author-avatar-hide';
|
||||
} else {
|
||||
$class = 'author-avatar-show';
|
||||
}
|
||||
?>
|
||||
<div class="entry-author <?php echo esc_attr( $class ); ?>">
|
||||
<?php if ( 'author-avatar-show' === $class ) : ?>
|
||||
<div class="author-avatar">
|
||||
<?php
|
||||
/**
|
||||
* Filter the author bio avatar size.
|
||||
*
|
||||
* @param int $size The avatar height and width size in pixels.
|
||||
*
|
||||
* @module theme-tools
|
||||
*
|
||||
* @since 4.5.0
|
||||
*/
|
||||
$author_bio_avatar_size = apply_filters( 'jetpack_author_bio_avatar_size', 48 );
|
||||
|
||||
echo get_avatar( get_the_author_meta( 'user_email' ), $author_bio_avatar_size );
|
||||
?>
|
||||
</div><!-- .author-avatar -->
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="author-heading">
|
||||
<h2 class="author-title">
|
||||
<?php
|
||||
/* translators: %s: post author */
|
||||
printf( esc_html__( 'Published by %s', 'jetpack-classic-theme-helper' ), '<span class="author-name">' . get_the_author() . '</span>' );
|
||||
?>
|
||||
</h2>
|
||||
</div><!-- .author-heading -->
|
||||
|
||||
<p class="author-bio">
|
||||
<?php the_author_meta( 'description' ); ?>
|
||||
<a class="author-link" href="<?php echo esc_url( get_author_posts_url( (int) get_the_author_meta( 'ID' ) ) ); ?>" rel="author">
|
||||
<?php
|
||||
/* translators: %s: post author */
|
||||
printf( esc_html__( 'View all posts by %s', 'jetpack-classic-theme-helper' ), get_the_author() );
|
||||
?>
|
||||
</a>
|
||||
</p><!-- .author-bio -->
|
||||
</div><!-- .entry-auhtor -->
|
||||
<?php
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_has_gravatar' ) ) {
|
||||
|
||||
/**
|
||||
* Checks to see if the specified email address has a Gravatar image.
|
||||
*
|
||||
* @param string $email The email of the address of the user to check.
|
||||
* @return bool Whether or not the user has a gravatar
|
||||
*/
|
||||
function jetpack_has_gravatar( $email ) {
|
||||
|
||||
$url = get_avatar_url( $email, array( 'default' => '404' ) );
|
||||
if ( ! is_string( $url ) || $url === '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$headers = get_headers( $url );
|
||||
if ( ! is_array( $headers ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If 200 is found, the user has a Gravatar; otherwise, they don't.
|
||||
return preg_match( '|200|', $headers[0] ) ? true : false;
|
||||
}
|
||||
|
||||
}
|
||||
+308
@@ -0,0 +1,308 @@
|
||||
<?php
|
||||
/**
|
||||
* Theme Tools: the functions to display Content or Excerpt in a theme.
|
||||
*
|
||||
* @package automattic/jetpack-classic-theme-helper
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* If the theme doesn't support 'jetpack-content-options', don't continue.
|
||||
*/
|
||||
if ( ! current_theme_supports( 'jetpack-content-options' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Blog Display setting.
|
||||
* If theme is using both 'Content' and 'Excerpt' then this setting will be called 'Mixed'.
|
||||
*/
|
||||
$options = get_theme_support( 'jetpack-content-options' );
|
||||
$blog_display = ( ! empty( $options[0]['blog-display'] ) ) ? $options[0]['blog-display'] : null;
|
||||
$blog_display = preg_grep( '/^(content|excerpt)$/', (array) $blog_display );
|
||||
sort( $blog_display );
|
||||
$blog_display = implode( ', ', $blog_display );
|
||||
$blog_display = ( 'content, excerpt' === $blog_display ) ? 'mixed' : $blog_display;
|
||||
|
||||
/**
|
||||
* If the theme doesn't support 'jetpack-content-options[ 'blog-display' ]', don't continue.
|
||||
*/
|
||||
if ( ! in_array( $blog_display, array( 'content', 'excerpt', 'mixed' ), true ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_blog_display_custom_excerpt' ) ) {
|
||||
|
||||
/**
|
||||
* Apply Content filters.
|
||||
*
|
||||
* @since 9.7.0 Deprecated $content parameter.
|
||||
*
|
||||
* @param string $content Post content. Deprecated.
|
||||
*/
|
||||
function jetpack_blog_display_custom_excerpt( $content = '' ) {
|
||||
if ( ! empty( $content ) ) {
|
||||
_doing_it_wrong(
|
||||
'jetpack_blog_display_custom_excerpt',
|
||||
esc_html__( 'You do not need to pass a $content parameter anymore.', 'jetpack-classic-theme-helper' ),
|
||||
'jetpack-9.7.0'
|
||||
);
|
||||
}
|
||||
|
||||
$post = get_post();
|
||||
if ( empty( $post ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ( empty( $post->post_excerpt ) ) {
|
||||
$text = strip_shortcodes( $post->post_content );
|
||||
$text = str_replace( ']]>', ']]>', $text );
|
||||
$text = wp_strip_all_tags( $text );
|
||||
/** This filter is documented in wp-includes/formatting.php */
|
||||
$excerpt_length = apply_filters( 'excerpt_length', 55 );
|
||||
$excerpt_length = is_numeric( $excerpt_length ) ? (int) $excerpt_length : 55;
|
||||
|
||||
/** This filter is documented in wp-includes/formatting.php */
|
||||
$excerpt_more = apply_filters( 'excerpt_more', ' [...]' );
|
||||
|
||||
/*
|
||||
* translators: If your word count is based on single characters (e.g. East Asian characters),
|
||||
* enter 'characters_excluding_spaces' or 'characters_including_spaces'. Otherwise, enter 'words'.
|
||||
* Do not translate into your own language.
|
||||
*/
|
||||
if ( strpos( _x( 'words', 'Word count type. Do not translate!', 'jetpack-classic-theme-helper' ), 'characters' ) === 0 && preg_match( '/^utf\-?8$/i', get_option( 'blog_charset' ) ) ) {
|
||||
$text = trim( preg_replace( "/[\n\r\t ]+/", ' ', $text ), ' ' );
|
||||
preg_match_all( '/./u', $text, $words );
|
||||
$words = array_slice( $words[0], 0, $excerpt_length + 1 );
|
||||
$sep = '';
|
||||
} else {
|
||||
$words = preg_split( "/[\n\r\t ]+/", $text, $excerpt_length + 1, PREG_SPLIT_NO_EMPTY );
|
||||
$sep = ' ';
|
||||
}
|
||||
|
||||
if ( count( $words ) > $excerpt_length ) {
|
||||
array_pop( $words );
|
||||
$text = implode( $sep, $words );
|
||||
$text .= $excerpt_more;
|
||||
} else {
|
||||
$text = implode( $sep, $words );
|
||||
}
|
||||
} else {
|
||||
$text = wp_kses_post( $post->post_excerpt );
|
||||
}
|
||||
return sprintf( '<p>%s</p>', $text );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_the_content_to_the_excerptt' ) ) {
|
||||
|
||||
/**
|
||||
* Display Excerpt instead of Content.
|
||||
*
|
||||
* @param string $content Post content.
|
||||
*/
|
||||
function jetpack_the_content_to_the_excerpt( $content ) {
|
||||
if ( ( is_home() || is_archive() ) && ! is_post_type_archive( array( 'jetpack-testimonial', 'jetpack-portfolio', 'product' ) ) ) {
|
||||
if ( post_password_required() ) {
|
||||
$excerpt = sprintf( '<p>%s</p>', esc_html__( 'There is no excerpt because this is a protected post.', 'jetpack-classic-theme-helper' ) );
|
||||
} else {
|
||||
$excerpt = jetpack_blog_display_custom_excerpt();
|
||||
}
|
||||
}
|
||||
if ( empty( $excerpt ) ) {
|
||||
return $content;
|
||||
} else {
|
||||
return $excerpt;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_the_excerpt_to_the_content' ) ) {
|
||||
|
||||
/**
|
||||
* Display Content instead of Excerpt.
|
||||
*
|
||||
* @param string $content The post excerpt.
|
||||
*/
|
||||
function jetpack_the_excerpt_to_the_content( $content ) {
|
||||
if ( ( is_home() || is_archive() ) && ! is_post_type_archive( array( 'jetpack-testimonial', 'jetpack-portfolio', 'product' ) ) ) {
|
||||
ob_start();
|
||||
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>', 'jetpack-classic-theme-helper' ),
|
||||
array(
|
||||
'span' => array(
|
||||
'class' => array(),
|
||||
),
|
||||
)
|
||||
),
|
||||
get_the_title()
|
||||
)
|
||||
);
|
||||
$content = ob_get_clean();
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_the_content_customizer' ) ) {
|
||||
|
||||
/**
|
||||
* Display both Content and Excerpt instead of Content in the Customizer so live preview can switch between them.
|
||||
*
|
||||
* @param string $content The post content.
|
||||
*/
|
||||
function jetpack_the_content_customizer( $content ) {
|
||||
$class = jetpack_the_content_customizer_class();
|
||||
if ( ( is_home() || is_archive() ) && ! is_post_type_archive( array( 'jetpack-testimonial', 'jetpack-portfolio', 'product' ) ) ) {
|
||||
if ( post_password_required() ) {
|
||||
$excerpt = sprintf( '<p>%s</p>', esc_html__( 'There is no excerpt because this is a protected post.', 'jetpack-classic-theme-helper' ) );
|
||||
} else {
|
||||
$excerpt = jetpack_blog_display_custom_excerpt();
|
||||
}
|
||||
}
|
||||
if ( empty( $excerpt ) ) {
|
||||
return $content;
|
||||
} else {
|
||||
return sprintf( '<div class="jetpack-blog-display %s jetpack-the-content">%s</div><div class="jetpack-blog-display %s jetpack-the-excerpt">%s</div>', $class, $content, $class, $excerpt );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_the_excerpt_customizer' ) ) {
|
||||
|
||||
/**
|
||||
* Display both Content and Excerpt instead of Excerpt in the Customizer so live preview can switch between them.
|
||||
*
|
||||
* @param string $excerpt The post excerpt.
|
||||
*/
|
||||
function jetpack_the_excerpt_customizer( $excerpt ) {
|
||||
if ( ( is_home() || is_archive() ) && ! is_post_type_archive( array( 'jetpack-testimonial', 'jetpack-portfolio', 'product' ) ) ) {
|
||||
ob_start();
|
||||
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>', 'jetpack-classic-theme-helper' ),
|
||||
array(
|
||||
'span' => array(
|
||||
'class' => array(),
|
||||
),
|
||||
)
|
||||
),
|
||||
get_the_title()
|
||||
)
|
||||
);
|
||||
$content = ob_get_clean();
|
||||
}
|
||||
if ( empty( $content ) ) {
|
||||
return $excerpt;
|
||||
} else {
|
||||
return sprintf( '<div class="jetpack-blog-display jetpack-the-content">%s</div><div class="jetpack-blog-display jetpack-the-excerpt">%s</div>', $content, $excerpt );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_the_excerpt_mixed_customizer' ) ) {
|
||||
|
||||
/**
|
||||
* Display Content instead of Excerpt in the Customizer when theme uses a 'Mixed' display.
|
||||
*
|
||||
* @param string $content The post excerpt.
|
||||
*/
|
||||
function jetpack_the_excerpt_mixed_customizer( $content ) {
|
||||
if ( ( is_home() || is_archive() ) && ! is_post_type_archive( array( 'jetpack-testimonial', 'jetpack-portfolio', 'product' ) ) ) {
|
||||
jetpack_the_content_customizer_class( 'output-the-excerpt' );
|
||||
ob_start();
|
||||
the_content();
|
||||
$content = ob_get_clean();
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_the_content_customizer_class' ) ) {
|
||||
|
||||
/**
|
||||
* Returns a class value, `output-the-content` by default.
|
||||
* Used for themes with a 'Mixed' Blog Display so we can tell which output is by default.
|
||||
*
|
||||
* @param string|null $new_class CSS class added to content container.
|
||||
*/
|
||||
function jetpack_the_content_customizer_class( $new_class = null ) {
|
||||
static $class;
|
||||
if ( isset( $new_class ) ) {
|
||||
// Assign a new class and return.
|
||||
$class = $new_class;
|
||||
} elseif ( isset( $class ) ) {
|
||||
// Reset the class after getting value.
|
||||
$prev_class = $class;
|
||||
$class = null;
|
||||
return $prev_class;
|
||||
} else {
|
||||
// Return default class value.
|
||||
return 'output-the-content';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( is_customize_preview() ) {
|
||||
/*
|
||||
* Display Content and Excerpt if the default Blog Display is 'Content'
|
||||
* and we are in the Customizer.
|
||||
*/
|
||||
if ( 'content' === $blog_display ) {
|
||||
add_filter( 'the_content', 'jetpack_the_content_customizer' );
|
||||
}
|
||||
|
||||
/*
|
||||
* Display Content and Excerpt if the default Blog Display is 'Excerpt'
|
||||
* and we are in the Customizer.
|
||||
*/
|
||||
if ( 'excerpt' === $blog_display ) {
|
||||
add_filter( 'the_excerpt', 'jetpack_the_excerpt_customizer' );
|
||||
}
|
||||
|
||||
/*
|
||||
* Display Content and Excerpt if the default Blog Display is 'Mixed'
|
||||
* and we are in the Customizer.
|
||||
*/
|
||||
if ( 'mixed' === $blog_display ) {
|
||||
add_filter( 'the_content', 'jetpack_the_content_customizer' );
|
||||
add_filter( 'the_excerpt', 'jetpack_the_excerpt_mixed_customizer' );
|
||||
}
|
||||
} else {
|
||||
$display_option = get_option( 'jetpack_content_blog_display', $blog_display );
|
||||
|
||||
/*
|
||||
* Display Excerpt if the default Blog Display is 'Content'
|
||||
* or default Blog Display is 'Mixed'
|
||||
* and the Option picked is 'Post Excerpt'
|
||||
* and we aren't in the Customizer.
|
||||
*/
|
||||
if ( ( 'content' === $blog_display || 'mixed' === $blog_display ) && 'excerpt' === $display_option ) {
|
||||
add_filter( 'the_content', 'jetpack_the_content_to_the_excerpt' );
|
||||
}
|
||||
|
||||
/*
|
||||
* Display Content if the default Blog Display is 'Excerpt'
|
||||
* or default Blog Display is 'Mixed'
|
||||
* and the Option picked is 'Full Post'
|
||||
* and we aren't in the Customizer.
|
||||
*/
|
||||
if ( ( 'excerpt' === $blog_display || 'mixed' === $blog_display ) && 'content' === $display_option ) {
|
||||
add_filter( 'the_excerpt', 'jetpack_the_excerpt_to_the_content' );
|
||||
}
|
||||
}
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
/* global blogDisplay, postDetails, wp */
|
||||
|
||||
/**
|
||||
* customizer.js
|
||||
*
|
||||
* Theme Customizer enhancements for a better user experience.
|
||||
*
|
||||
* Contains handlers to make Theme Customizer preview reload changes asynchronously.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Function to apply styles to elements based on the display type
|
||||
* @param {object} selectors - HTML selectors which styles will apply to.
|
||||
* @param {object} styles - Styles to be applied to selectors.
|
||||
*/
|
||||
function applyStyles( selectors, styles ) {
|
||||
document.querySelectorAll( selectors ).forEach( el => {
|
||||
for ( const [ key, value ] of Object.entries( styles ) ) {
|
||||
el.style[ key ] = value;
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
// Blog Display
|
||||
wp.customize( 'jetpack_content_blog_display', function ( value ) {
|
||||
/**
|
||||
* Updates the blog display based on the selected option.
|
||||
* @param {string} to - Content display option.
|
||||
*/
|
||||
function updateBlogDisplay( to ) {
|
||||
const contentSelectors = '.jetpack-blog-display.jetpack-the-content';
|
||||
const excerptSelectors = '.jetpack-blog-display.jetpack-the-excerpt';
|
||||
const featuredContentSelectors = '.featured-content .jetpack-blog-display';
|
||||
|
||||
if ( to === 'content' ) {
|
||||
applyStyles( `${ excerptSelectors }, ${ featuredContentSelectors }.jetpack-the-excerpt`, {
|
||||
clip: 'rect(1px, 1px, 1px, 1px)',
|
||||
position: 'absolute',
|
||||
} );
|
||||
applyStyles( `${ contentSelectors }, ${ featuredContentSelectors }.jetpack-the-content`, {
|
||||
clip: 'auto',
|
||||
position: 'relative',
|
||||
} );
|
||||
} else if ( to === 'excerpt' ) {
|
||||
applyStyles( `${ contentSelectors }, ${ featuredContentSelectors }.jetpack-the-content`, {
|
||||
clip: 'rect(1px, 1px, 1px, 1px)',
|
||||
position: 'absolute',
|
||||
} );
|
||||
applyStyles( `${ excerptSelectors }, ${ featuredContentSelectors }.jetpack-the-excerpt`, {
|
||||
clip: 'auto',
|
||||
position: 'relative',
|
||||
} );
|
||||
} else if ( to === 'mixed' ) {
|
||||
applyStyles(
|
||||
`${ contentSelectors }.output-the-content, ${ featuredContentSelectors }.jetpack-the-content.output-the-content`,
|
||||
{
|
||||
clip: 'auto',
|
||||
position: 'relative',
|
||||
}
|
||||
);
|
||||
applyStyles(
|
||||
`${ excerptSelectors }.output-the-content, ${ contentSelectors }.output-the-excerpt, ${ featuredContentSelectors }.jetpack-the-excerpt.output-the-content, ${ featuredContentSelectors }.jetpack-the-content.output-the-excerpt`,
|
||||
{
|
||||
clip: 'rect(1px, 1px, 1px, 1px)',
|
||||
position: 'absolute',
|
||||
}
|
||||
);
|
||||
applyStyles(
|
||||
`${ excerptSelectors }.output-the-excerpt, ${ featuredContentSelectors }.jetpack-the-excerpt.output-the-excerpt`,
|
||||
{
|
||||
clip: 'auto',
|
||||
position: 'relative',
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if ( blogDisplay.masonry ) {
|
||||
const masonryElement = document.querySelector( blogDisplay.masonry );
|
||||
if ( masonryElement ) {
|
||||
masonryElement.masonry();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateBlogDisplay( blogDisplay.display );
|
||||
value.bind( updateBlogDisplay );
|
||||
} );
|
||||
|
||||
/**
|
||||
* Function to update post details visibility
|
||||
* @param {object} selectors - HTML selectors which styles will apply to.
|
||||
* @param {string} to - Content display option.
|
||||
* @param {string} hiddenClass - Class to be added to the body when the post details are hidden.
|
||||
*/
|
||||
function updatePostDetails( selectors, to, hiddenClass ) {
|
||||
document.querySelectorAll( selectors ).forEach( element => {
|
||||
if ( to === false ) {
|
||||
element.style.clip = 'rect(1px, 1px, 1px, 1px)';
|
||||
element.style.height = '1px';
|
||||
element.style.overflow = 'hidden';
|
||||
element.style.position = 'absolute';
|
||||
element.style.width = '1px';
|
||||
document.body.classList.add( hiddenClass );
|
||||
} else {
|
||||
element.style.clip = 'auto';
|
||||
element.style.height = 'auto';
|
||||
element.style.overflow = 'visible';
|
||||
element.style.position = 'relative';
|
||||
element.style.width = 'auto';
|
||||
document.body.classList.remove( hiddenClass );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
// Post Details: Date
|
||||
wp.customize( 'jetpack_content_post_details_date', function ( value ) {
|
||||
value.bind( function ( to ) {
|
||||
updatePostDetails( postDetails.date, to, 'date-hidden' );
|
||||
} );
|
||||
} );
|
||||
|
||||
// Post Details: Categories
|
||||
wp.customize( 'jetpack_content_post_details_categories', function ( value ) {
|
||||
value.bind( function ( to ) {
|
||||
updatePostDetails( postDetails.categories, to, 'categories-hidden' );
|
||||
} );
|
||||
} );
|
||||
|
||||
// Post Details: Tags
|
||||
wp.customize( 'jetpack_content_post_details_tags', function ( value ) {
|
||||
value.bind( function ( to ) {
|
||||
updatePostDetails( postDetails.tags, to, 'tags-hidden' );
|
||||
} );
|
||||
} );
|
||||
|
||||
// Post Details: Author
|
||||
wp.customize( 'jetpack_content_post_details_author', function ( value ) {
|
||||
value.bind( function ( to ) {
|
||||
updatePostDetails( postDetails.author, to, 'author-hidden' );
|
||||
} );
|
||||
} );
|
||||
|
||||
// Post Details: Comment link
|
||||
wp.customize( 'jetpack_content_post_details_comment', function ( value ) {
|
||||
value.bind( function ( to ) {
|
||||
updatePostDetails( postDetails.comment, to, 'comment-hidden' );
|
||||
} );
|
||||
} );
|
||||
+538
@@ -0,0 +1,538 @@
|
||||
<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
|
||||
/**
|
||||
* Theme Tools: functions for Customizer enhancements.
|
||||
*
|
||||
* @package automattic/jetpack-classic-theme-helper
|
||||
*/
|
||||
|
||||
use Automattic\Jetpack\Assets;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_content_options_customize_register' ) ) {
|
||||
|
||||
/**
|
||||
* Add Content section to the Theme Customizer.
|
||||
*
|
||||
* @param WP_Customize_Manager $wp_customize Theme Customizer object.
|
||||
*/
|
||||
function jetpack_content_options_customize_register( $wp_customize ) {
|
||||
$options = get_theme_support( 'jetpack-content-options' );
|
||||
$blog_display = ( ! empty( $options[0]['blog-display'] ) ) ? $options[0]['blog-display'] : null;
|
||||
$blog_display = preg_grep( '/^(content|excerpt)$/', (array) $blog_display );
|
||||
sort( $blog_display );
|
||||
$blog_display = implode( ', ', $blog_display );
|
||||
$blog_display = ( 'content, excerpt' === $blog_display ) ? 'mixed' : $blog_display;
|
||||
$author_bio = ( ! empty( $options[0]['author-bio'] ) ) ? $options[0]['author-bio'] : null;
|
||||
$author_bio_default = ( isset( $options[0]['author-bio-default'] ) && false === $options[0]['author-bio-default'] ) ? '' : 1;
|
||||
$post_details = ( ! empty( $options[0]['post-details'] ) ) ? $options[0]['post-details'] : null;
|
||||
$date = ( ! empty( $post_details['date'] ) ) ? $post_details['date'] : null;
|
||||
$categories = ( ! empty( $post_details['categories'] ) ) ? $post_details['categories'] : null;
|
||||
$tags = ( ! empty( $post_details['tags'] ) ) ? $post_details['tags'] : null;
|
||||
$author = ( ! empty( $post_details['author'] ) ) ? $post_details['author'] : null;
|
||||
$comment = ( ! empty( $post_details['comment'] ) ) ? $post_details['comment'] : null;
|
||||
$featured_images = ( ! empty( $options[0]['featured-images'] ) ) ? $options[0]['featured-images'] : null;
|
||||
$fi_archive = ( ! empty( $featured_images['archive'] ) ) ? $featured_images['archive'] : null;
|
||||
$fi_post = ( ! empty( $featured_images['post'] ) ) ? $featured_images['post'] : null;
|
||||
$fi_page = ( ! empty( $featured_images['page'] ) ) ? $featured_images['page'] : null;
|
||||
$fi_portfolio = ( ! empty( $featured_images['portfolio'] ) ) ? $featured_images['portfolio'] : null;
|
||||
$fi_fallback = ( ! empty( $featured_images['fallback'] ) ) ? $featured_images['fallback'] : null;
|
||||
$fi_archive_default = ( isset( $featured_images['archive-default'] ) && false === $featured_images['archive-default'] ) ? '' : 1;
|
||||
$fi_post_default = ( isset( $featured_images['post-default'] ) && false === $featured_images['post-default'] ) ? '' : 1;
|
||||
$fi_page_default = ( isset( $featured_images['page-default'] ) && false === $featured_images['page-default'] ) ? '' : 1;
|
||||
$fi_portfolio_default = ( isset( $featured_images['portfolio-default'] ) && false === $featured_images['portfolio-default'] ) ? '' : 1;
|
||||
$fi_fallback_default = ( isset( $featured_images['fallback-default'] ) && false === $featured_images['fallback-default'] ) ? '' : 1;
|
||||
|
||||
// If the theme doesn't support 'jetpack-content-options[ 'blog-display' ]', 'jetpack-content-options[ 'author-bio' ]', 'jetpack-content-options[ 'post-details' ]' and 'jetpack-content-options[ 'featured-images' ]', don't continue.
|
||||
if ( ( ! in_array( $blog_display, array( 'content', 'excerpt', 'mixed' ), true ) )
|
||||
&& ( true !== $author_bio )
|
||||
&& ( ( empty( $post_details['stylesheet'] ) )
|
||||
&& ( empty( $date )
|
||||
|| empty( $categories )
|
||||
|| empty( $tags )
|
||||
|| empty( $author )
|
||||
|| empty( $comment ) ) )
|
||||
&& ( true !== $fi_archive && true !== $fi_post && true !== $fi_page && true !== $fi_portfolio && true !== $fi_fallback ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Jetpack_Customize_Control_Title' ) ) {
|
||||
|
||||
/**
|
||||
* New Customizer control type: Title.
|
||||
*/
|
||||
class Jetpack_Customize_Control_Title extends WP_Customize_Control {
|
||||
/**
|
||||
* Customizer control type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $type = 'title';
|
||||
|
||||
/**
|
||||
* Render the control's content.
|
||||
*/
|
||||
public function render_content() {
|
||||
?>
|
||||
<span class="customize-control-title"><?php echo wp_kses_post( $this->label ); ?></span>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add Content section.
|
||||
$wp_customize->add_section(
|
||||
'jetpack_content_options',
|
||||
array(
|
||||
'title' => esc_html__( 'Content Options', 'jetpack-classic-theme-helper' ),
|
||||
'theme_supports' => 'jetpack-content-options',
|
||||
'priority' => 100,
|
||||
)
|
||||
);
|
||||
|
||||
// Add Blog Display option.
|
||||
if ( in_array( $blog_display, array( 'content', 'excerpt', 'mixed' ), true ) ) {
|
||||
if ( 'mixed' === $blog_display ) {
|
||||
$blog_display_choices = array(
|
||||
'content' => esc_html__( 'Full post', 'jetpack-classic-theme-helper' ),
|
||||
'excerpt' => esc_html__( 'Post excerpt', 'jetpack-classic-theme-helper' ),
|
||||
'mixed' => esc_html__( 'Default', 'jetpack-classic-theme-helper' ),
|
||||
);
|
||||
|
||||
$blog_display_description = esc_html__( 'Choose between a full post or an excerpt for the blog and archive pages, or opt for the theme\'s default combination of excerpt and full post.', 'jetpack-classic-theme-helper' );
|
||||
} else {
|
||||
$blog_display_choices = array(
|
||||
'content' => esc_html__( 'Full post', 'jetpack-classic-theme-helper' ),
|
||||
'excerpt' => esc_html__( 'Post excerpt', 'jetpack-classic-theme-helper' ),
|
||||
);
|
||||
|
||||
$blog_display_description = esc_html__( 'Choose between a full post or an excerpt for the blog and archive pages.', 'jetpack-classic-theme-helper' );
|
||||
|
||||
if ( 'mixed' === get_option( 'jetpack_content_blog_display' ) ) {
|
||||
update_option( 'jetpack_content_blog_display', $blog_display );
|
||||
}
|
||||
}
|
||||
|
||||
$wp_customize->add_setting(
|
||||
'jetpack_content_blog_display',
|
||||
array(
|
||||
'default' => $blog_display,
|
||||
'type' => 'option',
|
||||
'transport' => 'postMessage',
|
||||
'sanitize_callback' => 'jetpack_content_options_sanitize_blog_display',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
'jetpack_content_blog_display',
|
||||
array(
|
||||
'section' => 'jetpack_content_options',
|
||||
'label' => esc_html__( 'Blog Display', 'jetpack-classic-theme-helper' ),
|
||||
'description' => $blog_display_description,
|
||||
'type' => 'radio',
|
||||
'choices' => $blog_display_choices,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Add Author Bio option.
|
||||
if ( true === $author_bio ) {
|
||||
$wp_customize->add_setting( 'jetpack_content_author_bio_title' );
|
||||
|
||||
$wp_customize->add_control(
|
||||
new Jetpack_Customize_Control_Title(
|
||||
$wp_customize,
|
||||
'jetpack_content_author_bio_title',
|
||||
array(
|
||||
'section' => 'jetpack_content_options',
|
||||
'label' => esc_html__( 'Author Bio', 'jetpack-classic-theme-helper' ),
|
||||
'type' => 'title',
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_setting(
|
||||
'jetpack_content_author_bio',
|
||||
array(
|
||||
'default' => $author_bio_default,
|
||||
'type' => 'option',
|
||||
'sanitize_callback' => 'jetpack_content_options_sanitize_checkbox',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
'jetpack_content_author_bio',
|
||||
array(
|
||||
'section' => 'jetpack_content_options',
|
||||
'label' => esc_html__( 'Display on single posts', 'jetpack-classic-theme-helper' ),
|
||||
'type' => 'checkbox',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Add Post Details options.
|
||||
if ( ( ! empty( $post_details ) )
|
||||
&& ( ! empty( $post_details['stylesheet'] ) )
|
||||
&& ( ! empty( $date )
|
||||
|| ! empty( $categories )
|
||||
|| ! empty( $tags )
|
||||
|| ! empty( $author )
|
||||
|| ! empty( $comment ) ) ) {
|
||||
$wp_customize->add_setting( 'jetpack_content_post_details_title' );
|
||||
|
||||
$wp_customize->add_control(
|
||||
new Jetpack_Customize_Control_Title(
|
||||
$wp_customize,
|
||||
'jetpack_content_post_details_title',
|
||||
array(
|
||||
'section' => 'jetpack_content_options',
|
||||
'label' => esc_html__( 'Post Details', 'jetpack-classic-theme-helper' ),
|
||||
'type' => 'title',
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// Post Details: Date.
|
||||
if ( ! empty( $date ) ) {
|
||||
$wp_customize->add_setting(
|
||||
'jetpack_content_post_details_date',
|
||||
array(
|
||||
'default' => 1,
|
||||
'type' => 'option',
|
||||
'transport' => 'postMessage',
|
||||
'sanitize_callback' => 'jetpack_content_options_sanitize_checkbox',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
'jetpack_content_post_details_date',
|
||||
array(
|
||||
'section' => 'jetpack_content_options',
|
||||
'label' => esc_html__( 'Display date', 'jetpack-classic-theme-helper' ),
|
||||
'type' => 'checkbox',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Post Details: Categories.
|
||||
if ( ! empty( $categories ) ) {
|
||||
$wp_customize->add_setting(
|
||||
'jetpack_content_post_details_categories',
|
||||
array(
|
||||
'default' => 1,
|
||||
'type' => 'option',
|
||||
'transport' => 'postMessage',
|
||||
'sanitize_callback' => 'jetpack_content_options_sanitize_checkbox',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
'jetpack_content_post_details_categories',
|
||||
array(
|
||||
'section' => 'jetpack_content_options',
|
||||
'label' => esc_html__( 'Display categories', 'jetpack-classic-theme-helper' ),
|
||||
'type' => 'checkbox',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Post Details: Tags.
|
||||
if ( ! empty( $tags ) ) {
|
||||
$wp_customize->add_setting(
|
||||
'jetpack_content_post_details_tags',
|
||||
array(
|
||||
'default' => 1,
|
||||
'type' => 'option',
|
||||
'transport' => 'postMessage',
|
||||
'sanitize_callback' => 'jetpack_content_options_sanitize_checkbox',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
'jetpack_content_post_details_tags',
|
||||
array(
|
||||
'section' => 'jetpack_content_options',
|
||||
'label' => esc_html__( 'Display tags', 'jetpack-classic-theme-helper' ),
|
||||
'type' => 'checkbox',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Post Details: Author.
|
||||
if ( ! empty( $author ) ) {
|
||||
$wp_customize->add_setting(
|
||||
'jetpack_content_post_details_author',
|
||||
array(
|
||||
'default' => 1,
|
||||
'type' => 'option',
|
||||
'transport' => 'postMessage',
|
||||
'sanitize_callback' => 'jetpack_content_options_sanitize_checkbox',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
'jetpack_content_post_details_author',
|
||||
array(
|
||||
'section' => 'jetpack_content_options',
|
||||
'label' => esc_html__( 'Display author', 'jetpack-classic-theme-helper' ),
|
||||
'type' => 'checkbox',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Post Details: Comment link.
|
||||
if ( ! empty( $comment ) ) {
|
||||
$wp_customize->add_setting(
|
||||
'jetpack_content_post_details_comment',
|
||||
array(
|
||||
'default' => 1,
|
||||
'type' => 'option',
|
||||
'transport' => 'postMessage',
|
||||
'sanitize_callback' => 'jetpack_content_options_sanitize_checkbox',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
'jetpack_content_post_details_comment',
|
||||
array(
|
||||
'section' => 'jetpack_content_options',
|
||||
'label' => esc_html__( 'Display comment link', 'jetpack-classic-theme-helper' ),
|
||||
'type' => 'checkbox',
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Add Featured Images options.
|
||||
if ( true === $fi_archive || true === $fi_post || true === $fi_page || true === $fi_portfolio || true === $fi_fallback ) {
|
||||
$wp_customize->add_setting( 'jetpack_content_featured_images_title' );
|
||||
|
||||
$wp_customize->add_control(
|
||||
new Jetpack_Customize_Control_Title(
|
||||
$wp_customize,
|
||||
'jetpack_content_featured_images_title',
|
||||
array(
|
||||
'section' => 'jetpack_content_options',
|
||||
'label' => esc_html__( 'Featured Images', 'jetpack-classic-theme-helper' ) . sprintf( '<a href="https://en.support.wordpress.com/featured-images/" class="customize-help-toggle dashicons dashicons-editor-help" title="%1$s" rel="noopener noreferrer" target="_blank"><span class="screen-reader-text">%1$s</span></a>', esc_html__( 'Learn more about Featured Images', 'jetpack-classic-theme-helper' ) ),
|
||||
'type' => 'title',
|
||||
'active_callback' => 'jetpack_post_thumbnail_supports',
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// Featured Images: Archive.
|
||||
if ( true === $fi_archive ) {
|
||||
$wp_customize->add_setting(
|
||||
'jetpack_content_featured_images_archive',
|
||||
array(
|
||||
'default' => $fi_archive_default,
|
||||
'type' => 'option',
|
||||
'sanitize_callback' => 'jetpack_content_options_sanitize_checkbox',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
'jetpack_content_featured_images_archive',
|
||||
array(
|
||||
'section' => 'jetpack_content_options',
|
||||
'label' => esc_html__( 'Display on blog and archives', 'jetpack-classic-theme-helper' ),
|
||||
'type' => 'checkbox',
|
||||
'active_callback' => 'jetpack_post_thumbnail_supports',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Featured Images: Post.
|
||||
if ( true === $fi_post ) {
|
||||
$wp_customize->add_setting(
|
||||
'jetpack_content_featured_images_post',
|
||||
array(
|
||||
'default' => $fi_post_default,
|
||||
'type' => 'option',
|
||||
'sanitize_callback' => 'jetpack_content_options_sanitize_checkbox',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
'jetpack_content_featured_images_post',
|
||||
array(
|
||||
'section' => 'jetpack_content_options',
|
||||
'label' => esc_html__( 'Display on single posts', 'jetpack-classic-theme-helper' ),
|
||||
'type' => 'checkbox',
|
||||
'active_callback' => 'jetpack_post_thumbnail_supports',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Featured Images: Page.
|
||||
if ( true === $fi_page ) {
|
||||
$wp_customize->add_setting(
|
||||
'jetpack_content_featured_images_page',
|
||||
array(
|
||||
'default' => $fi_page_default,
|
||||
'type' => 'option',
|
||||
'sanitize_callback' => 'jetpack_content_options_sanitize_checkbox',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
'jetpack_content_featured_images_page',
|
||||
array(
|
||||
'section' => 'jetpack_content_options',
|
||||
'label' => esc_html__( 'Display on pages', 'jetpack-classic-theme-helper' ),
|
||||
'type' => 'checkbox',
|
||||
'active_callback' => 'jetpack_post_thumbnail_supports',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Featured Images: Portfolio.
|
||||
if ( true === $fi_portfolio && post_type_exists( 'jetpack-portfolio' ) ) {
|
||||
$wp_customize->add_setting(
|
||||
'jetpack_content_featured_images_portfolio',
|
||||
array(
|
||||
'default' => $fi_portfolio_default,
|
||||
'type' => 'option',
|
||||
'sanitize_callback' => 'jetpack_content_options_sanitize_checkbox',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
'jetpack_content_featured_images_portfolio',
|
||||
array(
|
||||
'section' => 'jetpack_content_options',
|
||||
'label' => esc_html__( 'Display on single projects', 'jetpack-classic-theme-helper' ),
|
||||
'type' => 'checkbox',
|
||||
'active_callback' => 'jetpack_post_thumbnail_supports',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Featured Images: Fallback.
|
||||
if ( true === $fi_fallback ) {
|
||||
$wp_customize->add_setting(
|
||||
'jetpack_content_featured_images_fallback',
|
||||
array(
|
||||
'default' => $fi_fallback_default,
|
||||
'type' => 'option',
|
||||
'sanitize_callback' => 'jetpack_content_options_sanitize_checkbox',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_control(
|
||||
'jetpack_content_featured_images_fallback',
|
||||
array(
|
||||
'section' => 'jetpack_content_options',
|
||||
'label' => esc_html__( 'Automatically use first image in post', 'jetpack-classic-theme-helper' ),
|
||||
'type' => 'checkbox',
|
||||
'active_callback' => 'jetpack_post_thumbnail_supports',
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
add_action( 'customize_register', 'jetpack_content_options_customize_register' );
|
||||
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_post_thumbnail_supports' ) ) {
|
||||
|
||||
/**
|
||||
* Return whether the theme supports Post Thumbnails.
|
||||
*/
|
||||
function jetpack_post_thumbnail_supports() {
|
||||
return ( current_theme_supports( 'post-thumbnails' ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_content_options_sanitize_checkbox' ) ) {
|
||||
|
||||
/**
|
||||
* Sanitize the checkbox.
|
||||
*
|
||||
* @param int $input The unsanitized value from the setting.
|
||||
* @return int|string
|
||||
*/
|
||||
function jetpack_content_options_sanitize_checkbox( $input ) {
|
||||
return ( 1 === (int) $input ) ? 1 : '';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_content_options_sanitize_blog_display' ) ) {
|
||||
|
||||
/**
|
||||
* Sanitize the Display value.
|
||||
*
|
||||
* @param string $display The unsanitized value from the setting.
|
||||
* @return string
|
||||
*/
|
||||
function jetpack_content_options_sanitize_blog_display( $display ) {
|
||||
if ( ! in_array( $display, array( 'content', 'excerpt', 'mixed' ), true ) ) {
|
||||
$display = 'content';
|
||||
}
|
||||
return $display;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_content_options_customize_preview_js' ) ) {
|
||||
|
||||
/**
|
||||
* Binds JS handlers to make Theme Customizer preview reload changes asynchronously.
|
||||
*/
|
||||
function jetpack_content_options_customize_preview_js() {
|
||||
$options = get_theme_support( 'jetpack-content-options' );
|
||||
$blog_display = ( ! empty( $options[0]['blog-display'] ) ) ? $options[0]['blog-display'] : null;
|
||||
$blog_display = preg_grep( '/^(content|excerpt)$/', (array) $blog_display );
|
||||
sort( $blog_display );
|
||||
$blog_display = implode( ', ', $blog_display );
|
||||
$blog_display = ( 'content, excerpt' === $blog_display ) ? 'mixed' : $blog_display;
|
||||
$masonry = ( ! empty( $options[0]['masonry'] ) ) ? $options[0]['masonry'] : null;
|
||||
$post_details = ( ! empty( $options[0]['post-details'] ) ) ? $options[0]['post-details'] : null;
|
||||
$date = ( ! empty( $post_details['date'] ) ) ? $post_details['date'] : null;
|
||||
$categories = ( ! empty( $post_details['categories'] ) ) ? $post_details['categories'] : null;
|
||||
$tags = ( ! empty( $post_details['tags'] ) ) ? $post_details['tags'] : null;
|
||||
$author = ( ! empty( $post_details['author'] ) ) ? $post_details['author'] : null;
|
||||
$comment = ( ! empty( $post_details['comment'] ) ) ? $post_details['comment'] : null;
|
||||
|
||||
Assets::register_script(
|
||||
'jetpack-content-options-customizer',
|
||||
'../../dist/content-options/customizer.js',
|
||||
__FILE__,
|
||||
array(
|
||||
'dependencies' => array(
|
||||
'customize-preview',
|
||||
),
|
||||
'in_footer' => true,
|
||||
'enqueue' => true,
|
||||
)
|
||||
);
|
||||
|
||||
wp_localize_script(
|
||||
'jetpack-content-options-customizer',
|
||||
'blogDisplay',
|
||||
array(
|
||||
'display' => get_option( 'jetpack_content_blog_display', $blog_display ),
|
||||
'masonry' => $masonry,
|
||||
)
|
||||
);
|
||||
|
||||
wp_localize_script(
|
||||
'jetpack-content-options-customizer',
|
||||
'postDetails',
|
||||
array(
|
||||
'date' => $date,
|
||||
'categories' => $categories,
|
||||
'tags' => $tags,
|
||||
'author' => $author,
|
||||
'comment' => $comment,
|
||||
)
|
||||
);
|
||||
}
|
||||
add_action( 'customize_preview_init', 'jetpack_content_options_customize_preview_js' );
|
||||
|
||||
}
|
||||
+244
@@ -0,0 +1,244 @@
|
||||
<?php
|
||||
/**
|
||||
* Theme Tools: functions for Featured Images fallback.
|
||||
*
|
||||
* @package automattic/jetpack-classic-theme-helper
|
||||
*/
|
||||
|
||||
use Automattic\Jetpack\Post_Media\Images;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_featured_images_fallback_get_image' ) ) {
|
||||
|
||||
/**
|
||||
* Get one image from a specified post in the following order:
|
||||
* Featured Image then first image from the_content HTML
|
||||
* and filter the post_thumbnail_html
|
||||
*
|
||||
* @param string $html The HTML for the image markup.
|
||||
* @param int $post_id The post ID to check.
|
||||
* @param int $post_thumbnail_id The ID of the featured image.
|
||||
* @param string $size The image size to return, defaults to 'post-thumbnail'.
|
||||
* @param string|array $attr Optional. Query string or array of attributes.
|
||||
*
|
||||
* @return string $html Thumbnail image with markup.
|
||||
*/
|
||||
function jetpack_featured_images_fallback_get_image( $html, $post_id, $post_thumbnail_id, $size, $attr ) {
|
||||
$opts = jetpack_featured_images_get_settings();
|
||||
|
||||
if ( ! empty( $html ) || (bool) 1 !== (bool) $opts['fallback-option'] ) {
|
||||
return trim( $html );
|
||||
}
|
||||
|
||||
if ( jetpack_featured_images_should_load() ) {
|
||||
if (
|
||||
( true === $opts['archive'] && ( is_home() || is_archive() || is_search() ) && ! $opts['archive-option'] )
|
||||
|| ( true === $opts['post'] && is_single() && ! $opts['post-option'] )
|
||||
|| ! $opts['fallback-option']
|
||||
) {
|
||||
return trim( $html );
|
||||
}
|
||||
}
|
||||
|
||||
global $_wp_additional_image_sizes;
|
||||
|
||||
$args = array(
|
||||
'from_thumbnail' => false,
|
||||
'from_slideshow' => true,
|
||||
'from_gallery' => true,
|
||||
'from_attachment' => false,
|
||||
);
|
||||
|
||||
$image = Images::get_image( $post_id, $args );
|
||||
|
||||
if ( ! empty( $image ) ) {
|
||||
$image['width'] = '';
|
||||
$image['height'] = '';
|
||||
$image['crop'] = '';
|
||||
|
||||
if ( array_key_exists( $size, $_wp_additional_image_sizes ) ) {
|
||||
$image['width'] = $_wp_additional_image_sizes[ $size ]['width'];
|
||||
$image['height'] = $_wp_additional_image_sizes[ $size ]['height'];
|
||||
$image['crop'] = $_wp_additional_image_sizes[ $size ]['crop'];
|
||||
}
|
||||
|
||||
// Force `crop` to be a simple boolean, to avoid dealing with WP crop positions.
|
||||
$image['crop'] = boolval( $image['crop'] );
|
||||
|
||||
$image_sizes = '';
|
||||
|
||||
$width = isset( $image['width'] ) ? intval( $image['width'] ) : null;
|
||||
$height = isset( $image['height'] ) ? intval( $image['height'] ) : null;
|
||||
|
||||
if ( ! empty( $image['src_width'] ) && ! empty( $image['src_height'] ) && ! empty( $image['width'] ) && ! empty( $image['height'] ) ) {
|
||||
$src_width = intval( $image['src_width'] );
|
||||
$src_height = intval( $image['src_height'] );
|
||||
|
||||
// If we're aware of the source dimensions, calculate the final image height and width.
|
||||
// This allows us to provide them as attributes in the `<img>` tag, to avoid layout shifts.
|
||||
// It also allows us to calculate a `srcset`.
|
||||
if ( $image['crop'] ) {
|
||||
// If we're cropping, the final dimensions are calculated independently of each other.
|
||||
$width = min( $width, $src_width );
|
||||
$height = min( $height, $src_height );
|
||||
} else {
|
||||
// If we're not cropping, we need to preserve aspect ratio.
|
||||
$dims = wp_constrain_dimensions( $src_width, $src_height, $width, $height );
|
||||
$width = $dims[0];
|
||||
$height = $dims[1];
|
||||
}
|
||||
|
||||
$image_src = Images::fit_image_url( $image['src'], $width, $height );
|
||||
$image_srcset = Images::generate_cropped_srcset( $image, $width, $height, true );
|
||||
$image_sizes = 'min(' . $width . 'px, 100vw)';
|
||||
} else {
|
||||
// If we're not aware of the source dimensions, leave the size calculations to the CDN, and
|
||||
// fall back to a simpler `<img>` tag without `width`/`height` or `srcset`.
|
||||
$image_src = Images::fit_image_url( $image['src'], $image['width'], $image['height'] );
|
||||
|
||||
// Use the theme's crop setting rather than forcing to true.
|
||||
$image_src = add_query_arg( 'crop', $image['crop'], $image_src );
|
||||
|
||||
$image_srcset = null;
|
||||
$image_sizes = null;
|
||||
}
|
||||
|
||||
$default_attr = array(
|
||||
'srcset' => $image_srcset,
|
||||
'sizes' => $image_sizes,
|
||||
'loading' => is_singular() ? 'eager' : 'lazy',
|
||||
'decoding' => 'async',
|
||||
'title' => wp_strip_all_tags( get_the_title() ),
|
||||
'alt' => '',
|
||||
'class' => "attachment-$size wp-post-image",
|
||||
);
|
||||
|
||||
$image_attr = wp_parse_args( $attr, $default_attr );
|
||||
$hwstring = image_hwstring( $width, $height );
|
||||
|
||||
$html = rtrim( "<img $hwstring" );
|
||||
$html .= ' src="' . esc_url( $image_src ) . '"';
|
||||
|
||||
foreach ( $image_attr as $name => $value ) {
|
||||
if ( $value ) {
|
||||
$html .= " $name=" . '"' . esc_attr( $value ) . '"';
|
||||
}
|
||||
}
|
||||
|
||||
$html .= ' />';
|
||||
|
||||
return trim( $html );
|
||||
}
|
||||
|
||||
return trim( $html );
|
||||
}
|
||||
add_filter( 'post_thumbnail_html', 'jetpack_featured_images_fallback_get_image', 10, 5 );
|
||||
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_featured_images_fallback_get_image_src' ) ) {
|
||||
|
||||
/**
|
||||
* Get URL of one image from a specified post in the following order:
|
||||
* Featured Image then first image from the_content HTML
|
||||
*
|
||||
* @param int $post_id The post ID to check.
|
||||
* @param int $post_thumbnail_id The ID of the featured image.
|
||||
* @param string $size The image size to return, defaults to 'post-thumbnail'.
|
||||
*
|
||||
* @return string|null $image_src The URL of the thumbnail image.
|
||||
*/
|
||||
function jetpack_featured_images_fallback_get_image_src( $post_id, $post_thumbnail_id, $size ) {
|
||||
$image_src = wp_get_attachment_image_src( $post_thumbnail_id, $size );
|
||||
$image_src = ( ! empty( $image_src[0] ) ) ? $image_src[0] : '';
|
||||
$opts = jetpack_featured_images_get_settings();
|
||||
|
||||
if ( ! empty( $image_src ) || (bool) 1 !== (bool) $opts['fallback-option'] ) {
|
||||
return esc_url( $image_src );
|
||||
}
|
||||
|
||||
if ( jetpack_featured_images_should_load() ) {
|
||||
if ( ( true === $opts['archive'] && ( is_home() || is_archive() || is_search() ) && ! $opts['archive-option'] )
|
||||
|| ( true === $opts['post'] && is_single() && ! $opts['post-option'] ) ) {
|
||||
return esc_url( $image_src );
|
||||
}
|
||||
}
|
||||
|
||||
global $_wp_additional_image_sizes;
|
||||
|
||||
$args = array(
|
||||
'from_thumbnail' => false,
|
||||
'from_slideshow' => true,
|
||||
'from_gallery' => true,
|
||||
'from_attachment' => false,
|
||||
);
|
||||
|
||||
$image = Images::get_image( $post_id, $args );
|
||||
|
||||
if ( ! empty( $image ) ) {
|
||||
$image['width'] = '';
|
||||
$image['height'] = '';
|
||||
$image['crop'] = '';
|
||||
|
||||
if ( array_key_exists( $size, $_wp_additional_image_sizes ) ) {
|
||||
$image['width'] = $_wp_additional_image_sizes[ $size ]['width'];
|
||||
$image['height'] = $_wp_additional_image_sizes[ $size ]['height'];
|
||||
$image['crop'] = $_wp_additional_image_sizes[ $size ]['crop'];
|
||||
}
|
||||
|
||||
$image_src = Images::fit_image_url( $image['src'], $image['width'], $image['height'] );
|
||||
|
||||
// Use the theme's crop setting rather than forcing to true.
|
||||
$image_src = add_query_arg( 'crop', $image['crop'], $image_src );
|
||||
|
||||
return esc_url( $image_src );
|
||||
}
|
||||
|
||||
return esc_url( $image_src );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_has_featured_image' ) ) {
|
||||
|
||||
/**
|
||||
* Check if post has an image attached, including a fallback.
|
||||
*
|
||||
* @param int $post The post ID to check.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function jetpack_has_featured_image( $post = null ) {
|
||||
return (bool) get_the_post_thumbnail( $post );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_featured_images_post_class' ) ) {
|
||||
|
||||
/**
|
||||
* Adds custom class to the array of post classes.
|
||||
*
|
||||
* @param array $classes Classes for the post element.
|
||||
* @param array $class Optional. Comma-separated list of additional classes.
|
||||
* @param int $post_id Unique The post ID to check.
|
||||
*
|
||||
* @return array $classes
|
||||
*/
|
||||
function jetpack_featured_images_post_class( $classes, $class, $post_id ) {
|
||||
$post_password_required = post_password_required( $post_id );
|
||||
$opts = jetpack_featured_images_get_settings();
|
||||
|
||||
if ( jetpack_has_featured_image( $post_id ) && (bool) 1 === (bool) $opts['fallback-option'] && ! is_attachment() && ! $post_password_required && 'post' === get_post_type() ) {
|
||||
$classes[] = 'has-post-thumbnail';
|
||||
$classes[] = 'fallback-thumbnail';
|
||||
}
|
||||
|
||||
return $classes;
|
||||
}
|
||||
add_filter( 'post_class', 'jetpack_featured_images_post_class', 10, 3 );
|
||||
|
||||
}
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
/**
|
||||
* Theme Tools: functions for Featured Images.
|
||||
*
|
||||
* @package automattic/jetpack-classic-theme-helper
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_featured_images_remove_post_thumbnail' ) ) {
|
||||
|
||||
/**
|
||||
* The function to prevent for Featured Images to be displayed in a theme.
|
||||
*
|
||||
* @param array $metadata Post metadata.
|
||||
* @param int $object_id Post ID.
|
||||
* @param string $meta_key Metadata key.
|
||||
*/
|
||||
function jetpack_featured_images_remove_post_thumbnail( $metadata, $object_id, $meta_key ) {
|
||||
$opts = jetpack_featured_images_get_settings();
|
||||
|
||||
/**
|
||||
* Allow featured images to be displayed at all times for specific CPTs.
|
||||
*
|
||||
* @module theme-tools
|
||||
*
|
||||
* @since 9.1.0
|
||||
*
|
||||
* @param array $excluded_post_types Array of excluded post types.
|
||||
*/
|
||||
$excluded_post_types = apply_filters(
|
||||
'jetpack_content_options_featured_image_exclude_cpt',
|
||||
array( 'jp_pay_product' )
|
||||
);
|
||||
|
||||
// Automatically return metadata for specific post types, when we don't want to hide the Featured Image.
|
||||
if ( in_array( get_post_type( $object_id ), $excluded_post_types, true ) ) {
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
// Return false if the archive option or singular option is unticked.
|
||||
if (
|
||||
( true === $opts['archive']
|
||||
&& ( is_home() || is_archive() || is_search() )
|
||||
&& ! jetpack_is_shop_page()
|
||||
&& ! $opts['archive-option']
|
||||
&& ( isset( $meta_key )
|
||||
&& '_thumbnail_id' === $meta_key )
|
||||
&& in_the_loop()
|
||||
)
|
||||
|| ( true === $opts['post']
|
||||
&& is_single()
|
||||
&& ! jetpack_is_product()
|
||||
&& ! $opts['post-option']
|
||||
&& ( isset( $meta_key )
|
||||
&& '_thumbnail_id' === $meta_key )
|
||||
&& in_the_loop()
|
||||
)
|
||||
|| ( true === $opts['page']
|
||||
&& is_singular()
|
||||
&& is_page()
|
||||
&& ! $opts['page-option']
|
||||
&& ( isset( $meta_key )
|
||||
&& '_thumbnail_id' === $meta_key )
|
||||
&& in_the_loop()
|
||||
)
|
||||
|| ( true === $opts['portfolio']
|
||||
&& post_type_exists( 'jetpack-portfolio' )
|
||||
&& is_singular( 'jetpack-portfolio' )
|
||||
&& ! $opts['portfolio-option']
|
||||
&& ( isset( $meta_key )
|
||||
&& '_thumbnail_id' === $meta_key )
|
||||
&& in_the_loop()
|
||||
)
|
||||
) {
|
||||
|
||||
// Do not override thumbnail settings within blocks (eg. Latest Posts block).
|
||||
$trace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_debug_backtrace
|
||||
foreach ( $trace as $frame ) {
|
||||
if ( ! empty( $frame['class'] ) && class_exists( $frame['class'], false ) && is_a( $frame['class'], WP_Block::class, true ) ) {
|
||||
return $metadata;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} else {
|
||||
return $metadata;
|
||||
}
|
||||
}
|
||||
// We need this hook to execute at the end since core overrides the thumbnail id in _wp_preview_post_thumbnail_filter.
|
||||
add_filter( 'get_post_metadata', 'jetpack_featured_images_remove_post_thumbnail', PHP_INT_MAX, 3 );
|
||||
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_is_product' ) ) {
|
||||
|
||||
/**
|
||||
* Check if we are in a WooCommerce Product in order to exclude it from the is_single check.
|
||||
*/
|
||||
function jetpack_is_product() {
|
||||
return ( function_exists( 'is_product' ) ) ? is_product() : false; // @phan-suppress-current-line PhanUndeclaredFunction -- We only call the function if it exists.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_is_shop_page' ) ) {
|
||||
|
||||
/**
|
||||
* Check if we are in a WooCommerce Shop in order to exclude it from the is_archive check.
|
||||
*/
|
||||
function jetpack_is_shop_page() {
|
||||
// Check if WooCommerce is active first.
|
||||
if ( ! class_exists( 'WooCommerce' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
global $wp_query;
|
||||
|
||||
$front_page_id = get_option( 'page_on_front' );
|
||||
$current_page_id = $wp_query->get( 'page_id' );
|
||||
$is_static_front_page = 'page' === get_option( 'show_on_front' );
|
||||
|
||||
$is_shop_page = false;
|
||||
if ( $is_static_front_page && $front_page_id === $current_page_id ) {
|
||||
$is_shop_page = function_exists( 'wc_get_page_id' ) && wc_get_page_id( 'shop' ) === $current_page_id; // @phan-suppress-current-line PhanUndeclaredFunction -- We're checking the function exists first.
|
||||
} elseif ( function_exists( 'is_shop' ) ) {
|
||||
$is_shop_page = is_shop(); // @phan-suppress-current-line PhanUndeclaredFunction -- We're checking the function exists first.
|
||||
}
|
||||
|
||||
return $is_shop_page;
|
||||
}
|
||||
|
||||
}
|
||||
+186
@@ -0,0 +1,186 @@
|
||||
<?php
|
||||
/**
|
||||
* Theme Tools: functions for Post Details.
|
||||
*
|
||||
* @package automattic/jetpack-classic-theme-helper
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_post_details_enqueue_scripts' ) ) {
|
||||
|
||||
/**
|
||||
* The function to include Post Details in a theme's stylesheet.
|
||||
*/
|
||||
function jetpack_post_details_enqueue_scripts() {
|
||||
// Make sure we can proceed.
|
||||
list( $should_run, $options, $definied, $post_details ) = jetpack_post_details_should_run();
|
||||
|
||||
if ( ! $should_run ) {
|
||||
return;
|
||||
}
|
||||
|
||||
list( $date_option, $categories_option, $tags_option, $author_option, $comment_option ) = $options;
|
||||
list( $date, $categories, $tags, $author, $comment ) = $definied;
|
||||
|
||||
$elements = array();
|
||||
|
||||
// If date option is unticked, add it to the list of classes.
|
||||
if ( 1 !== (int) $date_option && ! empty( $date ) ) {
|
||||
$elements[] = $date;
|
||||
}
|
||||
|
||||
// If categories option is unticked, add it to the list of classes.
|
||||
if ( 1 !== (int) $categories_option && ! empty( $categories ) ) {
|
||||
$elements[] = $categories;
|
||||
}
|
||||
|
||||
// If tags option is unticked, add it to the list of classes.
|
||||
if ( 1 !== (int) $tags_option && ! empty( $tags ) ) {
|
||||
$elements[] = $tags;
|
||||
}
|
||||
|
||||
// If author option is unticked, add it to the list of classes.
|
||||
if ( 1 !== (int) $author_option && ! empty( $author ) ) {
|
||||
$elements[] = $author;
|
||||
}
|
||||
|
||||
// If comment option is unticked, add it to the list of classes.
|
||||
if ( 1 !== (int) $comment_option && ! empty( $comment ) ) {
|
||||
$elements[] = $comment;
|
||||
}
|
||||
|
||||
// If the Elements array is empty, return without setting custom CSS.
|
||||
if ( empty( $elements ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the list of classes.
|
||||
$elements = implode( ', ', $elements );
|
||||
|
||||
// Hide the classes with CSS.
|
||||
$css = $elements . ' { clip: rect(1px, 1px, 1px, 1px); height: 1px; position: absolute; overflow: hidden; width: 1px; }';
|
||||
|
||||
// Add the CSS to the stylesheet.
|
||||
|
||||
if ( is_array( $post_details ) && isset( $post_details['stylesheet'] ) ) {
|
||||
wp_add_inline_style( $post_details['stylesheet'], $css );
|
||||
}
|
||||
}
|
||||
add_action( 'wp_enqueue_scripts', 'jetpack_post_details_enqueue_scripts' );
|
||||
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_post_details_body_classes' ) ) {
|
||||
|
||||
/**
|
||||
* Adds custom classes to the array of body classes.
|
||||
*
|
||||
* @param array $classes Classes for the body element.
|
||||
*/
|
||||
function jetpack_post_details_body_classes( $classes ) {
|
||||
// Make sure we can proceed.
|
||||
list( $should_run, $options, $definied ) = jetpack_post_details_should_run();
|
||||
|
||||
if ( ! $should_run ) {
|
||||
return $classes;
|
||||
}
|
||||
|
||||
list( $date_option, $categories_option, $tags_option, $author_option, $comment_option ) = $options;
|
||||
list( $date, $categories, $tags, $author, $comment ) = $definied;
|
||||
|
||||
// If date option is unticked, add a class of 'date-hidden' to the body.
|
||||
if ( 1 !== (int) $date_option && ! empty( $date ) ) {
|
||||
$classes[] = 'date-hidden';
|
||||
}
|
||||
|
||||
// If categories option is unticked, add a class of 'categories-hidden' to the body.
|
||||
if ( 1 !== (int) $categories_option && ! empty( $categories ) ) {
|
||||
$classes[] = 'categories-hidden';
|
||||
}
|
||||
|
||||
// If tags option is unticked, add a class of 'tags-hidden' to the body.
|
||||
if ( 1 !== (int) $tags_option && ! empty( $tags ) ) {
|
||||
$classes[] = 'tags-hidden';
|
||||
}
|
||||
|
||||
// If author option is unticked, add a class of 'author-hidden' to the body.
|
||||
if ( 1 !== (int) $author_option && ! empty( $author ) ) {
|
||||
$classes[] = 'author-hidden';
|
||||
}
|
||||
|
||||
// If comment option is unticked, add a class of 'comment-hidden' to the body.
|
||||
if ( 1 !== (int) $comment_option && ! empty( $comment ) ) {
|
||||
$classes[] = 'comment-hidden';
|
||||
}
|
||||
|
||||
return $classes;
|
||||
}
|
||||
add_filter( 'body_class', 'jetpack_post_details_body_classes' );
|
||||
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_post_details_should_run' ) ) {
|
||||
|
||||
/**
|
||||
* Determines if Post Details should run.
|
||||
*/
|
||||
function jetpack_post_details_should_run() {
|
||||
// Empty value representing falsy return value.
|
||||
$void = array( false, null, null, null );
|
||||
|
||||
// If the theme doesn't support 'jetpack-content-options', don't continue.
|
||||
if ( ! current_theme_supports( 'jetpack-content-options' ) ) {
|
||||
return $void;
|
||||
}
|
||||
|
||||
$options = get_theme_support( 'jetpack-content-options' );
|
||||
$post_details = ( ! empty( $options[0]['post-details'] ) ) ? $options[0]['post-details'] : null;
|
||||
|
||||
// If the theme doesn't support 'jetpack-content-options[ 'post-details' ]', don't continue.
|
||||
if ( empty( $post_details ) ) {
|
||||
return $void;
|
||||
}
|
||||
|
||||
$date = ( ! empty( $post_details['date'] ) ) ? $post_details['date'] : null;
|
||||
$categories = ( ! empty( $post_details['categories'] ) ) ? $post_details['categories'] : null;
|
||||
$tags = ( ! empty( $post_details['tags'] ) ) ? $post_details['tags'] : null;
|
||||
$author = ( ! empty( $post_details['author'] ) ) ? $post_details['author'] : null;
|
||||
$comment = ( ! empty( $post_details['comment'] ) ) ? $post_details['comment'] : null;
|
||||
|
||||
// If there is no stylesheet and there are no date, categories, tags, author or comment declared, don't continue.
|
||||
if (
|
||||
empty( $post_details['stylesheet'] )
|
||||
&& ( empty( $date )
|
||||
|| empty( $categories )
|
||||
|| empty( $tags )
|
||||
|| empty( $author )
|
||||
|| empty( $comment ) )
|
||||
) {
|
||||
return $void;
|
||||
}
|
||||
|
||||
if ( class_exists( 'Jetpack_Options' ) ) {
|
||||
|
||||
$date_option = Jetpack_Options::get_option_and_ensure_autoload( 'jetpack_content_post_details_date', 1 ); // @phan-suppress-current-line PhanUndeclaredClassMethod -- We're only running this code if the class exists.
|
||||
$categories_option = Jetpack_Options::get_option_and_ensure_autoload( 'jetpack_content_post_details_categories', 1 ); // @phan-suppress-current-line PhanUndeclaredClassMethod -- We're only running this code if the class exists.
|
||||
$tags_option = Jetpack_Options::get_option_and_ensure_autoload( 'jetpack_content_post_details_tags', 1 ); // @phan-suppress-current-line PhanUndeclaredClassMethod -- We're only running this code if the class exists.
|
||||
$author_option = Jetpack_Options::get_option_and_ensure_autoload( 'jetpack_content_post_details_author', 1 ); // @phan-suppress-current-line PhanUndeclaredClassMethod -- We're only running this code if the class exists.
|
||||
$comment_option = Jetpack_Options::get_option_and_ensure_autoload( 'jetpack_content_post_details_comment', 1 ); // @phan-suppress-current-line PhanUndeclaredClassMethod -- We're only running this code if the class exists.
|
||||
|
||||
$options = array( $date_option, $categories_option, $tags_option, $author_option, $comment_option );
|
||||
$definied = array( $date, $categories, $tags, $author, $comment );
|
||||
|
||||
// If all the options are ticked, don't continue.
|
||||
if ( array( 1, 1, 1, 1, 1 ) === $options ) {
|
||||
return $void;
|
||||
}
|
||||
|
||||
return array( true, $options, $definied, $post_details );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+211
@@ -0,0 +1,211 @@
|
||||
<?php
|
||||
/**
|
||||
* Module Name: Custom content types
|
||||
* Module Description: Display different types of content on your site with custom content types.
|
||||
* First Introduced: 3.1
|
||||
* Requires Connection: No
|
||||
* Auto Activate: No
|
||||
* Module Tags: Writing
|
||||
* Sort Order: 34
|
||||
* Feature: Writing
|
||||
* Additional Search Queries: cpt, custom post types, portfolio, portfolios, testimonial, testimonials, nova
|
||||
*
|
||||
* @package automattic/jetpack-classic-theme-helper
|
||||
*/
|
||||
|
||||
use Automattic\Jetpack\Classic_Theme_Helper\Jetpack_Portfolio;
|
||||
use Automattic\Jetpack\Classic_Theme_Helper\Jetpack_Testimonial;
|
||||
use Automattic\Jetpack\Redirect;
|
||||
use Automattic\Jetpack\Status\Host;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_load_custom_post_types' ) ) {
|
||||
/**
|
||||
* Load Portfolio, Testimonial, and Nova CPT.
|
||||
*/
|
||||
function jetpack_load_custom_post_types() {
|
||||
include __DIR__ . '/custom-post-types/class-jetpack-portfolio.php';
|
||||
include __DIR__ . '/custom-post-types/class-jetpack-testimonial.php';
|
||||
include __DIR__ . '/custom-post-types/class-nova-restaurant.php';
|
||||
}
|
||||
add_action( 'init', array( '\Automattic\Jetpack\Classic_Theme_Helper\Jetpack_Portfolio', 'init' ) );
|
||||
register_activation_hook( __FILE__, array( '\Automattic\Jetpack\Classic_Theme_Helper\Jetpack_Portfolio', 'activation_post_type_support' ) );
|
||||
add_action( 'jetpack_activate_module_custom-content-types', array( '\Automattic\Jetpack\Classic_Theme_Helper\Jetpack_Portfolio', 'activation_post_type_support' ) );
|
||||
|
||||
add_action( 'init', array( '\Automattic\Jetpack\Classic_Theme_Helper\Jetpack_Testimonial', 'init' ) );
|
||||
register_activation_hook( __FILE__, array( '\Automattic\Jetpack\Classic_Theme_Helper\Jetpack_Testimonial', 'activation_post_type_support' ) );
|
||||
add_action( 'jetpack_activate_module_custom-content-types', array( '\Automattic\Jetpack\Classic_Theme_Helper\Jetpack_Testimonial', 'activation_post_type_support' ) );
|
||||
|
||||
add_action( 'init', array( '\Automattic\Jetpack\Classic_Theme_Helper\Nova_Restaurant', 'init' ) );
|
||||
|
||||
add_action( 'rest_api_init', 'register_rest_route_custom_content_types' );
|
||||
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_custom_post_types_loaded' ) ) {
|
||||
/**
|
||||
* Pass the active status to the front-end in it's initial state.
|
||||
*/
|
||||
function jetpack_custom_post_types_loaded() {
|
||||
// Ensure we're only adding this script on the Jetpack settings page.
|
||||
if ( ! isset( $_GET['page'] ) || 'jetpack' !== $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- We are not processing any data here.
|
||||
return;
|
||||
}
|
||||
$initial_state = 'var CUSTOM_CONTENT_TYPE__INITIAL_STATE; typeof CUSTOM_CONTENT_TYPE__INITIAL_STATE === "object" || (CUSTOM_CONTENT_TYPE__INITIAL_STATE = ' . wp_json_encode(
|
||||
array(
|
||||
'active' => classic_theme_helper_cpt_should_be_active(),
|
||||
'over_ride' => false,
|
||||
'should_show_testimonials' => Jetpack_Testimonial::site_should_display_testimonials() ? true : false,
|
||||
'should_show_portfolios' => Jetpack_Portfolio::site_should_display_portfolios() ? true : false,
|
||||
),
|
||||
JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP
|
||||
) . ');';
|
||||
|
||||
// Create a global variable with the custom content type feature status so that the value is available
|
||||
// earlier than the API method above allows, preventing delayed loading of the settings card.
|
||||
wp_register_script( 'custom-content-types-data', '', array(), '0.1.0', true );
|
||||
wp_enqueue_script( 'custom-content-types-data' );
|
||||
wp_add_inline_script(
|
||||
'custom-content-types-data',
|
||||
$initial_state,
|
||||
'before'
|
||||
);
|
||||
}
|
||||
add_action( 'init', 'jetpack_custom_post_types_loaded' );
|
||||
}
|
||||
if ( ! function_exists( 'register_rest_route_custom_content_types' ) ) {
|
||||
/**
|
||||
* Register the REST route for the custom content types.
|
||||
*/
|
||||
function register_rest_route_custom_content_types() {
|
||||
|
||||
register_rest_route(
|
||||
'jetpack/v4',
|
||||
'/feature/custom-content-types',
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => 'get_custom_content_type_details',
|
||||
'permission_callback' => 'custom_content_require_admin_privilege_callback',
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the custom content type details.
|
||||
*
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
function get_custom_content_type_details() {
|
||||
|
||||
$active = classic_theme_helper_cpt_should_be_active();
|
||||
$over_ride = false;
|
||||
$name = 'Custom Content Types';
|
||||
$description = 'Display different types of content on your site with custom content types.';
|
||||
$additional_search_queries = 'cpt, custom post types, portfolio, portfolios, testimonial, testimonials';
|
||||
|
||||
return rest_ensure_response(
|
||||
array(
|
||||
'custom-content-types' => array(
|
||||
'active' => $active,
|
||||
'over_ride' => $over_ride,
|
||||
'name' => $name,
|
||||
'description' => $description,
|
||||
'additional_search_queries' => $additional_search_queries,
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the current user has the required capability.
|
||||
*
|
||||
* @return bool|WP_Error True if the request is made by ad administrator, WP_Error otherwise.
|
||||
*/
|
||||
function custom_content_require_admin_privilege_callback() {
|
||||
if ( current_user_can( 'manage_options' ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return new WP_Error(
|
||||
'rest_forbidden',
|
||||
esc_html__( 'You are not allowed to perform this action.', 'jetpack-classic-theme-helper' ),
|
||||
array( 'status' => rest_authorization_required_code() )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the custom content types should be active.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function classic_theme_helper_cpt_should_be_active() {
|
||||
if ( ! Jetpack_Testimonial::site_should_display_testimonials() && ! Jetpack_Portfolio::site_should_display_portfolios() ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_cpt_settings_api_init' ) ) {
|
||||
/**
|
||||
* Add Settings Section for CPT
|
||||
*/
|
||||
function jetpack_cpt_settings_api_init() {
|
||||
if ( ! classic_theme_helper_cpt_should_be_active() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_settings_section(
|
||||
'jetpack_cpt_section',
|
||||
'<span id="cpt-options">' . __( 'Your Custom Content Types', 'jetpack-classic-theme-helper' ) . '</span>',
|
||||
'jetpack_cpt_section_callback',
|
||||
'writing'
|
||||
);
|
||||
}
|
||||
if ( ( new Host() )->is_wpcom_simple() ) {
|
||||
add_action( 'admin_init', 'jetpack_cpt_settings_api_init', 15 );
|
||||
} else {
|
||||
add_action( 'admin_init', 'jetpack_cpt_settings_api_init' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_cpt_section_callback' ) ) {
|
||||
/**
|
||||
* Settings Description
|
||||
*/
|
||||
function jetpack_cpt_section_callback() {
|
||||
if ( class_exists( 'Redirect' ) ) {
|
||||
?>
|
||||
<p>
|
||||
<?php esc_html_e( 'Use these settings to display different types of content on your site.', 'jetpack-classic-theme-helper' ); ?>
|
||||
<a target="_blank" rel="noopener noreferrer" href="<?php echo esc_url( Redirect::get_url( 'jetpack-support-custom-content-types' ) ); ?>"><?php esc_html_e( 'Learn More', 'jetpack-classic-theme-helper' ); ?></a>
|
||||
</p>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Custom Content Types from the old Module list.
|
||||
* Available at wp-admin/admin.php?page=jetpack_modules
|
||||
*
|
||||
* @param array $items Array of Jetpack modules.
|
||||
* @todo Remove this function once the module file is removed from the Jetpack plugin.
|
||||
* @return array
|
||||
*/
|
||||
function remove_custom_content_types_module_list( $items ) {
|
||||
if ( isset( $items['custom-content-types'] ) ) {
|
||||
unset( $items['custom-content-types'] );
|
||||
}
|
||||
return $items;
|
||||
}
|
||||
add_filter( 'jetpack_modules_list_table_items', 'remove_custom_content_types_module_list' );
|
||||
|
||||
if ( function_exists( 'jetpack_load_custom_post_types' ) ) {
|
||||
|
||||
jetpack_load_custom_post_types();
|
||||
|
||||
}
|
||||
+1195
File diff suppressed because it is too large
Load Diff
+52
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/**
|
||||
* Helper class for the Jetpack Testimonial Textarea Control.
|
||||
*
|
||||
* @package automattic/jetpack-classic-theme-helper
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Classic_Theme_Helper;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
if ( ! class_exists( __NAMESPACE__ . '\Jetpack_Testimonial_Textarea_Control' ) ) {
|
||||
/**
|
||||
* Extends the WP_Customize_Control class to clean the textarea content.
|
||||
*/
|
||||
class Jetpack_Testimonial_Textarea_Control extends \WP_Customize_Control {
|
||||
/**
|
||||
* Control type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $type = 'textarea';
|
||||
|
||||
/**
|
||||
* Render the control's content.
|
||||
*/
|
||||
public function render_content() {
|
||||
?>
|
||||
<label>
|
||||
<span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
|
||||
<textarea rows="5" style="width:100%;" <?php $this->link(); ?>><?php echo esc_textarea( $this->value() ); ?></textarea>
|
||||
</label>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize content passed to control.
|
||||
*
|
||||
* @param string $value Control value.
|
||||
* @return string Sanitized value.
|
||||
*/
|
||||
public static function sanitize_content( $value ) {
|
||||
if ( ! empty( $value ) ) {
|
||||
$value = apply_filters( 'the_content', $value );
|
||||
}
|
||||
$value = preg_replace( '@<div id="jp-post-flair"([^>]+)?>(.+)?</div>@is', '', $value );
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/**
|
||||
* Helper class for the Jetpack Testimonial Title Control.
|
||||
*
|
||||
* @package automattic/jetpack-classic-theme-helper
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Classic_Theme_Helper;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
if ( ! class_exists( __NAMESPACE__ . '\Jetpack_Testimonial_Title_Control' ) ) {
|
||||
/**
|
||||
* Extends the WP_Customize_Control class to clean the title parameter.
|
||||
*/
|
||||
class Jetpack_Testimonial_Title_Control extends \WP_Customize_Control {
|
||||
/**
|
||||
* Sanitize content passed to control.
|
||||
*
|
||||
* @param string $value Control value.
|
||||
* @return string Sanitized value.
|
||||
*/
|
||||
public static function sanitize_content( $value ) {
|
||||
if ( '' != $value ) { // phpcs:ignore Universal.Operators.StrictComparisons.LooseNotEqual -- handle non-string inputs gracefully.
|
||||
$value = trim( convert_chars( wptexturize( $value ) ) );
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
+929
@@ -0,0 +1,929 @@
|
||||
<?php
|
||||
/**
|
||||
* Register a Testimonial post type and handle displaying it anywhere on the site.
|
||||
*
|
||||
* @package automattic/jetpack-classic-theme-helper
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Classic_Theme_Helper;
|
||||
|
||||
use Automattic\Jetpack\Blocks;
|
||||
use Automattic\Jetpack\Status\Host;
|
||||
use Jetpack_Options;
|
||||
use WP_Customize_Image_Control;
|
||||
use WP_Customize_Manager;
|
||||
use WP_Query;
|
||||
|
||||
if ( ! class_exists( __NAMESPACE__ . '\Jetpack_Testimonial' ) ) {
|
||||
|
||||
/**
|
||||
* Add a Testimonial CPT, and display it with a shortcode
|
||||
*/
|
||||
class Jetpack_Testimonial {
|
||||
const CUSTOM_POST_TYPE = 'jetpack-testimonial';
|
||||
const OPTION_NAME = 'jetpack_testimonial';
|
||||
const OPTION_READING_SETTING = 'jetpack_testimonial_posts_per_page';
|
||||
|
||||
/**
|
||||
* Initialize class.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function init() {
|
||||
|
||||
static $instance = false;
|
||||
|
||||
if ( ! $instance ) {
|
||||
$instance = new Jetpack_Testimonial();
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Conditionally hook into WordPress.
|
||||
*
|
||||
* Setup user option for enabling CPT.
|
||||
* If user has CPT enabled, show in admin.
|
||||
*/
|
||||
public function __construct() {
|
||||
|
||||
// Add an option to enable the CPT. Set the priority to 11 to ensure "Portfolio Projects" appears above "Testimonials" in the UI.
|
||||
add_action( 'admin_init', array( $this, 'settings_api_init' ), 11 );
|
||||
|
||||
// Check on theme switch if theme supports CPT and setting is disabled
|
||||
add_action( 'after_switch_theme', array( $this, 'activation_post_type_support' ) );
|
||||
|
||||
// Make sure the post types are loaded for imports
|
||||
add_action( 'import_start', array( $this, 'register_post_types' ) );
|
||||
|
||||
// If called via REST API, we need to register later in lifecycle
|
||||
add_action( 'restapi_theme_init', array( $this, 'maybe_register_cpt' ) );
|
||||
|
||||
// Add to REST API post type allowed list.
|
||||
add_filter( 'rest_api_allowed_post_types', array( $this, 'allow_cpt_rest_api_type' ) );
|
||||
|
||||
if ( get_option( self::OPTION_NAME, '0' ) || ( new Host() )->is_wpcom_platform() ) {
|
||||
$this->maybe_register_cpt();
|
||||
} else {
|
||||
add_action( 'init', array( $this, 'maybe_register_cpt' ) );
|
||||
}
|
||||
|
||||
// Add a variable with the theme support status for the Jetpack Settings Testimonial toggle UI.
|
||||
if ( current_theme_supports( self::CUSTOM_POST_TYPE ) ) {
|
||||
wp_register_script( 'jetpack-testimonial-theme-supports', '', array(), '0.1.0', true );
|
||||
wp_enqueue_script( 'jetpack-testimonial-theme-supports' );
|
||||
$supports_testimonial = ( new Host() )->is_woa_site() ? 'true' : 'false';
|
||||
} else {
|
||||
$supports_testimonial = 'false';
|
||||
}
|
||||
wp_add_inline_script(
|
||||
'jetpack-testimonial-theme-supports',
|
||||
'const jetpack_testimonial_theme_supports = ' . $supports_testimonial
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the custom post types and adds action/filter handlers, but
|
||||
* only if the site supports it
|
||||
*/
|
||||
public function maybe_register_cpt() {
|
||||
|
||||
$setting = class_exists( 'Jetpack_Options' ) ? Jetpack_Options::get_option_and_ensure_autoload( self::OPTION_NAME, '0' ) : '0'; // @phan-suppress-current-line PhanUndeclaredClassMethod -- We check if the class exists first.
|
||||
|
||||
// Bail early if Testimonial option is not set and the theme doesn't declare support
|
||||
if ( empty( $setting ) && ! $this->site_supports_custom_post_type() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// CPT magic
|
||||
$this->register_post_types();
|
||||
if ( ! post_type_exists( self::CUSTOM_POST_TYPE ) ) {
|
||||
return;
|
||||
}
|
||||
add_action( sprintf( 'add_option_%s', self::OPTION_NAME ), array( $this, 'flush_rules_on_enable' ), 10 );
|
||||
add_action( sprintf( 'update_option_%s', self::OPTION_NAME ), array( $this, 'flush_rules_on_enable' ), 10 );
|
||||
add_action( sprintf( 'publish_%s', self::CUSTOM_POST_TYPE ), array( $this, 'flush_rules_on_first_testimonial' ) );
|
||||
add_action( 'after_switch_theme', array( $this, 'flush_rules_on_switch' ) );
|
||||
|
||||
// Admin Customization
|
||||
add_filter( 'enter_title_here', array( $this, 'change_default_title' ) );
|
||||
add_filter( sprintf( 'manage_%s_posts_columns', self::CUSTOM_POST_TYPE ), array( $this, 'edit_title_column_label' ) );
|
||||
add_filter( 'post_updated_messages', array( $this, 'updated_messages' ) );
|
||||
if ( ! wp_is_block_theme() ) {
|
||||
add_action( 'customize_register', array( $this, 'customize_register' ) );
|
||||
}
|
||||
|
||||
// Only add the 'Customize' sub-menu if the theme supports it.
|
||||
if ( is_admin() && current_theme_supports( self::CUSTOM_POST_TYPE ) ) {
|
||||
add_action( 'admin_menu', array( $this, 'add_customize_page' ) );
|
||||
}
|
||||
|
||||
if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
|
||||
// Track all the things
|
||||
add_action( sprintf( 'add_option_%s', self::OPTION_NAME ), array( $this, 'new_activation_stat_bump' ) );
|
||||
add_action( sprintf( 'update_option_%s', self::OPTION_NAME ), array( $this, 'update_option_stat_bump' ), 11, 2 );
|
||||
add_action( sprintf( 'publish_%s', self::CUSTOM_POST_TYPE ), array( $this, 'new_testimonial_stat_bump' ) );
|
||||
|
||||
// Add to Dotcom XML sitemaps
|
||||
add_filter( 'wpcom_sitemap_post_types', array( $this, 'add_to_sitemap' ) );
|
||||
} else {
|
||||
// Add to Jetpack XML sitemap
|
||||
add_filter( 'jetpack_sitemap_post_types', array( $this, 'add_to_sitemap' ) );
|
||||
}
|
||||
|
||||
// Adjust CPT archive and custom taxonomies to obey CPT reading setting
|
||||
add_filter( 'pre_get_posts', array( $this, 'query_reading_setting' ), 20 );
|
||||
add_filter( 'infinite_scroll_settings', array( $this, 'infinite_scroll_click_posts_per_page' ) );
|
||||
|
||||
// Register [jetpack_testimonials] always and
|
||||
// register [testimonials] if [testimonials] isn't already set
|
||||
add_shortcode( 'jetpack_testimonials', array( $this, 'jetpack_testimonial_shortcode' ) );
|
||||
|
||||
if ( ! shortcode_exists( 'testimonials' ) ) {
|
||||
add_shortcode( 'testimonials', array( $this, 'jetpack_testimonial_shortcode' ) );
|
||||
}
|
||||
|
||||
// If CPT was enabled programatically and no CPT items exist when user switches away, disable
|
||||
if ( $setting && $this->site_supports_custom_post_type() ) {
|
||||
add_action( 'switch_theme', array( $this, 'deactivation_post_type_support' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a site should display testimonials - it should not if:
|
||||
* - the theme is a block theme without testimonials enabled.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function site_should_display_testimonials() {
|
||||
$should_display = true;
|
||||
if ( current_theme_supports( self::CUSTOM_POST_TYPE ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( ( ! ( new Host() )->is_wpcom_simple() ) && Blocks::is_fse_theme() ) {
|
||||
if ( ! get_option( self::OPTION_NAME, '0' ) ) {
|
||||
$should_display = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter whether the site should display testimonials.
|
||||
*
|
||||
* @since 0.11.0
|
||||
*
|
||||
* @param bool $should_display Whether testimonials should be displayed.
|
||||
*/
|
||||
return apply_filters( 'classic_theme_helper_should_display_testimonials', $should_display );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a checkbox field in 'Settings' > 'Writing'
|
||||
* for enabling CPT functionality.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function settings_api_init() {
|
||||
|
||||
if ( ! self::site_should_display_testimonials() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_settings_field(
|
||||
self::OPTION_NAME,
|
||||
'<span class="cpt-options">' . __( 'Testimonials', 'jetpack-classic-theme-helper' ) . '</span>',
|
||||
array( $this, 'setting_html' ),
|
||||
'writing',
|
||||
'jetpack_cpt_section'
|
||||
);
|
||||
|
||||
register_setting(
|
||||
'writing',
|
||||
self::OPTION_NAME,
|
||||
'intval'
|
||||
);
|
||||
|
||||
// Check if CPT is enabled first so that intval doesn't get set to NULL on re-registering.
|
||||
if ( $this->site_supports_custom_post_type() ) {
|
||||
register_setting(
|
||||
'writing',
|
||||
self::OPTION_READING_SETTING,
|
||||
'intval'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* HTML code to display a checkbox true/false option
|
||||
* for the CPT setting.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setting_html() {
|
||||
if ( current_theme_supports( self::CUSTOM_POST_TYPE ) ) : ?>
|
||||
<p><?php esc_html_e( 'Your theme supports Testimonials', 'jetpack-classic-theme-helper' ); ?></p>
|
||||
<?php else : ?>
|
||||
<label for="<?php echo esc_attr( self::OPTION_NAME ); ?>">
|
||||
<input name="<?php echo esc_attr( self::OPTION_NAME ); ?>" id="<?php echo esc_attr( self::OPTION_NAME ); ?>" <?php echo checked( get_option( self::OPTION_NAME, '0' ), true, false ); ?> type="checkbox" value="1" />
|
||||
<?php esc_html_e( 'Enable Testimonials for this site.', 'jetpack-classic-theme-helper' ); ?>
|
||||
<a target="_blank" href="https://en.support.wordpress.com/testimonials/" data-target="wpcom-help-center"><?php esc_html_e( 'Learn More', 'jetpack-classic-theme-helper' ); ?></a>
|
||||
</label>
|
||||
<?php
|
||||
endif;
|
||||
|
||||
if ( $this->site_supports_custom_post_type() ) :
|
||||
printf(
|
||||
'<p><label for="%1$s">%2$s</label></p>',
|
||||
esc_attr( self::OPTION_READING_SETTING ),
|
||||
sprintf(
|
||||
/* translators: %1$s is replaced with an input field for numbers */
|
||||
esc_html__( 'Testimonial pages display at most %1$s testimonials', 'jetpack-classic-theme-helper' ),
|
||||
sprintf(
|
||||
'<input name="%1$s" id="%1$s" type="number" step="1" min="1" value="%2$s" class="small-text" />',
|
||||
esc_attr( self::OPTION_READING_SETTING ),
|
||||
esc_attr( get_option( self::OPTION_READING_SETTING, '10' ) )
|
||||
)
|
||||
)
|
||||
);
|
||||
endif;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should this Custom Post Type be made available?
|
||||
*/
|
||||
private function site_supports_custom_post_type() {
|
||||
// If the current theme requests it.
|
||||
if ( current_theme_supports( self::CUSTOM_POST_TYPE ) || get_option( self::OPTION_NAME, '0' ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, say no unless something wants to filter us to say yes.
|
||||
/** This action is documented in classic-theme-helper/src/custom-post-types/class-nova-restaurant.php */
|
||||
return (bool) apply_filters( 'jetpack_enable_cpt', false, self::CUSTOM_POST_TYPE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add to REST API post type allowed list.
|
||||
*
|
||||
* @param array $post_types Array of allowed post types.
|
||||
* @return array `$post_types` with our type added.
|
||||
*/
|
||||
public function allow_cpt_rest_api_type( $post_types ) {
|
||||
$post_types[] = self::CUSTOM_POST_TYPE;
|
||||
|
||||
return $post_types;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bump Testimonial > New Activation stat
|
||||
*/
|
||||
public function new_activation_stat_bump() {
|
||||
/** This action is documented in modules/widgets/social-media-icons.php */
|
||||
do_action( 'jetpack_bump_stats_extras', 'testimonials', 'new-activation' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Bump Testimonial > Option On/Off stats to get total active
|
||||
*
|
||||
* @param mixed $old The old option value.
|
||||
* @param mixed $new The new option value.
|
||||
*/
|
||||
public function update_option_stat_bump( $old, $new ) {
|
||||
if ( empty( $old ) && ! empty( $new ) ) {
|
||||
/** This action is documented in modules/widgets/social-media-icons.php */
|
||||
do_action( 'jetpack_bump_stats_extras', 'testimonials', 'option-on' );
|
||||
}
|
||||
|
||||
if ( ! empty( $old ) && empty( $new ) ) {
|
||||
/** This action is documented in modules/widgets/social-media-icons.php */
|
||||
do_action( 'jetpack_bump_stats_extras', 'testimonials', 'option-off' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bump Testimonial > Published Testimonials stat when testimonials are published
|
||||
*/
|
||||
public function new_testimonial_stat_bump() {
|
||||
/** This action is documented in modules/widgets/social-media-icons.php */
|
||||
do_action( 'jetpack_bump_stats_extras', 'testimonials', 'published-testimonials' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush permalinks when CPT option is turned on/off
|
||||
*/
|
||||
public function flush_rules_on_enable() {
|
||||
flush_rewrite_rules();
|
||||
}
|
||||
|
||||
/**
|
||||
* Count published testimonials and flush permalinks when first testimonial is published
|
||||
*/
|
||||
public function flush_rules_on_first_testimonial() {
|
||||
$testimonials = get_transient( 'jetpack-testimonial-count-cache' );
|
||||
|
||||
if ( false === $testimonials ) {
|
||||
flush_rewrite_rules();
|
||||
$testimonials = (int) wp_count_posts( self::CUSTOM_POST_TYPE )->publish;
|
||||
|
||||
if ( ! empty( $testimonials ) ) {
|
||||
set_transient( 'jetpack-testimonial-count-cache', $testimonials, HOUR_IN_SECONDS * 12 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush permalinks when CPT supported theme is activated
|
||||
*/
|
||||
public function flush_rules_on_switch() {
|
||||
if ( current_theme_supports( self::CUSTOM_POST_TYPE ) ) {
|
||||
flush_rewrite_rules();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* On plugin/theme activation, check if current theme supports CPT
|
||||
*/
|
||||
public static function activation_post_type_support() {
|
||||
if ( current_theme_supports( self::CUSTOM_POST_TYPE ) ) {
|
||||
update_option( self::OPTION_NAME, '1' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* On theme switch, check if CPT item exists and disable if not
|
||||
*/
|
||||
public function deactivation_post_type_support() {
|
||||
$portfolios = get_posts(
|
||||
array(
|
||||
'fields' => 'ids',
|
||||
'posts_per_page' => 1,
|
||||
'post_type' => self::CUSTOM_POST_TYPE,
|
||||
'suppress_filters' => false,
|
||||
)
|
||||
);
|
||||
|
||||
if ( empty( $portfolios ) ) {
|
||||
update_option( self::OPTION_NAME, '0' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register Post Type
|
||||
*/
|
||||
public function register_post_types() {
|
||||
if ( post_type_exists( self::CUSTOM_POST_TYPE ) ) {
|
||||
return;
|
||||
}
|
||||
if ( ! self::site_should_display_testimonials() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
register_post_type(
|
||||
self::CUSTOM_POST_TYPE,
|
||||
array(
|
||||
'description' => __( 'Customer Testimonials', 'jetpack-classic-theme-helper' ),
|
||||
'labels' => array(
|
||||
'name' => esc_html__( 'Testimonials', 'jetpack-classic-theme-helper' ),
|
||||
'singular_name' => esc_html__( 'Testimonial', 'jetpack-classic-theme-helper' ),
|
||||
'menu_name' => esc_html__( 'Testimonials', 'jetpack-classic-theme-helper' ),
|
||||
'all_items' => esc_html__( 'All Testimonials', 'jetpack-classic-theme-helper' ),
|
||||
'add_new' => esc_html__( 'Add New', 'jetpack-classic-theme-helper' ),
|
||||
'add_new_item' => esc_html__( 'Add New Testimonial', 'jetpack-classic-theme-helper' ),
|
||||
'edit_item' => esc_html__( 'Edit Testimonial', 'jetpack-classic-theme-helper' ),
|
||||
'new_item' => esc_html__( 'New Testimonial', 'jetpack-classic-theme-helper' ),
|
||||
'view_item' => esc_html__( 'View Testimonial', 'jetpack-classic-theme-helper' ),
|
||||
'search_items' => esc_html__( 'Search Testimonials', 'jetpack-classic-theme-helper' ),
|
||||
'not_found' => esc_html__( 'No Testimonials found', 'jetpack-classic-theme-helper' ),
|
||||
'not_found_in_trash' => esc_html__( 'No Testimonials found in Trash', 'jetpack-classic-theme-helper' ),
|
||||
'filter_items_list' => esc_html__( 'Filter Testimonials list', 'jetpack-classic-theme-helper' ),
|
||||
'items_list_navigation' => esc_html__( 'Testimonial list navigation', 'jetpack-classic-theme-helper' ),
|
||||
'items_list' => esc_html__( 'Testimonials list', 'jetpack-classic-theme-helper' ),
|
||||
),
|
||||
'supports' => array(
|
||||
'title',
|
||||
'editor',
|
||||
'thumbnail',
|
||||
'page-attributes',
|
||||
'revisions',
|
||||
'excerpt',
|
||||
'newspack_blocks',
|
||||
),
|
||||
'rewrite' => array(
|
||||
'slug' => 'testimonial',
|
||||
'with_front' => false,
|
||||
'feeds' => false,
|
||||
'pages' => true,
|
||||
),
|
||||
'public' => true,
|
||||
'show_ui' => true,
|
||||
'menu_position' => 20, // below Pages
|
||||
'menu_icon' => 'dashicons-testimonial',
|
||||
'capability_type' => 'page',
|
||||
'map_meta_cap' => true,
|
||||
'has_archive' => true,
|
||||
'query_var' => 'testimonial',
|
||||
'show_in_rest' => true,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update messages for the Testimonial admin.
|
||||
*
|
||||
* @param array $messages Existing post update messages.
|
||||
* @return array Updated `$messages`.
|
||||
*/
|
||||
public function updated_messages( $messages ) {
|
||||
global $post;
|
||||
|
||||
$messages[ self::CUSTOM_POST_TYPE ] = array(
|
||||
0 => '', // Unused. Messages start at index 1.
|
||||
1 => sprintf(
|
||||
/* Translators: link to Testimonial item's page. */
|
||||
__( 'Testimonial updated. <a href="%s">View testimonial</a>', 'jetpack-classic-theme-helper' ),
|
||||
esc_url( get_permalink( $post->ID ) )
|
||||
),
|
||||
2 => esc_html__( 'Custom field updated.', 'jetpack-classic-theme-helper' ),
|
||||
3 => esc_html__( 'Custom field deleted.', 'jetpack-classic-theme-helper' ),
|
||||
4 => esc_html__( 'Testimonial updated.', 'jetpack-classic-theme-helper' ),
|
||||
5 => isset( $_GET['revision'] ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Copying core message handling.
|
||||
? sprintf(
|
||||
/* translators: %s: date and time of the revision */
|
||||
esc_html__( 'Testimonial restored to revision from %s', 'jetpack-classic-theme-helper' ),
|
||||
wp_post_revision_title( (int) $_GET['revision'], false ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Copying core message handling.
|
||||
)
|
||||
: false,
|
||||
6 => sprintf(
|
||||
/* Translators: link to Testimonial item's page. */
|
||||
__( 'Testimonial published. <a href="%s">View testimonial</a>', 'jetpack-classic-theme-helper' ),
|
||||
esc_url( get_permalink( $post->ID ) )
|
||||
),
|
||||
7 => esc_html__( 'Testimonial saved.', 'jetpack-classic-theme-helper' ),
|
||||
8 => sprintf(
|
||||
/* Translators: link to Testimonial item's page. */
|
||||
__( 'Testimonial submitted. <a target="_blank" href="%s">Preview testimonial</a>', 'jetpack-classic-theme-helper' ),
|
||||
esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) )
|
||||
),
|
||||
9 => sprintf(
|
||||
/* Translators: 1: Publishing date and time. 2. Link to testimonial's item page. */
|
||||
__( 'Testimonial scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview testimonial</a>', 'jetpack-classic-theme-helper' ),
|
||||
// translators: Publish box date format, see https://php.net/date
|
||||
date_i18n( __( 'M j, Y @ G:i', 'jetpack-classic-theme-helper' ), strtotime( $post->post_date ) ),
|
||||
esc_url( get_permalink( $post->ID ) )
|
||||
),
|
||||
10 => sprintf(
|
||||
/* Translators: link to Testimonial item's page. */
|
||||
__( 'Testimonial draft updated. <a target="_blank" href="%s">Preview testimonial</a>', 'jetpack-classic-theme-helper' ),
|
||||
esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) )
|
||||
),
|
||||
);
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change ‘Enter Title Here’ text for the Testimonial.
|
||||
*
|
||||
* @param string $title Placeholder text. Default 'Add title'.
|
||||
* @return string Replacement title.
|
||||
*/
|
||||
public function change_default_title( $title ) {
|
||||
if ( self::CUSTOM_POST_TYPE === get_post_type() ) {
|
||||
$title = esc_html__( "Enter the customer's name here", 'jetpack-classic-theme-helper' );
|
||||
}
|
||||
|
||||
return $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change ‘Title’ column label on all Testimonials page.
|
||||
*
|
||||
* @param array $columns An array of column names.
|
||||
* @return array Updated array.
|
||||
*/
|
||||
public function edit_title_column_label( $columns ) {
|
||||
$columns['title'] = esc_html__( 'Customer Name', 'jetpack-classic-theme-helper' );
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Follow CPT reading setting on CPT archive page
|
||||
*
|
||||
* @param WP_Query $query A WP_Query instance.
|
||||
*/
|
||||
public function query_reading_setting( $query ) {
|
||||
if ( ! is_admin()
|
||||
&& $query->is_main_query()
|
||||
&& $query->is_post_type_archive( self::CUSTOM_POST_TYPE )
|
||||
) {
|
||||
$query->set( 'posts_per_page', get_option( self::OPTION_READING_SETTING, '10' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If Infinite Scroll is set to 'click', use our custom reading setting instead of core's `posts_per_page`.
|
||||
*
|
||||
* @param array $settings Array of Infinite Scroll settings.
|
||||
* @return array Updated `$settings`.
|
||||
*/
|
||||
public function infinite_scroll_click_posts_per_page( $settings ) {
|
||||
global $wp_query;
|
||||
|
||||
if ( ! is_admin() && true === $settings['click_handle'] && $wp_query->is_post_type_archive( self::CUSTOM_POST_TYPE ) ) {
|
||||
$settings['posts_per_page'] = get_option( self::OPTION_READING_SETTING, $settings['posts_per_page'] );
|
||||
}
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add CPT to Dotcom sitemap
|
||||
*
|
||||
* @param array $post_types Array of post types included in sitemap.
|
||||
* @return array Updated `$post_types`.
|
||||
*/
|
||||
public function add_to_sitemap( $post_types ) {
|
||||
$post_types[] = self::CUSTOM_POST_TYPE;
|
||||
|
||||
return $post_types;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the number of published testimonials.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function count_testimonials() {
|
||||
$testimonials = get_transient( 'jetpack-testimonial-count-cache' );
|
||||
|
||||
if ( false === $testimonials ) {
|
||||
$testimonials = (int) ( wp_count_posts( self::CUSTOM_POST_TYPE )->publish ?? 0 );
|
||||
|
||||
if ( ! empty( $testimonials ) ) {
|
||||
set_transient( 'jetpack-testimonial-count-cache', $testimonials, 60 * 60 * 12 );
|
||||
}
|
||||
}
|
||||
|
||||
return $testimonials;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a submenu link to the Customizer.
|
||||
*/
|
||||
public function add_customize_page() {
|
||||
if ( ! empty( self::count_testimonials() ) ) {
|
||||
return;
|
||||
}
|
||||
add_submenu_page(
|
||||
'edit.php?post_type=' . self::CUSTOM_POST_TYPE,
|
||||
esc_html__( 'Customize Testimonials Archive', 'jetpack-classic-theme-helper' ),
|
||||
esc_html__( 'Customize', 'jetpack-classic-theme-helper' ),
|
||||
'edit_theme_options',
|
||||
add_query_arg(
|
||||
array(
|
||||
'url' => rawurlencode( home_url( '/testimonial/' ) ),
|
||||
'autofocus[section]' => 'jetpack_testimonials',
|
||||
),
|
||||
'customize.php'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds testimonial section to the Customizer.
|
||||
*
|
||||
* @param WP_Customize_Manager $wp_customize Customizer instance.
|
||||
*/
|
||||
public function customize_register( $wp_customize ) {
|
||||
|
||||
require_once __DIR__ . '/class-jetpack-testimonial-textarea-control.php';
|
||||
require_once __DIR__ . '/class-jetpack-testimonial-title-control.php';
|
||||
|
||||
$wp_customize->add_section(
|
||||
'jetpack_testimonials',
|
||||
array(
|
||||
'title' => esc_html__( 'Testimonials', 'jetpack-classic-theme-helper' ),
|
||||
'theme_supports' => self::CUSTOM_POST_TYPE,
|
||||
'priority' => 130,
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_setting(
|
||||
'jetpack_testimonials[page-title]',
|
||||
array(
|
||||
'default' => esc_html__( 'Testimonials', 'jetpack-classic-theme-helper' ),
|
||||
'sanitize_callback' => array( Jetpack_Testimonial_Title_Control::class, 'sanitize_content' ),
|
||||
'sanitize_js_callback' => array( Jetpack_Testimonial_Title_Control::class, 'sanitize_content' ),
|
||||
)
|
||||
);
|
||||
$wp_customize->add_control(
|
||||
'jetpack_testimonials[page-title]',
|
||||
array(
|
||||
'section' => 'jetpack_testimonials',
|
||||
'label' => esc_html__( 'Testimonial Archive Title', 'jetpack-classic-theme-helper' ),
|
||||
'type' => 'text',
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_setting(
|
||||
'jetpack_testimonials[page-content]',
|
||||
array(
|
||||
'default' => '',
|
||||
'sanitize_callback' => array( Jetpack_Testimonial_Textarea_Control::class, 'sanitize_content' ),
|
||||
'sanitize_js_callback' => array( Jetpack_Testimonial_Textarea_Control::class, 'sanitize_content' ),
|
||||
)
|
||||
);
|
||||
$wp_customize->add_control(
|
||||
new Jetpack_Testimonial_Textarea_Control(
|
||||
$wp_customize,
|
||||
'jetpack_testimonials[page-content]',
|
||||
array(
|
||||
'section' => 'jetpack_testimonials',
|
||||
'settings' => 'jetpack_testimonials[page-content]',
|
||||
'label' => esc_html__( 'Testimonial Archive Content', 'jetpack-classic-theme-helper' ),
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$wp_customize->add_setting(
|
||||
'jetpack_testimonials[featured-image]',
|
||||
array(
|
||||
'default' => '',
|
||||
'sanitize_callback' => 'attachment_url_to_postid',
|
||||
'sanitize_js_callback' => 'attachment_url_to_postid',
|
||||
'theme_supports' => 'post-thumbnails',
|
||||
)
|
||||
);
|
||||
$wp_customize->add_control(
|
||||
new WP_Customize_Image_Control(
|
||||
$wp_customize,
|
||||
'jetpack_testimonials[featured-image]',
|
||||
array(
|
||||
'section' => 'jetpack_testimonials',
|
||||
'label' => esc_html__( 'Testimonial Archive Featured Image', 'jetpack-classic-theme-helper' ),
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// The featured image control doesn't display properly in the Customizer unless we coerce
|
||||
// it back into a URL sooner, since that's what WP_Customize_Upload_Control::to_json() expects
|
||||
if ( is_admin() ) {
|
||||
add_filter( 'theme_mod_jetpack_testimonials', array( $this, 'coerce_testimonial_image_to_url' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Featured image to theme mod if necessary.
|
||||
*
|
||||
* @param array $opt The value of the current theme modification.
|
||||
* @return array Updated `$opt`.
|
||||
*/
|
||||
public function coerce_testimonial_image_to_url( $opt ) {
|
||||
if ( ! $opt || ! is_array( $opt ) ) {
|
||||
return $opt;
|
||||
}
|
||||
if ( ! isset( $opt['featured-image'] ) || ! is_scalar( $opt['featured-image'] ) ) {
|
||||
return $opt;
|
||||
}
|
||||
$url = wp_get_attachment_url( $opt['featured-image'] );
|
||||
if ( $url ) {
|
||||
$opt['featured-image'] = $url;
|
||||
}
|
||||
return $opt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Our [testimonial] shortcode.
|
||||
* Prints Testimonial data styled to look good on *any* theme.
|
||||
*
|
||||
* @param array $atts Shortcode attributes.
|
||||
*
|
||||
* @return string HTML from `self::jetpack_testimonial_shortcode_html()`.
|
||||
*/
|
||||
public static function jetpack_testimonial_shortcode( $atts ) {
|
||||
// Default attributes.
|
||||
$atts = shortcode_atts(
|
||||
array(
|
||||
'display_content' => true, // Can be false, true, or full.
|
||||
'image' => true,
|
||||
'columns' => 1,
|
||||
'showposts' => -1,
|
||||
'order' => 'asc',
|
||||
'orderby' => 'menu_order,date',
|
||||
),
|
||||
$atts,
|
||||
'testimonial'
|
||||
);
|
||||
|
||||
// A little sanitization.
|
||||
if (
|
||||
$atts['display_content']
|
||||
&& 'true' != $atts['display_content'] // phpcs:ignore Universal.Operators.StrictComparisons.LooseNotEqual
|
||||
&& 'full' !== $atts['display_content']
|
||||
) {
|
||||
$atts['display_content'] = false;
|
||||
}
|
||||
|
||||
if ( $atts['image'] && 'true' != $atts['image'] ) { // phpcs:ignore Universal.Operators.StrictComparisons.LooseNotEqual
|
||||
$atts['image'] = false;
|
||||
}
|
||||
|
||||
$atts['columns'] = absint( $atts['columns'] );
|
||||
|
||||
$atts['showposts'] = (int) $atts['showposts'];
|
||||
|
||||
if ( $atts['order'] ) {
|
||||
$atts['order'] = urldecode( $atts['order'] );
|
||||
$atts['order'] = strtoupper( $atts['order'] );
|
||||
if ( 'DESC' !== $atts['order'] ) {
|
||||
$atts['order'] = 'ASC';
|
||||
}
|
||||
}
|
||||
|
||||
if ( $atts['orderby'] ) {
|
||||
$atts['orderby'] = urldecode( $atts['orderby'] );
|
||||
$atts['orderby'] = strtolower( $atts['orderby'] );
|
||||
$allowed_keys = array( 'author', 'date', 'title', 'menu_order', 'rand' );
|
||||
|
||||
$parsed = array();
|
||||
foreach ( explode( ',', $atts['orderby'] ) as $orderby ) {
|
||||
if ( ! in_array( $orderby, $allowed_keys, true ) ) {
|
||||
continue;
|
||||
}
|
||||
$parsed[] = $orderby;
|
||||
}
|
||||
|
||||
if ( empty( $parsed ) ) {
|
||||
unset( $atts['orderby'] );
|
||||
} else {
|
||||
$atts['orderby'] = implode( ' ', $parsed );
|
||||
}
|
||||
}
|
||||
|
||||
// enqueue shortcode styles when shortcode is used
|
||||
if ( ! wp_style_is( 'jetpack-testimonial-style', 'enqueued' ) ) {
|
||||
wp_enqueue_style( 'jetpack-testimonial-style', plugins_url( 'css/testimonial-shortcode.css', __FILE__ ), array(), '20140326' );
|
||||
}
|
||||
|
||||
return self::jetpack_testimonial_shortcode_html( $atts );
|
||||
}
|
||||
|
||||
/**
|
||||
* The Testimonial shortcode loop.
|
||||
*
|
||||
* @param array $atts Shortcode attributes.
|
||||
*
|
||||
* @return string html
|
||||
*/
|
||||
private static function jetpack_testimonial_shortcode_html( $atts ) {
|
||||
// Default query arguments
|
||||
$defaults = array(
|
||||
'order' => $atts['order'],
|
||||
'posts_per_page' => $atts['showposts'],
|
||||
);
|
||||
|
||||
if ( ! empty( $atts['orderby'] ) ) {
|
||||
$defaults['orderby'] = $atts['orderby'];
|
||||
}
|
||||
|
||||
$args = wp_parse_args( $atts, $defaults );
|
||||
$args['post_type'] = self::CUSTOM_POST_TYPE; // Force this post type
|
||||
$query = new WP_Query( $args );
|
||||
|
||||
$testimonial_index_number = 0;
|
||||
|
||||
ob_start();
|
||||
|
||||
// If we have testimonials, create the html
|
||||
if ( $query->have_posts() ) {
|
||||
|
||||
?>
|
||||
<div class="jetpack-testimonial-shortcode column-<?php echo esc_attr( $atts['columns'] ); ?>">
|
||||
<?php
|
||||
// Construct the loop...
|
||||
while ( $query->have_posts() ) {
|
||||
$query->the_post();
|
||||
$post_id = get_the_ID();
|
||||
?>
|
||||
<div class="testimonial-entry <?php echo esc_attr( self::get_testimonial_class( $testimonial_index_number, $atts['columns'], has_post_thumbnail( $post_id ) ) ); ?>">
|
||||
<?php
|
||||
// The content
|
||||
if ( false !== $atts['display_content'] ) {
|
||||
if ( 'full' === $atts['display_content'] ) {
|
||||
?>
|
||||
<div class="testimonial-entry-content"><?php the_content(); ?></div>
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
<div class="testimonial-entry-content"><?php the_excerpt(); ?></div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
?>
|
||||
<span class="testimonial-entry-title">― <a href="<?php echo esc_url( get_permalink() ); ?>" title="<?php echo esc_attr( the_title_attribute() ); ?>"><?php the_title(); ?></a></span>
|
||||
<?php
|
||||
// Featured image
|
||||
if ( false !== $atts['image'] ) :
|
||||
echo self::get_testimonial_thumbnail_link( $post_id ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped in method.
|
||||
endif;
|
||||
?>
|
||||
</div><!-- close .testimonial-entry -->
|
||||
<?php
|
||||
++$testimonial_index_number;
|
||||
} // end of while loop
|
||||
|
||||
wp_reset_postdata();
|
||||
?>
|
||||
</div><!-- close .jetpack-testimonial-shortcode -->
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
<p><em><?php esc_html_e( 'Your Testimonial Archive currently has no entries. You can start creating them on your dashboard.', 'jetpack-classic-theme-helper' ); ?></p></em>
|
||||
<?php
|
||||
}
|
||||
$html = ob_get_clean();
|
||||
|
||||
// Return the HTML block
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Individual testimonial class
|
||||
*
|
||||
* @param int $testimonial_index_number iterator count the number of columns up starting from 0.
|
||||
* @param int $columns number of columns to display the content in.
|
||||
* @param bool $image has a thumbnail or not.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function get_testimonial_class( $testimonial_index_number, $columns, $image ) {
|
||||
$class = array();
|
||||
|
||||
$class[] = 'testimonial-entry-column-' . $columns;
|
||||
|
||||
if ( $columns > 1 ) {
|
||||
if ( ( $testimonial_index_number % 2 ) === 0 ) {
|
||||
$class[] = 'testimonial-entry-mobile-first-item-row';
|
||||
} else {
|
||||
$class[] = 'testimonial-entry-mobile-last-item-row';
|
||||
}
|
||||
}
|
||||
|
||||
// Add a guard clause to prevent division by zero below.
|
||||
if ( $columns <= 0 ) {
|
||||
$columns = 1;
|
||||
}
|
||||
|
||||
// add first and last classes to first and last items in a row
|
||||
if ( ( $testimonial_index_number % $columns ) === 0 ) {
|
||||
$class[] = 'testimonial-entry-first-item-row';
|
||||
} elseif ( ( $testimonial_index_number % $columns ) === ( $columns - 1 ) ) {
|
||||
$class[] = 'testimonial-entry-last-item-row';
|
||||
}
|
||||
|
||||
// add class if testimonial has a featured image
|
||||
if ( false !== $image ) {
|
||||
$class[] = 'has-testimonial-thumbnail';
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the class applied to testimonial div in the testimonial
|
||||
*
|
||||
* @module custom-content-types
|
||||
*
|
||||
* @since 3.4.0
|
||||
*
|
||||
* @param string $class class name of the div.
|
||||
* @param int $testimonial_index_number iterator count the number of columns up starting from 0.
|
||||
* @param int $columns number of columns to display the content in.
|
||||
* @param boolean $image has a thumbnail or not.
|
||||
*/
|
||||
return apply_filters( 'testimonial-entry-post-class', implode( ' ', $class ), $testimonial_index_number, $columns, $image ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the featured image if it's available
|
||||
*
|
||||
* @param int $post_id Post ID.
|
||||
*
|
||||
* @return string html
|
||||
*/
|
||||
private static function get_testimonial_thumbnail_link( $post_id ) {
|
||||
if ( has_post_thumbnail( $post_id ) ) {
|
||||
/**
|
||||
* Change the thumbnail size for the Testimonial CPT.
|
||||
*
|
||||
* @module custom-content-types
|
||||
*
|
||||
* @since 3.4.0
|
||||
*
|
||||
* @param string|array $var Either a registered size keyword or size array.
|
||||
*/
|
||||
return '<a class="testimonial-featured-image" href="' . esc_url( get_permalink( $post_id ) ) . '">' . get_the_post_thumbnail( $post_id, apply_filters( 'jetpack_testimonial_thumbnail_size', 'thumbnail' ) ) . '</a>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+1760
File diff suppressed because it is too large
Load Diff
+32
@@ -0,0 +1,32 @@
|
||||
.widefat .menu-label-row td {
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
|
||||
.widefat .menu-label-row td h3 {
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
.widefat .menu-order-value {
|
||||
width: 2.5em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.widefat .menu-label-row,
|
||||
.widefat .menu-label-row td {
|
||||
background-color: #d6d6d6;
|
||||
color: #111;
|
||||
border: 0 none;
|
||||
}
|
||||
|
||||
.ui-sortable .type-nova_menu_item {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.tablenav .button-reorder {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.tablenav .view-switch a,
|
||||
.tablenav div.tablenav-pages {
|
||||
display: none;
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
.many-items-table th,
|
||||
.many-items-table td {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.many-items-table input,
|
||||
.many-items-table textarea {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.many-items-table input[type="file"] {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
@font-face {
|
||||
font-family: nova-font;
|
||||
src: url(../fonts/nova.eot);
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: nova-font;
|
||||
src:
|
||||
url(data:font/ttf;base64,AAEAAAALAIAAAwAwT1MvMg5lAuAAAAC8AAAAYGNtYXDL9xqaAAABHAAAADxnYXNwAAAAEAAAAVgAAAAIZ2x5Zrlfj0YAAAFgAAABrGhlYWQAW+atAAADDAAAADZoaGVhB2ED4AAAA0QAAAAkaG10eAXcAGQAAANoAAAADGxvY2EACgDWAAADdAAAAAhtYXhwAAgAkQAAA3wAAAAgbmFtZXvEneAAAAOcAAABHnBvc3QAAwAAAAAEvAAAACAAAwPoAZAABQAAAooCvAAAAIwCigK8AAAB4AAxAQIAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAACDmAwOp/8L/wgOpAD4AAAAAAAAAAAAAAAAAAAAgAAAAAAACAAAAAwAAABQAAwABAAAAFAAEACgAAAAGAAQAAQACACDmA///AAAAIOYD////4Rn/AAEAAAAAAAAAAQAB//8ADwABAAAAAAAAAAAAAgAANzkBAAAAAAQAZAAyA7YDhAAoAEUAfQCOAAABMhY6ATMyPgI/ASMHJz8BDwEnNycHDgMHFgYWBhcHMgYWIjMXNwUHDgMHHgMXHgMzMj4CPwEnKgMjFyc3Ni4CJy4DIyIOAgcOAxceAxceAz8BAR4DMzI+Ajc+Ayc2LgIvAQEmPgI3PgEeARceAxcnApQCBAQEAg4XFxQKtzGXH2oaM3UhlwHUCg0KBAEBAQIBAhQBAQEBAXIN/t3oCwwLAwEBAwsMCwgVFhkMDhgXEwuxcgICAwEC94wFBQMUIRkRLS0xFQsVFxULCQ8GAgQDDxMaDxUuNDIaDgEwBhAQFQkMExIQCAcMBgUBAQUGDAfm/i8CAwIHAhApLy0VCRMMCwLrAfUBBAoNCtWWIHYyGWsglDS5CRQWGQ0CBAQEAw8BAWkOKsIJFBYZDQ0YFxQJCg0KBAQKDQrWngp+DxczNTUXEx4VDAMHDAoKGh4iExMnJSMPFB4SBQQD/l8HCgYEBAcLCAcQEhQKCxMSEAjPAV8BBgcHBA4KCRgTCxgWFQlaAAAAAAEAAAABAAAD2anvXw889QALA+gAAAAAzsPRIgAAAADOw9EiAAAAAAO2A4QAAAAIAAIAAAAAAAAAAQAAA6n/wgAAA+gAAAAyA7YAAQAAAAAAAAAAAAAAAAAAAAMAAAAAAfQAAAPoAGQAAAAAAAoA1gABAAAAAwCPAAQAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAADgCuAAEAAAAAAAEACAAAAAEAAAAAAAIADgAyAAEAAAAAAAMACAAeAAEAAAAAAAQACABAAAEAAAAAAAUAFgAIAAEAAAAAAAYABAAmAAEAAAAAAAoAKABIAAMAAQQJAAEACAAAAAMAAQQJAAIADgAyAAMAAQQJAAMACAAeAAMAAQQJAAQACABAAAMAAQQJAAUAFgAIAAMAAQQJAAYACAAqAAMAAQQJAAoAKABIAG4AbwB2AGEAVgBlAHIAcwBpAG8AbgAgADAALgAwAG4AbwB2AGFub3ZhAG4AbwB2AGEAUgBlAGcAdQBsAGEAcgBuAG8AdgBhAEcAZQBuAGUAcgBhAHQAZQBkACAAYgB5ACAASQBjAG8ATQBvAG8AbgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=) format("truetype"),
|
||||
url(data:font/woff;base64,d09GRgABAAAAAAUoAAsAAAAABNwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABPUy8yAAABCAAAAGAAAABgDmUC4GNtYXAAAAFoAAAAPAAAADzL9xqaZ2FzcAAAAaQAAAAIAAAACAAAABBnbHlmAAABrAAAAawAAAGsuV+PRmhlYWQAAANYAAAANgAAADYAW+ataGhlYQAAA5AAAAAkAAAAJAdhA+BobXR4AAADtAAAAAwAAAAMBdwAZGxvY2EAAAPAAAAACAAAAAgACgDWbWF4cAAAA8gAAAAgAAAAIAAIAJFuYW1lAAAD6AAAAR4AAAEee8Sd4HBvc3QAAAUIAAAAIAAAACAAAwAAAAMD6AGQAAUAAAKKArwAAACMAooCvAAAAeAAMQECAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAg5gMDqf/C/8IDqQA+AAAAAAAAAAAAAAAAAAAAIAAAAAAAAgAAAAMAAAAUAAMAAQAAABQABAAoAAAABgAEAAEAAgAg5gP//wAAACDmA////+EZ/wABAAAAAAAAAAEAAf//AA8AAQAAAAAAAAAAAAIAADc5AQAAAAAEAGQAMgO2A4QAKABFAH0AjgAAATIWOgEzMj4CPwEjByc/AQ8BJzcnBw4DBxYGFgYXBzIGFiIzFzcFBw4DBx4DFx4DMzI+Aj8BJyoDIxcnNzYuAicuAyMiDgIHDgMXHgMXHgM/AQEeAzMyPgI3PgMnNi4CLwEBJj4CNz4BHgEXHgMXJwKUAgQEBAIOFxcUCrcxlx9qGjN1IZcB1AoNCgQBAQECAQIUAQEBAQFyDf7d6AsMCwMBAQMLDAsIFRYZDA4YFxMLsXICAgMBAveMBQUDFCEZES0tMRULFRcVCwkPBgIEAw8TGg8VLjQyGg4BMAYQEBUJDBMSEAgHDAYFAQEFBgwH5v4vAgMCBwIQKS8tFQkTDAsC6wH1AQQKDQrVliB2MhlrIJQ0uQkUFhkNAgQEBAMPAQFpDirCCRQWGQ0NGBcUCQoNCgQECg0K1p4Kfg8XMzU1FxMeFQwDBwwKChoeIhMTJyUjDxQeEgUEA/5fBwoGBAQHCwgHEBIUCgsTEhAIzwFfAQYHBwQOCgkYEwsYFhUJWgAAAAABAAAAAQAAA9mp718PPPUACwPoAAAAAM7D0SIAAAAAzsPRIgAAAAADtgOEAAAACAACAAAAAAAAAAEAAAOp/8IAAAPoAAAAMgO2AAEAAAAAAAAAAAAAAAAAAAADAAAAAAH0AAAD6ABkAAAAAAAKANYAAQAAAAMAjwAEAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAA4ArgABAAAAAAABAAgAAAABAAAAAAACAA4AMgABAAAAAAADAAgAHgABAAAAAAAEAAgAQAABAAAAAAAFABYACAABAAAAAAAGAAQAJgABAAAAAAAKACgASAADAAEECQABAAgAAAADAAEECQACAA4AMgADAAEECQADAAgAHgADAAEECQAEAAgAQAADAAEECQAFABYACAADAAEECQAGAAgAKgADAAEECQAKACgASABuAG8AdgBhAFYAZQByAHMAaQBvAG4AIAAwAC4AMABuAG8AdgBhbm92YQBuAG8AdgBhAFIAZQBnAHUAbABhAHIAbgBvAHYAYQBHAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAEkAYwBvAE0AbwBvAG4AAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) format("woff");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
#menu-posts-nova_menu_item::before,
|
||||
#dashboard_right_now .nova-menu-count a::before,
|
||||
#dashboard_right_now .nova-menu-count span::before {
|
||||
/* stylelint-disable-next-line font-family-no-missing-generic-family-keyword -- this is a one-off icon font. */
|
||||
font-family: nova-font;
|
||||
speak: none;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
line-height: 1;
|
||||
|
||||
/* Better Font Rendering =========== */
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
#dashboard_right_now .nova-menu-count a::before,
|
||||
#dashboard_right_now .nova-menu-count span::before {
|
||||
content: "\e603";
|
||||
}
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
/* edit-items.css
|
||||
-------------------------------------------------------------- */
|
||||
|
||||
.widefat .menu-label-row td {
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
|
||||
.widefat .menu-label-row td h3 {
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
.widefat .menu-label-row td h3 .edit-nova-section {
|
||||
font-size: 0.8em;
|
||||
font-weight: 400;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.widefat .menu-order-value {
|
||||
width: 2.5em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.widefat .menu-label-row,
|
||||
.widefat .menu-label-row td {
|
||||
background-color: #f0f0f1;
|
||||
color: #111;
|
||||
border: 0 none;
|
||||
box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.ui-sortable .type-nova_menu_item {
|
||||
cursor: move;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.ui-sortable .type-nova_menu_item:nth-child(even) {
|
||||
background-color: #f6f7f7;
|
||||
}
|
||||
|
||||
.ui-sortable .type-nova_menu_item.ui-sortable-helper {
|
||||
box-shadow: 0 0 1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.tablenav .button-reorder {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.tablenav .view-switch a,
|
||||
.tablenav div.tablenav-pages {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/* many-items.css
|
||||
-------------------------------------------------------------- */
|
||||
|
||||
.many-items-table th,
|
||||
.many-items-table td {
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
.many-items-table th.nova-price,
|
||||
.many-items-table td.nova-price {
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
.many-items-table input,
|
||||
.many-items-table textarea {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.many-items-table input[type="file"] {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
|
||||
/* new
|
||||
-------------------------------------------------------------- */
|
||||
|
||||
#the-list tr td:nth-of-type(2) {
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
||||
.nova-move-menu-up::before,
|
||||
.nova-move-menu-down::before {
|
||||
margin-right: 5px;
|
||||
font: 400 10px/1 dashicons !important;
|
||||
speak: none;
|
||||
}
|
||||
|
||||
.nova-move-menu-up::before {
|
||||
content: "\f342";
|
||||
}
|
||||
|
||||
.nova-move-menu-down::before {
|
||||
content: "\f346";
|
||||
}
|
||||
|
||||
.dashicon::before {
|
||||
font: 400 20px/1 dashicons;
|
||||
speak: none;
|
||||
top: 5px;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-decoration: none !important;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.dashicon-plus::before {
|
||||
content: "\f132";
|
||||
}
|
||||
|
||||
.dashicon-edit::before {
|
||||
margin: 2px 5px 0 10px;
|
||||
content: "\f327";
|
||||
font-size: 10px;
|
||||
}
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
.jetpack-portfolio-shortcode {
|
||||
clear: both;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.portfolio-entry {
|
||||
float: left;
|
||||
margin: 0 0 3em;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Column setting */
|
||||
.portfolio-entry-column-1 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.portfolio-entry-column-2 {
|
||||
margin-right: 4%;
|
||||
width: 48%;
|
||||
}
|
||||
|
||||
.portfolio-entry-column-3 {
|
||||
margin-right: 3.5%;
|
||||
width: 31%;
|
||||
}
|
||||
|
||||
.portfolio-entry-column-4 {
|
||||
margin-right: 3%;
|
||||
width: 22%;
|
||||
}
|
||||
|
||||
.portfolio-entry-column-5 {
|
||||
margin-right: 2.5%;
|
||||
width: 18%;
|
||||
}
|
||||
|
||||
.portfolio-entry-column-6 {
|
||||
margin-right: 2%;
|
||||
width: 15%;
|
||||
}
|
||||
|
||||
.portfolio-entry-first-item-row {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.portfolio-entry-last-item-row {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
|
||||
.portfolio-entry-mobile-first-item-row {
|
||||
margin-right: 4%;
|
||||
width: 48%;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.portfolio-entry-first-item-row {
|
||||
clear: none;
|
||||
}
|
||||
|
||||
.portfolio-entry-mobile-last-item-row {
|
||||
width: 48%;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Entry Header */
|
||||
.portfolio-entry-header {
|
||||
border: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.portfolio-featured-image {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.portfolio-featured-image img {
|
||||
border: 0;
|
||||
height: auto;
|
||||
max-width: 100%;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.portfolio-entry-title {
|
||||
font-weight: 700;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.portfolio-featured-image + .portfolio-entry-title {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.portfolio-entry-title a {
|
||||
border: 0;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Entry Meta */
|
||||
.portfolio-entry-meta {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.portfolio-entry-title + .portfolio-entry-meta {
|
||||
margin-top: 0.75em;
|
||||
}
|
||||
|
||||
.portfolio-entry-title + .portfolio-entry-meta:empty {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.portfolio-entry-meta span,
|
||||
.portfolio-entry-meta a {
|
||||
font-size: 0.9em;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.portfolio-entry-meta a {
|
||||
border: 0;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Entry Content */
|
||||
.portfolio-entry-content {
|
||||
margin: 0.75em 0 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.portfolio-entry-content > :last-child {
|
||||
margin: 0;
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
.jetpack-testimonial-shortcode {
|
||||
clear: both;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.testimonial-entry {
|
||||
float: left;
|
||||
margin: 0 0 3em;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Column setting */
|
||||
.testimonial-entry-column-1 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.testimonial-entry-column-2 {
|
||||
margin-right: 4%;
|
||||
width: 48%;
|
||||
}
|
||||
|
||||
.testimonial-entry-column-3 {
|
||||
margin-right: 3.5%;
|
||||
width: 31%;
|
||||
}
|
||||
|
||||
.testimonial-entry-column-4 {
|
||||
margin-right: 3%;
|
||||
width: 22%;
|
||||
}
|
||||
|
||||
.testimonial-entry-column-5 {
|
||||
margin-right: 2.5%;
|
||||
width: 18%;
|
||||
}
|
||||
|
||||
.testimonial-entry-column-6 {
|
||||
margin-right: 2%;
|
||||
width: 15%;
|
||||
}
|
||||
|
||||
.testimonial-entry-first-item-row {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.testimonial-entry-last-item-row {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
|
||||
.testimonial-entry-mobile-first-item-row {
|
||||
margin-right: 4%;
|
||||
width: 48%;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.testimonial-entry-first-item-row {
|
||||
clear: none;
|
||||
}
|
||||
|
||||
.testimonial-entry-mobile-last-item-row {
|
||||
width: 48%;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.testimonial-featured-image {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.testimonial-featured-image img {
|
||||
border: 0;
|
||||
height: auto;
|
||||
max-width: 100%;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.testimonial-entry-title {
|
||||
font-weight: 700;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.testimonial-featured-image + .testimonial-entry-title {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.testimonial-entry-title a {
|
||||
border: 0;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Entry Content */
|
||||
.testimonial-entry-content {
|
||||
margin: 0.75em 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.testimonial-entry-content > :last-child {
|
||||
margin: 0;
|
||||
}
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
( function () {
|
||||
let menuSelector, nonceInput;
|
||||
const initializedTables = new Set();
|
||||
|
||||
const methods = {
|
||||
init: function ( table ) {
|
||||
let tbody = table.lastElementChild;
|
||||
while ( tbody && tbody.tagName !== 'TBODY' ) {
|
||||
tbody = tbody.previousElementSibling;
|
||||
}
|
||||
const row = tbody.querySelector( 'tr:first-child' ).cloneNode( true );
|
||||
|
||||
table.dataset.form = table.closest( 'form' );
|
||||
table.dataset.tbody = tbody;
|
||||
table.dataset.row = row;
|
||||
table.dataset.currentRow = row;
|
||||
|
||||
menuSelector = document.getElementById( 'nova-menu-tax' );
|
||||
nonceInput = document.getElementById( '_wpnonce' );
|
||||
|
||||
table.addEventListener( 'keypress', function ( event ) {
|
||||
if ( event.which !== 13 ) return;
|
||||
|
||||
event.preventDefault();
|
||||
if ( typeof FormData === 'function' ) {
|
||||
methods.submitRow.call( table );
|
||||
}
|
||||
methods.addRow.call( table );
|
||||
} );
|
||||
|
||||
table.addEventListener( 'focusin', function ( event ) {
|
||||
if ( event.target.tagName === 'INPUT' || event.target.tagName === 'TEXTAREA' ) {
|
||||
table.dataset.currentRow = event.target.closest( 'tr' );
|
||||
}
|
||||
} );
|
||||
|
||||
initializedTables.add( table );
|
||||
return table;
|
||||
},
|
||||
|
||||
destroy: function ( table ) {
|
||||
table.removeEventListener( 'keypress', methods.keypressHandler );
|
||||
table.removeEventListener( 'focusin', methods.focusinHandler );
|
||||
initializedTables.delete( table );
|
||||
return table;
|
||||
},
|
||||
|
||||
submitRow: function ( table ) {
|
||||
const submittedRow = table.dataset.currentRow;
|
||||
const currentInputs = submittedRow.querySelectorAll( 'input, textarea, select' );
|
||||
const form = document.querySelector( table.dataset.form );
|
||||
const allInputs = Array.from( form.querySelectorAll( 'input, textarea, select' ) );
|
||||
|
||||
currentInputs.forEach( input => ( input.disabled = true ) );
|
||||
allInputs
|
||||
.filter( input => ! currentInputs.includes( input ) )
|
||||
.forEach( input => ( input.disabled = true ) );
|
||||
|
||||
const partialFormData = new FormData( form );
|
||||
partialFormData.append( 'ajax', '1' );
|
||||
partialFormData.append( 'nova_menu_tax', menuSelector.value );
|
||||
partialFormData.append( '_wpnonce', nonceInput.value );
|
||||
|
||||
fetch( '', {
|
||||
method: 'POST',
|
||||
body: partialFormData,
|
||||
} )
|
||||
.then( response => response.text() )
|
||||
.then( responseText => {
|
||||
submittedRow.innerHTML = responseText;
|
||||
} );
|
||||
|
||||
allInputs.forEach( input => ( input.disabled = false ) );
|
||||
|
||||
return table;
|
||||
},
|
||||
|
||||
addRow: function ( table ) {
|
||||
const row = table.dataset.row.cloneNode( true );
|
||||
|
||||
const tbody = table.dataset.tbody;
|
||||
tbody.appendChild( row );
|
||||
|
||||
const firstInput = row.querySelector( 'input, textarea, select' );
|
||||
if ( firstInput ) firstInput.focus();
|
||||
|
||||
return table;
|
||||
},
|
||||
|
||||
clickAddRow: function ( table ) {
|
||||
let tbody = table.lastElementChild;
|
||||
|
||||
while ( tbody && tbody.tagName !== 'TBODY' ) {
|
||||
tbody = tbody.previousElementSibling;
|
||||
}
|
||||
const row = tbody.querySelector( 'tr:first-child' ).cloneNode( true );
|
||||
|
||||
row.querySelectorAll( 'input, textarea' ).forEach( input => {
|
||||
input.value = '';
|
||||
} );
|
||||
|
||||
tbody.appendChild( row );
|
||||
},
|
||||
};
|
||||
|
||||
const observeTableRemoval = function () {
|
||||
const observer = new MutationObserver( mutations => {
|
||||
mutations.forEach( mutation => {
|
||||
mutation.removedNodes.forEach( node => {
|
||||
if ( node.matches && node.matches( '.many-items-table' ) ) {
|
||||
methods.destroy( node );
|
||||
}
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
|
||||
observer.observe( document.body, { childList: true, subtree: true } );
|
||||
};
|
||||
|
||||
// Initialization for many-items-table
|
||||
document.addEventListener( 'focusin', event => {
|
||||
const table = event.target.closest( '.many-items-table' );
|
||||
if ( table && ! initializedTables.has( table ) ) {
|
||||
methods.init( table );
|
||||
}
|
||||
} );
|
||||
|
||||
document.addEventListener( 'click', event => {
|
||||
if ( event.target.matches( 'a.nova-new-row' ) ) {
|
||||
const table = event.target.closest( '.many-items-table' );
|
||||
if ( table ) {
|
||||
event.preventDefault();
|
||||
methods.clickAddRow( table );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
observeTableRemoval();
|
||||
} )();
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
( function () {
|
||||
const NovaCheckBoxes = {
|
||||
inputs: null,
|
||||
popInputs: null,
|
||||
|
||||
initialize: function () {
|
||||
// Get all checkboxes in the "nova_menuchecklist-pop"
|
||||
NovaCheckBoxes.popInputs = document.querySelectorAll(
|
||||
'#nova_menuchecklist-pop input[type="checkbox"]'
|
||||
);
|
||||
|
||||
// Get all checkboxes in the "nova_menuchecklist" and add event listeners
|
||||
NovaCheckBoxes.inputs = document.querySelectorAll(
|
||||
'#nova_menuchecklist input[type="checkbox"]'
|
||||
);
|
||||
NovaCheckBoxes.inputs.forEach( input => {
|
||||
input.addEventListener( 'change', NovaCheckBoxes.checkOne );
|
||||
input.addEventListener( 'change', NovaCheckBoxes.syncPop );
|
||||
} );
|
||||
|
||||
// If no checkboxes are checked, check the first one
|
||||
if ( ! NovaCheckBoxes.isChecked() ) {
|
||||
NovaCheckBoxes.checkFirst();
|
||||
}
|
||||
|
||||
// Sync the state of the "pop" inputs
|
||||
NovaCheckBoxes.syncPop();
|
||||
},
|
||||
|
||||
syncPop: function () {
|
||||
NovaCheckBoxes.popInputs.forEach( popInput => {
|
||||
const linkedInput = document.querySelector( `#in-nova_menu-${ popInput.value }` );
|
||||
popInput.checked = linkedInput ? linkedInput.checked : false;
|
||||
} );
|
||||
},
|
||||
|
||||
isChecked: function () {
|
||||
return Array.from( NovaCheckBoxes.inputs ).some( input => input.checked );
|
||||
},
|
||||
|
||||
checkFirst: function () {
|
||||
const firstInput = NovaCheckBoxes.inputs[ 0 ];
|
||||
if ( firstInput ) {
|
||||
firstInput.checked = true;
|
||||
}
|
||||
},
|
||||
|
||||
checkOne: function () {
|
||||
const currentInput = this;
|
||||
|
||||
// If the current checkbox is checked, uncheck all other checkboxes
|
||||
if ( currentInput.checked ) {
|
||||
NovaCheckBoxes.inputs.forEach( input => {
|
||||
if ( input !== currentInput ) {
|
||||
input.checked = false;
|
||||
}
|
||||
} );
|
||||
return;
|
||||
}
|
||||
const checklist = document.querySelector( '#nova_menuchecklist' );
|
||||
|
||||
// If at least one checkbox is still checked, uncheck the current one
|
||||
if ( checklist.querySelectorAll( 'input[type="checkbox"]:checked' ).length > 0 ) {
|
||||
currentInput.checked = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, check the first checkbox
|
||||
NovaCheckBoxes.checkFirst();
|
||||
},
|
||||
};
|
||||
|
||||
// Initialize when the DOM is fully loaded
|
||||
document.addEventListener( 'DOMContentLoaded', NovaCheckBoxes.initialize );
|
||||
} )();
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
/* eslint-disable no-undef */
|
||||
/* global _novaDragDrop */
|
||||
|
||||
( function ( $ ) {
|
||||
let list;
|
||||
|
||||
/**
|
||||
* Initialize the drag and drop functionality.
|
||||
*/
|
||||
function init() {
|
||||
list = $( '#the-list' );
|
||||
dragMenus();
|
||||
addNonce();
|
||||
addSubmitButton();
|
||||
changeToPost();
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow the menu items to be dragged.
|
||||
*/
|
||||
function dragMenus() {
|
||||
list.sortable( {
|
||||
cancel: '.no-items, .inline-edit-row',
|
||||
stop: function ( event, ui ) {
|
||||
if ( ui.item.is( ':first-child' ) ) {
|
||||
return list.sortable( 'cancel' );
|
||||
}
|
||||
//
|
||||
reOrder();
|
||||
},
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow the menu items to be reordered.
|
||||
*/
|
||||
function reOrder() {
|
||||
list.find( '.menu-label-row' ).each( function () {
|
||||
const term_id = $( this ).data( 'term_id' );
|
||||
$( this )
|
||||
.nextUntil( '.menu-label-row' )
|
||||
.each( function ( i ) {
|
||||
const row = $( this );
|
||||
row.find( '.menu-order-value' ).val( i );
|
||||
row.find( '.nova-menu-term' ).val( term_id );
|
||||
} );
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the submit button is added to the page.
|
||||
*/
|
||||
function addSubmitButton() {
|
||||
$( '.tablenav' ).prepend(
|
||||
'<input type="submit" class="button-primary button-reorder alignright" value="' +
|
||||
_novaDragDrop.reorder +
|
||||
'" name="' +
|
||||
_novaDragDrop.reorderName +
|
||||
'" />'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the nonce to the form.
|
||||
*/
|
||||
function addNonce() {
|
||||
$( '#posts-filter' ).append(
|
||||
'<input type="hidden" name="' +
|
||||
_novaDragDrop.nonceName +
|
||||
'" value="' +
|
||||
_novaDragDrop.nonce +
|
||||
'" />'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the form method to POST.
|
||||
*/
|
||||
function changeToPost() {
|
||||
$( '#posts-filter' ).attr( 'method', 'post' );
|
||||
}
|
||||
|
||||
// do it
|
||||
$( document ).ready( init );
|
||||
} )( jQuery );
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
/* global jQuery ajaxurl:true */
|
||||
jQuery( function ( $ ) {
|
||||
$( '#customize-control-featured-content-tag-name input' ).suggest(
|
||||
ajaxurl + '?action=ajax-tag-search&tax=post_tag',
|
||||
{ delay: 500, minchars: 2 }
|
||||
);
|
||||
} );
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
<?php //phpcs:ignore Squiz.Commenting.FileComment.Missing
|
||||
/**
|
||||
* Theme Tools: Jetpack Color.
|
||||
*
|
||||
* @package automattic/jetpack-classic-theme-helper
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../_inc/lib/class.color.php';
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
<?php
|
||||
/**
|
||||
* Theme Tools: Responsive videos enhancements.
|
||||
*
|
||||
* @package automattic/jetpack
|
||||
*/
|
||||
|
||||
use Automattic\Jetpack\Assets;
|
||||
|
||||
/**
|
||||
* Load the Responsive videos plugin
|
||||
*/
|
||||
function jetpack_responsive_videos_init() {
|
||||
|
||||
/* If the doesn't theme support 'jetpack-responsive-videos', don't continue */
|
||||
if ( ! current_theme_supports( 'jetpack-responsive-videos' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the theme does support 'jetpack-responsive-videos', wrap the videos */
|
||||
add_filter( 'wp_video_shortcode', 'jetpack_responsive_videos_embed_html' );
|
||||
add_filter( 'video_embed_html', 'jetpack_responsive_videos_embed_html' );
|
||||
|
||||
/* Only wrap oEmbeds if video */
|
||||
add_filter( 'embed_oembed_html', 'jetpack_responsive_videos_maybe_wrap_oembed', 10, 2 );
|
||||
add_filter( 'embed_handler_html', 'jetpack_responsive_videos_maybe_wrap_oembed', 10, 2 );
|
||||
|
||||
/* Wrap videos in Buddypress */
|
||||
add_filter( 'bp_embed_oembed_html', 'jetpack_responsive_videos_embed_html' );
|
||||
|
||||
/* Wrap Slideshare shortcodes */
|
||||
add_filter( 'jetpack_slideshare_shortcode', 'jetpack_responsive_videos_embed_html' );
|
||||
|
||||
// Remove the Jetpack Responsive video wrapper in embed blocks on sites that support core Responsive embeds.
|
||||
if ( current_theme_supports( 'responsive-embeds' ) ) {
|
||||
add_filter( 'render_block', 'jetpack_responsive_videos_remove_wrap_oembed', 10, 2 );
|
||||
}
|
||||
}
|
||||
add_action( 'after_setup_theme', 'jetpack_responsive_videos_init', 99 );
|
||||
|
||||
/**
|
||||
* Adds a wrapper to videos and enqueue script
|
||||
*
|
||||
* @param string $html The video embed HTML.
|
||||
* @return string
|
||||
*/
|
||||
function jetpack_responsive_videos_embed_html( $html ) {
|
||||
if ( empty( $html ) || ! is_string( $html ) ) {
|
||||
return $html;
|
||||
}
|
||||
|
||||
// Short-circuit for AMP responses, since custom scripts are not allowed in AMP and videos are naturally responsive.
|
||||
// @phan-suppress-next-line PhanUndeclaredClassMethod
|
||||
if ( class_exists( 'Jetpack_AMP_Support' ) && Jetpack_AMP_Support::is_amp_request() ) {
|
||||
return $html;
|
||||
}
|
||||
|
||||
// The customizer video widget wraps videos with a class of wp-video
|
||||
// mejs as of 4.9 apparently resizes videos too which causes issues
|
||||
// skip the video if it is wrapped in wp-video.
|
||||
$video_widget_wrapper = 'class="wp-video"';
|
||||
|
||||
$mejs_wrapped = strpos( $html, $video_widget_wrapper );
|
||||
|
||||
// If this is a video widget wrapped by mejs, return the html.
|
||||
if ( false !== $mejs_wrapped ) {
|
||||
return $html;
|
||||
}
|
||||
|
||||
Assets::register_script(
|
||||
'jetpack-responsive-videos',
|
||||
'../dist/responsive-videos/responsive-videos.js',
|
||||
__FILE__,
|
||||
array(
|
||||
'in_footer' => true,
|
||||
'enqueue' => true,
|
||||
'textdomain' => 'jetpack-classic-theme-helper',
|
||||
'css_path' => '../dist/responsive-videos/responsive-videos.css',
|
||||
)
|
||||
);
|
||||
|
||||
return '<div class="jetpack-video-wrapper">' . $html . '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if oEmbed is a `$video_patterns` provider video before wrapping.
|
||||
*
|
||||
* @param mixed $html The cached HTML result, stored in post meta.
|
||||
* @param string $url he attempted embed URL.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function jetpack_responsive_videos_maybe_wrap_oembed( $html, $url = null ) {
|
||||
if ( empty( $html ) || ! is_string( $html ) || ! $url ) {
|
||||
return $html;
|
||||
}
|
||||
|
||||
// Short-circuit for AMP responses, since custom scripts are not allowed in AMP and videos are naturally responsive.
|
||||
// @phan-suppress-next-line PhanUndeclaredClassMethod
|
||||
if ( class_exists( 'Jetpack_AMP_Support' ) && Jetpack_AMP_Support::is_amp_request() ) {
|
||||
return $html;
|
||||
}
|
||||
|
||||
$jetpack_video_wrapper = '<div class="jetpack-video-wrapper">';
|
||||
|
||||
$already_wrapped = strpos( $html, $jetpack_video_wrapper );
|
||||
|
||||
// If the oEmbed has already been wrapped, return the html.
|
||||
if ( false !== $already_wrapped ) {
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* The oEmbed video providers.
|
||||
*
|
||||
* An allowed list of oEmbed video provider Regex patterns to check against before wrapping the output.
|
||||
*
|
||||
* @module theme-tools
|
||||
*
|
||||
* @since 3.8.0
|
||||
*
|
||||
* @param array $video_patterns oEmbed video provider Regex patterns.
|
||||
*/
|
||||
$video_patterns = apply_filters(
|
||||
'jetpack_responsive_videos_oembed_videos',
|
||||
array(
|
||||
'https?://((m|www)\.)?youtube\.com/watch',
|
||||
'https?://((m|www)\.)?youtube\.com/playlist',
|
||||
'https?://youtu\.be/',
|
||||
'https?://(.+\.)?vimeo\.com/',
|
||||
'https?://(www\.)?dailymotion\.com/',
|
||||
'https?://dai.ly/',
|
||||
'https?://(www\.)?hulu\.com/watch/',
|
||||
'https?://wordpress.tv/',
|
||||
'https?://(www\.)?funnyordie\.com/videos/',
|
||||
'https?://vine.co/v/',
|
||||
'https?://(www\.)?collegehumor\.com/video/',
|
||||
'https?://(www\.|embed\.)?ted\.com/talks/',
|
||||
)
|
||||
);
|
||||
|
||||
// Merge patterns to run in a single preg_match call.
|
||||
$video_patterns = '(' . implode( '|', $video_patterns ) . ')';
|
||||
|
||||
$is_video = preg_match( $video_patterns, $url );
|
||||
|
||||
// If the oEmbed is a video, wrap it in the responsive wrapper.
|
||||
if ( false === $already_wrapped && 1 === $is_video ) {
|
||||
return jetpack_responsive_videos_embed_html( $html );
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the Jetpack Responsive video wrapper in embed blocks.
|
||||
*
|
||||
* @since 7.0.0
|
||||
*
|
||||
* @param string $block_content The block content about to be appended.
|
||||
* @param array $block The full block, including name and attributes.
|
||||
*
|
||||
* @return string $block_content String of rendered HTML.
|
||||
*/
|
||||
function jetpack_responsive_videos_remove_wrap_oembed( $block_content, $block ) {
|
||||
if (
|
||||
isset( $block['blockName'] )
|
||||
&& (
|
||||
str_contains( $block['blockName'], 'core-embed' ) // pre-WP 5.6 embeds (multiple embed blocks starting with 'core-embed').
|
||||
|| 'core/embed' === $block['blockName'] // WP 5.6 embed block format (single embed block w/ block variations).
|
||||
)
|
||||
) {
|
||||
$block_content = preg_replace( '#<div class="jetpack-video-wrapper">(.*?)</div>#', '${1}', $block_content );
|
||||
}
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
.jetpack-video-wrapper {
|
||||
margin-bottom: 1.6em;
|
||||
}
|
||||
|
||||
.jetpack-video-wrapper > embed,
|
||||
.jetpack-video-wrapper > iframe,
|
||||
.jetpack-video-wrapper > object,
|
||||
.jetpack-video-wrapper > .wp-video {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
import './responsive-videos.css';
|
||||
|
||||
let resizeTimer;
|
||||
|
||||
/**
|
||||
* Resize all videos in the document.
|
||||
*/
|
||||
function responsiveVideos() {
|
||||
document.querySelectorAll( '.jetpack-video-wrapper' ).forEach( function ( wrapper ) {
|
||||
wrapper.querySelectorAll( 'embed, iframe, object' ).forEach( function ( video ) {
|
||||
let videoMargin = 0;
|
||||
|
||||
const previousSibling = wrapper.previousElementSibling;
|
||||
if (
|
||||
previousSibling &&
|
||||
previousSibling.nodeName === 'P' &&
|
||||
getComputedStyle( previousSibling )[ 'text-align' ] === 'center'
|
||||
) {
|
||||
videoMargin = '0 auto';
|
||||
}
|
||||
|
||||
if ( ! video.hasAttribute( 'data-ratio' ) ) {
|
||||
video.setAttribute( 'data-ratio', ( video.height || 0 ) / ( video.width || 0 ) );
|
||||
video.setAttribute( 'data-width', video.width );
|
||||
video.setAttribute( 'data-height', video.height );
|
||||
video.style.display = 'block';
|
||||
video.style.margin = videoMargin;
|
||||
}
|
||||
|
||||
const videoHeight = video.getAttribute( 'data-height' );
|
||||
const videoRatio = video.getAttribute( 'data-ratio' );
|
||||
const containerWidth = video.parentElement.clientWidth;
|
||||
|
||||
video.removeAttribute( 'height' );
|
||||
video.removeAttribute( 'width' );
|
||||
|
||||
if ( videoRatio === 'Infinity' ) {
|
||||
video.style.width = '100%';
|
||||
video.style.height = videoHeight + 'px';
|
||||
return;
|
||||
}
|
||||
|
||||
const videoWidth = video.getAttribute( 'data-width' );
|
||||
|
||||
if ( parseInt( videoWidth, 10 ) > containerWidth ) {
|
||||
video.style.width = containerWidth + 'px';
|
||||
video.style.height = containerWidth * parseFloat( videoRatio ) + 'px';
|
||||
} else {
|
||||
video.style.width = videoWidth + 'px';
|
||||
video.style.height = videoHeight + 'px';
|
||||
}
|
||||
} );
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize event listeners and resize everything straight away.
|
||||
*/
|
||||
function init() {
|
||||
window.addEventListener( 'load', responsiveVideos );
|
||||
window.addEventListener( 'resize', function () {
|
||||
clearTimeout( resizeTimer );
|
||||
resizeTimer = setTimeout( responsiveVideos, 500 );
|
||||
} );
|
||||
window.addEventListener( 'is.post-load', responsiveVideos );
|
||||
setTimeout( responsiveVideos );
|
||||
}
|
||||
|
||||
if ( document.readyState !== 'loading' ) {
|
||||
init();
|
||||
} else {
|
||||
document.addEventListener( 'DOMContentLoaded', init );
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/**
|
||||
* Theme Tools: Functions shared between several features.
|
||||
*
|
||||
* @package automattic/jetpack-classic-theme-helper
|
||||
*/
|
||||
|
||||
if ( ! function_exists( 'jetpack_mastodon_get_instance_list' ) ) {
|
||||
|
||||
/**
|
||||
* Build a list of Mastodon instance hosts.
|
||||
* That list can be extended via a filter.
|
||||
*
|
||||
* @since 0.4.3 in Classic Theme Helper (previously in Jetpack since 11.8)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function jetpack_mastodon_get_instance_list() {
|
||||
$mastodon_instance_list = array(
|
||||
// Regex pattern to match any .tld for the mastodon host name.
|
||||
'#https?:\/\/(www\.)?mastodon\.(\w+)(\.\w+)?#',
|
||||
// Regex pattern to match any .tld for the mstdn host name.
|
||||
'#https?:\/\/(www\.)?mstdn\.(\w+)(\.\w+)?#',
|
||||
'counter.social',
|
||||
'fosstodon.org',
|
||||
'gc2.jp',
|
||||
'hachyderm.io',
|
||||
'infosec.exchange',
|
||||
'mas.to',
|
||||
'pawoo.net',
|
||||
);
|
||||
|
||||
/**
|
||||
* Filter the list of Mastodon instances.
|
||||
*
|
||||
* @since 0.4.3 in Classic Theme Helper (previously in Jetpack since 11.8)
|
||||
*
|
||||
* @module widgets, theme-tools
|
||||
*
|
||||
* @param array $mastodon_instance_list Array of Mastodon instances.
|
||||
*/
|
||||
return (array) apply_filters( 'jetpack_mastodon_instance_list', $mastodon_instance_list );
|
||||
}
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
/**
|
||||
* Theme Tools: Site Breadcrumbs.
|
||||
*
|
||||
* Quickly add breadcrumbs to the single view of a hierarchical post type or a hierarchical taxonomy.
|
||||
*
|
||||
* @package automattic/jetpack-classic-theme-helper
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
$host = new Automattic\Jetpack\Status\Host();
|
||||
if ( ! function_exists( 'jetpack_breadcrumbs' ) && ! $host->is_wpcom_simple() ) {
|
||||
/**
|
||||
* Echos a set of breadcrumbs.
|
||||
*
|
||||
* Themes can call this function where the breadcrumbs should be outputted.
|
||||
*/
|
||||
function jetpack_breadcrumbs() {
|
||||
$taxonomy = is_category() ? 'category' : get_query_var( 'taxonomy' );
|
||||
$is_taxonomy_hierarchical = is_taxonomy_hierarchical( $taxonomy );
|
||||
|
||||
$post_type = is_page() ? 'page' : get_query_var( 'post_type' );
|
||||
$is_post_type_hierarchical = is_post_type_hierarchical( $post_type );
|
||||
|
||||
if ( ! ( $is_post_type_hierarchical || $is_taxonomy_hierarchical ) || is_front_page() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$breadcrumb = '';
|
||||
$position = 1;
|
||||
|
||||
if ( $is_post_type_hierarchical ) {
|
||||
$post_id = get_queried_object_id();
|
||||
$ancestors = array_reverse( get_post_ancestors( $post_id ) );
|
||||
if ( $ancestors ) {
|
||||
foreach ( $ancestors as $ancestor ) {
|
||||
$breadcrumb .= '<span itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem"><meta itemprop="position" content="' . esc_attr( (string) $position ) . '"><a href="' . esc_url( get_permalink( $ancestor ) ) . '" itemprop="item"><span itemprop="name">' . esc_html( get_the_title( $ancestor ) ) . '</span></a></span>';
|
||||
++$position;
|
||||
}
|
||||
}
|
||||
$breadcrumb .= '<span class="current-page" itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem"><meta itemprop="position" content="' . esc_attr( (string) $position ) . '"><span itemprop="name">' . esc_html( get_the_title( $post_id ) ) . '</span></span>';
|
||||
} elseif ( $is_taxonomy_hierarchical ) {
|
||||
$current = get_term( get_queried_object_id(), $taxonomy );
|
||||
|
||||
if ( is_wp_error( $current ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( $current->parent ) {
|
||||
$breadcrumb = jetpack_get_term_parents( $current->parent, $taxonomy );
|
||||
}
|
||||
|
||||
$breadcrumb .= '<span class="current-category" itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem"><meta property="position" content="' . esc_attr( (string) $position ) . '"><span itemprop="name">' . esc_html( $current->name ) . '</span></span>';
|
||||
}
|
||||
|
||||
$home = '<span itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem"><meta itemprop="position" content="' . esc_attr( (string) $position ) . '"><meta itemprop="position" content="0"><a href="' . esc_url( home_url( '/' ) ) . '" class="home-link" itemprop="item" rel="home"><span itemprop="name">' . esc_html__( 'Home', 'jetpack-classic-theme-helper' ) . '</span></a></span>';
|
||||
|
||||
echo '<nav class="entry-breadcrumbs" itemscope itemtype="https://schema.org/BreadcrumbList">' . $home . $breadcrumb . '</nav>'; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_get_term_parents' ) ) {
|
||||
/**
|
||||
* Return the parents for a given taxonomy term ID.
|
||||
*
|
||||
* @param int $term Taxonomy term whose parents will be returned.
|
||||
* @param string $taxonomy Taxonomy name that the term belongs to.
|
||||
* @param array $visited Terms already added to prevent duplicates.
|
||||
*
|
||||
* @return string|WP_Error A list of links to the term parents|WP_Error.
|
||||
*/
|
||||
function jetpack_get_term_parents( $term, $taxonomy, $visited = array() ) {
|
||||
$parent = get_term( $term, $taxonomy );
|
||||
|
||||
if ( is_wp_error( $parent ) ) {
|
||||
return $parent;
|
||||
}
|
||||
|
||||
$chain = '';
|
||||
|
||||
if ( $parent->parent && ( $parent->parent !== $parent->term_id ) && ! in_array( $parent->parent, $visited, true ) ) {
|
||||
$visited[] = $parent->parent;
|
||||
$chain .= jetpack_get_term_parents( $parent->parent, $taxonomy, $visited );
|
||||
}
|
||||
|
||||
$chain .= '<a href="' . esc_url( get_category_link( $parent->term_id ) ) . '">' . $parent->name . '</a>';
|
||||
|
||||
return $chain;
|
||||
}
|
||||
}
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
/**
|
||||
* Social Menu.
|
||||
*
|
||||
* This feature will only be activated for themes that declare their support.
|
||||
* This can be done by adding code similar to the following during the
|
||||
* 'after_setup_theme' action:
|
||||
*
|
||||
* add_theme_support( 'jetpack-social-menu' );
|
||||
*
|
||||
* @package automattic/jetpack-classic-theme-helper
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_social_menu_init' ) ) {
|
||||
/**
|
||||
* Activate the Social Menu plugin.
|
||||
*
|
||||
* @uses current_theme_supports()
|
||||
*/
|
||||
function jetpack_social_menu_init() {
|
||||
// Only load our code if our theme declares support
|
||||
if ( ! current_theme_supports( 'jetpack-social-menu' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Social Menu description.
|
||||
*
|
||||
* Rename the social menu description.
|
||||
*
|
||||
* @module theme-tools
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @param string $social_menu_description Social Menu description
|
||||
*/
|
||||
$social_menu_description = apply_filters( 'jetpack_social_menu_description', __( 'Social Menu', 'jetpack-classic-theme-helper' ) );
|
||||
|
||||
// Register a new menu location
|
||||
register_nav_menus(
|
||||
array(
|
||||
'jetpack-social-menu' => esc_html( $social_menu_description ),
|
||||
)
|
||||
);
|
||||
|
||||
// Enqueue CSS
|
||||
add_action( 'wp_enqueue_scripts', 'jetpack_social_menu_style' );
|
||||
|
||||
// Load SVG icons related functions and filters
|
||||
if ( 'svg' === jetpack_social_menu_get_type() ) {
|
||||
require __DIR__ . '/social-menu/icon-functions.php';
|
||||
}
|
||||
}
|
||||
add_action( 'after_setup_theme', 'jetpack_social_menu_init', 99 );
|
||||
add_action( 'restapi_theme_init', 'jetpack_social_menu_init' );
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_social_menu_get_type' ) ) {
|
||||
/**
|
||||
* Return the type of menu the theme is using.
|
||||
*
|
||||
* @uses get_theme_support()
|
||||
* @return null|string $menu_type
|
||||
*/
|
||||
function jetpack_social_menu_get_type() {
|
||||
$options = get_theme_support( 'jetpack-social-menu' );
|
||||
|
||||
if ( ! $options ) {
|
||||
$menu_type = null;
|
||||
} else {
|
||||
$menu_type = 'genericons';
|
||||
if ( is_array( $options ) && isset( $options[0] ) ) {
|
||||
$menu_type = ( in_array( $options[0], array( 'genericons', 'svg' ), true ) ) ? $options[0] : 'genericons';
|
||||
}
|
||||
}
|
||||
|
||||
return $menu_type;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_social_menu_style' ) ) {
|
||||
/**
|
||||
* Function to enqueue the CSS.
|
||||
*/
|
||||
function jetpack_social_menu_style() {
|
||||
$menu_type = jetpack_social_menu_get_type();
|
||||
|
||||
if ( ! $menu_type ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$deps = ( 'genericons' === $menu_type ) ? array( 'genericons' ) : null;
|
||||
|
||||
if ( has_nav_menu( 'jetpack-social-menu' ) ) {
|
||||
wp_enqueue_style( 'jetpack-social-menu', plugins_url( 'social-menu/social-menu.css', __FILE__ ), $deps, '1.0' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_social_menu' ) ) {
|
||||
/**
|
||||
* Create the function for the menu.
|
||||
*/
|
||||
function jetpack_social_menu() {
|
||||
if ( has_nav_menu( 'jetpack-social-menu' ) ) :
|
||||
$menu_type = (string) jetpack_social_menu_get_type();
|
||||
$link_after = '</span>';
|
||||
|
||||
if ( 'svg' === $menu_type ) {
|
||||
$link_after .= jetpack_social_menu_get_svg( array( 'icon' => 'chain' ) );
|
||||
} ?>
|
||||
<nav class="jetpack-social-navigation jetpack-social-navigation-<?php echo esc_attr( $menu_type ); ?>" aria-label="<?php esc_html_e( 'Social Links Menu', 'jetpack-classic-theme-helper' ); ?>">
|
||||
<?php
|
||||
wp_nav_menu(
|
||||
array(
|
||||
'theme_location' => 'jetpack-social-menu',
|
||||
'link_before' => '<span class="screen-reader-text">',
|
||||
'link_after' => $link_after,
|
||||
'depth' => 1,
|
||||
)
|
||||
);
|
||||
?>
|
||||
</nav><!-- .jetpack-social-navigation -->
|
||||
<?php
|
||||
endif;
|
||||
}
|
||||
}
|
||||
+242
@@ -0,0 +1,242 @@
|
||||
<?php
|
||||
/**
|
||||
* SVG icons related functions and filters
|
||||
*
|
||||
* @package automattic/jetpack-classic-theme-helper
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_social_menu_include_svg_icons' ) ) {
|
||||
/**
|
||||
* Add SVG definitions to the footer.
|
||||
*/
|
||||
function jetpack_social_menu_include_svg_icons() {
|
||||
// Return early if Social Menu doesn't exist.
|
||||
if ( ! has_nav_menu( 'jetpack-social-menu' ) ) {
|
||||
return;
|
||||
}
|
||||
// Define SVG sprite file.
|
||||
$svg_icons = __DIR__ . '/social-menu.svg';
|
||||
// If it exists and we use the SVG menu type, include it.
|
||||
if ( file_exists( $svg_icons ) && 'svg' === jetpack_social_menu_get_type() ) {
|
||||
$svg_contents = file_get_contents( $svg_icons ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- Only reading a local file.
|
||||
}
|
||||
|
||||
if ( ! empty( $svg_contents ) ) {
|
||||
$allowed_tags = array(
|
||||
'svg' => array(
|
||||
'style' => true,
|
||||
'version' => true,
|
||||
'xmlns' => true,
|
||||
'xmlns:xlink' => true,
|
||||
),
|
||||
'defs' => array(),
|
||||
'symbol' => array(
|
||||
'id' => true,
|
||||
'viewbox' => true,
|
||||
),
|
||||
'path' => array(
|
||||
'd' => true,
|
||||
'style' => true,
|
||||
),
|
||||
);
|
||||
echo wp_kses( $svg_contents, $allowed_tags );
|
||||
}
|
||||
}
|
||||
add_action( 'wp_footer', 'jetpack_social_menu_include_svg_icons', 9999 );
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_social_menu_get_svg' ) ) {
|
||||
/**
|
||||
* Return SVG markup.
|
||||
*
|
||||
* @param array $args {
|
||||
* Parameters needed to display an SVG.
|
||||
*
|
||||
* @type string $icon Required SVG icon filename.
|
||||
* }
|
||||
* @return string SVG markup.
|
||||
*/
|
||||
function jetpack_social_menu_get_svg( $args = array() ) {
|
||||
// Make sure $args are an array.
|
||||
if ( empty( $args ) ) {
|
||||
return esc_html__( 'Please define default parameters in the form of an array.', 'jetpack-classic-theme-helper' );
|
||||
}
|
||||
|
||||
// Define an icon.
|
||||
if ( ! ( array_key_exists( 'icon', $args ) ) ) {
|
||||
return esc_html__( 'Please define an SVG icon filename.', 'jetpack-classic-theme-helper' );
|
||||
}
|
||||
|
||||
// Set defaults.
|
||||
$defaults = array(
|
||||
'icon' => '',
|
||||
'fallback' => false,
|
||||
);
|
||||
|
||||
// Parse args.
|
||||
$args = wp_parse_args( $args, $defaults );
|
||||
|
||||
// Set aria hidden.
|
||||
$aria_hidden = ' aria-hidden="true"';
|
||||
|
||||
// Begin SVG markup.
|
||||
$svg = '<svg class="icon icon-' . esc_attr( $args['icon'] ) . '"' . $aria_hidden . ' role="img">';
|
||||
|
||||
/*
|
||||
* Display the icon.
|
||||
*
|
||||
* The whitespace around `<use>` is intentional - it is a work around to a keyboard navigation bug in Safari 10.
|
||||
*
|
||||
* See https://core.trac.wordpress.org/ticket/38387.
|
||||
*/
|
||||
$svg .= ' <use href="#icon-' . esc_html( $args['icon'] ) . '" xlink:href="#icon-' . esc_html( $args['icon'] ) . '"></use> ';
|
||||
|
||||
// Add some markup to use as a fallback for browsers that do not support SVGs.
|
||||
if ( $args['fallback'] ) {
|
||||
$svg .= '<span class="svg-fallback icon-' . esc_attr( $args['icon'] ) . '"></span>';
|
||||
}
|
||||
|
||||
$svg .= '</svg>';
|
||||
|
||||
return $svg;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_social_menu_nav_menu_social_icons' ) ) {
|
||||
/**
|
||||
* Display SVG icons in social links menu.
|
||||
*
|
||||
* @param string $item_output The menu item output.
|
||||
* @param WP_Post $item Menu item object.
|
||||
* @param int $depth Depth of the menu.
|
||||
* @param object $args wp_nav_menu() arguments.
|
||||
* @return string $item_output The menu item output with social icon.
|
||||
*/
|
||||
function jetpack_social_menu_nav_menu_social_icons( $item_output, $item, $depth, $args ) {
|
||||
if ( ! is_object( $args ) ) {
|
||||
return $item_output;
|
||||
}
|
||||
|
||||
// Get supported social icons.
|
||||
$social_icons = jetpack_social_menu_social_links_icons();
|
||||
|
||||
// Change SVG icon inside social links menu if there is supported URL.
|
||||
if ( 'jetpack-social-menu' === $args->theme_location ) {
|
||||
foreach ( $social_icons as $attr => $value ) {
|
||||
/*
|
||||
* attr can be a URL host, or a regex, starting with #.
|
||||
* Let's check for both scenarios.
|
||||
*/
|
||||
if (
|
||||
// First Regex.
|
||||
(
|
||||
str_starts_with( $attr, '#' ) && str_ends_with( $attr, '#' )
|
||||
&& preg_match( $attr, $item_output )
|
||||
)
|
||||
// Then, regular host name.
|
||||
|| str_contains( $item_output, $attr )
|
||||
) {
|
||||
$item_output = str_replace(
|
||||
$args->link_after,
|
||||
'</span>' . jetpack_social_menu_get_svg( array( 'icon' => esc_attr( $value ) ) ),
|
||||
$item_output
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $item_output;
|
||||
}
|
||||
add_filter( 'walker_nav_menu_start_el', 'jetpack_social_menu_nav_menu_social_icons', 10, 4 );
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'jetpack_social_menu_social_links_icons' ) ) {
|
||||
/**
|
||||
* Returns an array of supported social links (URL / regex and icon name).
|
||||
* For regex, use the # delimiter.
|
||||
*
|
||||
* @return array $social_links_icons
|
||||
*/
|
||||
function jetpack_social_menu_social_links_icons() {
|
||||
// Supported social links icons.
|
||||
$social_links_icons = array(
|
||||
'#https?:\/\/(www\.)?amazon\.(com|cn|in|fr|de|it|nl|es|co|ca)\/#' => 'amazon',
|
||||
'500px.com' => '500px',
|
||||
'#https?:\/\/(www\.)?apple\.com\/#' => 'apple',
|
||||
'itunes.com' => 'apple',
|
||||
'bandcamp.com' => 'bandcamp',
|
||||
'behance.net' => 'behance',
|
||||
'blogger.com' => 'blogger',
|
||||
'blogspot.com' => 'blogger',
|
||||
'bsky.app' => 'bluesky',
|
||||
'codepen.io' => 'codepen',
|
||||
'deviantart.com' => 'deviantart',
|
||||
'discord.gg' => 'discord',
|
||||
'discordapp.com' => 'discord',
|
||||
'digg.com' => 'digg',
|
||||
'dribbble.com' => 'dribbble',
|
||||
'dropbox.com' => 'dropbox',
|
||||
'etsy.com' => 'etsy',
|
||||
'eventbrite.com' => 'eventbrite',
|
||||
'facebook.com' => 'facebook',
|
||||
'/feed/' => 'feed',
|
||||
'flickr.com' => 'flickr',
|
||||
'foursquare.com' => 'foursquare',
|
||||
'ghost.org' => 'ghost',
|
||||
'goodreads.com' => 'goodreads',
|
||||
'google.com' => 'google',
|
||||
'github.com' => 'github',
|
||||
'instagram.com' => 'instagram',
|
||||
'linkedin.com' => 'linkedin',
|
||||
'mailto:' => 'mail',
|
||||
'meetup.com' => 'meetup',
|
||||
'medium.com' => 'medium',
|
||||
'nextdoor.com' => 'nextdoor',
|
||||
'patreon.com' => 'patreon',
|
||||
'pinterest.' => 'pinterest',
|
||||
'pocketcasts.com' => 'pocket-casts',
|
||||
'podcasts.apple.com' => 'apple-podcasts',
|
||||
'ravelry.com' => 'ravelry',
|
||||
'reddit.com' => 'reddit',
|
||||
'slideshare.net' => 'slideshare',
|
||||
'sms:' => 'sms',
|
||||
'snapchat.com' => 'snapchat',
|
||||
'soundcloud.com' => 'soundcloud',
|
||||
'spotify.com' => 'spotify',
|
||||
'stackoverflow.com' => 'stackoverflow',
|
||||
'strava.com' => 'strava',
|
||||
'stumbleupon.com' => 'stumbleupon',
|
||||
'telegram.me' => 'telegram',
|
||||
'threads.net' => 'threads',
|
||||
'tiktok.com' => 'tiktok',
|
||||
'tumblr.com' => 'tumblr',
|
||||
'twitch.tv' => 'twitch',
|
||||
'twitter.com' => 'x',
|
||||
'vimeo.com' => 'vimeo',
|
||||
'vk.com' => 'vk',
|
||||
'whatsapp.com' => 'whatsapp',
|
||||
'woocommerce.com' => 'woocommerce',
|
||||
'wordpress.org' => 'wordpress',
|
||||
'wordpress.com' => 'wordpress',
|
||||
'yelp.com' => 'yelp',
|
||||
'x.com' => 'x',
|
||||
'xanga.com' => 'xanga',
|
||||
'youtube.com' => 'youtube',
|
||||
);
|
||||
|
||||
/*
|
||||
* Add Mastodon instances to this array.
|
||||
*/
|
||||
require_once __DIR__ . '../../shared-functions.php';
|
||||
$mastodon_instance_list = jetpack_mastodon_get_instance_list();
|
||||
foreach ( $mastodon_instance_list as $instance ) {
|
||||
$social_links_icons[ $instance ] = 'mastodon';
|
||||
}
|
||||
|
||||
return $social_links_icons;
|
||||
}
|
||||
}
|
||||
+206
@@ -0,0 +1,206 @@
|
||||
/*--------------------------------------------------------------
|
||||
Global
|
||||
--------------------------------------------------------------*/
|
||||
.jetpack-social-navigation ul {
|
||||
display: block;
|
||||
margin: 0 0 1.5em;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.jetpack-social-navigation li {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.jetpack-social-navigation a {
|
||||
border: 0;
|
||||
height: 1em;
|
||||
text-decoration: none;
|
||||
width: 1em;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------
|
||||
SVG
|
||||
--------------------------------------------------------------*/
|
||||
.jetpack-social-navigation-svg .icon {
|
||||
color: inherit;
|
||||
fill: currentColor;
|
||||
height: 1em;
|
||||
vertical-align: middle;
|
||||
width: 1em;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------
|
||||
Genericons
|
||||
--------------------------------------------------------------*/
|
||||
.jetpack-social-navigation-genericons a::before {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
display: inline-block;
|
||||
font-family: Genericons;
|
||||
font-size: 1em;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
height: 1em;
|
||||
line-height: 1;
|
||||
speak: none;
|
||||
text-decoration: inherit;
|
||||
vertical-align: top;
|
||||
width: 1em;
|
||||
|
||||
/* Default */
|
||||
content: "\f415";
|
||||
}
|
||||
|
||||
/* Bluesky */
|
||||
.jetpack-social-navigation-genericons a[href*="bsky.app"]::before {
|
||||
content: "\f10f";
|
||||
}
|
||||
|
||||
/* CodePen */
|
||||
.jetpack-social-navigation-genericons a[href*="codepen.io"]::before {
|
||||
content: "\f216";
|
||||
}
|
||||
|
||||
/* Digg */
|
||||
.jetpack-social-navigation-genericons a[href*="digg.com"]::before {
|
||||
content: "\f221";
|
||||
}
|
||||
|
||||
/* Dribbble */
|
||||
.jetpack-social-navigation-genericons a[href*="dribbble.com"]::before {
|
||||
content: "\f201";
|
||||
}
|
||||
|
||||
/* Dropbox */
|
||||
.jetpack-social-navigation-genericons a[href*="dropbox.com"]::before {
|
||||
content: "\f225";
|
||||
}
|
||||
|
||||
/* Email */
|
||||
.jetpack-social-navigation-genericons a[href*="mailto:"]::before {
|
||||
content: "\f410";
|
||||
}
|
||||
|
||||
/* Facebook */
|
||||
.jetpack-social-navigation-genericons a[href*="facebook.com"]::before {
|
||||
content: "\f203";
|
||||
}
|
||||
|
||||
/* Flickr */
|
||||
.jetpack-social-navigation-genericons a[href*="flickr.com"]::before {
|
||||
content: "\f211";
|
||||
}
|
||||
|
||||
/* Foursquare */
|
||||
.jetpack-social-navigation-genericons a[href*="foursquare.com"]::before {
|
||||
content: "\f226";
|
||||
}
|
||||
|
||||
/* GitHub */
|
||||
.jetpack-social-navigation-genericons a[href*="github.com"]::before {
|
||||
content: "\f200";
|
||||
}
|
||||
|
||||
/* Google Plus */
|
||||
.jetpack-social-navigation-genericons a[href*="plus.google.com"]::before {
|
||||
content: "\f206";
|
||||
}
|
||||
|
||||
/* Instagram */
|
||||
.jetpack-social-navigation-genericons a[href*="instagram.com"]::before {
|
||||
content: "\f215";
|
||||
}
|
||||
|
||||
/* LinkedIn */
|
||||
.jetpack-social-navigation-genericons a[href*="linkedin.com"]::before {
|
||||
content: "\f208";
|
||||
}
|
||||
|
||||
/* Nextdoor */
|
||||
.jetpack-social-navigation-genericons a[href*="nextdoor.com"]::before {
|
||||
content: "\f10c";
|
||||
}
|
||||
|
||||
/* Path */
|
||||
.jetpack-social-navigation-genericons a[href*="path.com"]::before {
|
||||
content: "\f219";
|
||||
}
|
||||
|
||||
/* Pinterest */
|
||||
.jetpack-social-navigation-genericons a[href*="pinterest."]::before {
|
||||
content: "\f210";
|
||||
}
|
||||
|
||||
/* Polldaddy */
|
||||
.jetpack-social-navigation-genericons a[href*="polldaddy.com"]::before {
|
||||
content: "\f217";
|
||||
}
|
||||
|
||||
/* Reddit */
|
||||
.jetpack-social-navigation-genericons a[href*="reddit.com"]::before {
|
||||
content: "\f222";
|
||||
}
|
||||
|
||||
/* RSS Feed */
|
||||
.jetpack-social-navigation-genericons a[href$="/feed/"]::before {
|
||||
content: "\f413";
|
||||
}
|
||||
|
||||
/* SMS */
|
||||
.jetpack-social-navigation-genericons a[href*="sms:"]::before {
|
||||
content: "\f110";
|
||||
}
|
||||
|
||||
/* Spotify */
|
||||
.jetpack-social-navigation-genericons a[href*="spotify.com"]::before {
|
||||
content: "\f515";
|
||||
}
|
||||
|
||||
/* StumbleUpon */
|
||||
.jetpack-social-navigation-genericons a[href*="stumbleupon.com"]::before {
|
||||
content: "\f223";
|
||||
}
|
||||
|
||||
/* Threads */
|
||||
.jetpack-social-navigation-genericons a[href*="threads.net"]::before {
|
||||
content: "\f10d";
|
||||
}
|
||||
|
||||
/* Tumblr */
|
||||
.jetpack-social-navigation-genericons a[href*="tumblr.com"]::before {
|
||||
content: "\f214";
|
||||
}
|
||||
|
||||
/* Twitch */
|
||||
.jetpack-social-navigation-genericons a[href*="twitch.tv"]::before {
|
||||
content: "\f516";
|
||||
}
|
||||
|
||||
/* Twitter, X */
|
||||
.jetpack-social-navigation-genericons a[href*="x.com"]::before,
|
||||
.jetpack-social-navigation-genericons a[href*="twitter.com"]::before {
|
||||
content: "\f202";
|
||||
}
|
||||
|
||||
/* Vimeo */
|
||||
.jetpack-social-navigation-genericons a[href*="vimeo.com"]::before {
|
||||
content: "\f212";
|
||||
}
|
||||
|
||||
/* Vine */
|
||||
.jetpack-social-navigation-genericons a[href*="vine.co"]::before {
|
||||
content: "\f517";
|
||||
}
|
||||
|
||||
/* WordPress */
|
||||
.jetpack-social-navigation-genericons a[href*="wordpress.com"]::before,
|
||||
.jetpack-social-navigation-genericons a[href*="wordpress.org"]::before {
|
||||
content: "\f205";
|
||||
}
|
||||
|
||||
/* YouTube */
|
||||
.jetpack-social-navigation-genericons a[href*="youtube.com"]::before {
|
||||
content: "\f213";
|
||||
}
|
||||
+191
@@ -0,0 +1,191 @@
|
||||
<svg style="position: absolute; width: 0; height: 0; overflow: hidden;" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs>
|
||||
<symbol id="icon-500px" viewBox="0 0 24 24">
|
||||
<path d="M6.94026,15.1412c.00437.01213.108.29862.168.44064a6.55008,6.55008,0,1,0,6.03191-9.09557,6.68654,6.68654,0,0,0-2.58357.51467A8.53914,8.53914,0,0,0,8.21268,8.61344L8.209,8.61725V3.22948l9.0504-.00008c.32934-.0036.32934-.46353.32934-.61466s0-.61091-.33035-.61467L7.47248,2a.43.43,0,0,0-.43131.42692v7.58355c0,.24466.30476.42131.58793.4819.553.11812.68074-.05864.81617-.2457l.018-.02481A10.52673,10.52673,0,0,1,9.32258,9.258a5.35268,5.35268,0,1,1,7.58985,7.54976,5.417,5.417,0,0,1-3.80867,1.56365,5.17483,5.17483,0,0,1-2.69822-.74478l.00342-4.61111a2.79372,2.79372,0,0,1,.71372-1.78792,2.61611,2.61611,0,0,1,1.98282-.89477,2.75683,2.75683,0,0,1,1.95525.79477,2.66867,2.66867,0,0,1,.79656,1.909,2.724,2.724,0,0,1-2.75849,2.748,4.94651,4.94651,0,0,1-.86254-.13719c-.31234-.093-.44519.34058-.48892.48349-.16811.54966.08453.65862.13687.67489a3.75751,3.75751,0,0,0,1.25234.18375,3.94634,3.94634,0,1,0-2.82444-6.742,3.67478,3.67478,0,0,0-1.13028,2.584l-.00041.02323c-.0035.11667-.00579,2.881-.00644,3.78811l-.00407-.00451a6.18521,6.18521,0,0,1-1.0851-1.86092c-.10544-.27856-.34358-.22925-.66857-.12917-.14192.04372-.57386.17677-.47833.489Zm4.65165-1.08338a.51346.51346,0,0,0,.19513.31818l.02276.022a.52945.52945,0,0,0,.3517.18416.24242.24242,0,0,0,.16577-.0611c.05473-.05082.67382-.67812.73287-.738l.69041.68819a.28978.28978,0,0,0,.21437.11032.53239.53239,0,0,0,.35708-.19486c.29792-.30419.14885-.46821.07676-.54751l-.69954-.69975.72952-.73469c.16-.17311.01874-.35708-.12218-.498-.20461-.20461-.402-.25742-.52855-.14083l-.7254.72665-.73354-.73375a.20128.20128,0,0,0-.14179-.05695.54135.54135,0,0,0-.34379.19648c-.22561.22555-.274.38149-.15656.5059l.73374.7315-.72942.73072A.26589.26589,0,0,0,11.59191,14.05782Zm1.59866-9.915A8.86081,8.86081,0,0,0,9.854,4.776a.26169.26169,0,0,0-.16938.22759.92978.92978,0,0,0,.08619.42094c.05682.14524.20779.531.50006.41955a8.40969,8.40969,0,0,1,2.91968-.55484,7.87875,7.87875,0,0,1,3.086.62286,8.61817,8.61817,0,0,1,2.30562,1.49315.2781.2781,0,0,0,.18318.07586c.15529,0,.30425-.15253.43167-.29551.21268-.23861.35873-.4369.1492-.63538a8.50425,8.50425,0,0,0-2.62312-1.694A9.0177,9.0177,0,0,0,13.19058,4.14283ZM19.50945,18.6236h0a.93171.93171,0,0,0-.36642-.25406.26589.26589,0,0,0-.27613.06613l-.06943.06929A7.90606,7.90606,0,0,1,7.60639,18.505a7.57284,7.57284,0,0,1-1.696-2.51537,8.58715,8.58715,0,0,1-.5147-1.77754l-.00871-.04864c-.04939-.25873-.28755-.27684-.62981-.22448-.14234.02178-.5755.088-.53426.39969l.001.00712a9.08807,9.08807,0,0,0,15.406,4.99094c.00193-.00192.04753-.04718.0725-.07436C19.79425,19.16234,19.87422,18.98728,19.50945,18.6236Z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-amazon" viewBox="0 0 24 24">
|
||||
<path d="M13.582,8.182C11.934,8.367,9.78,8.49,8.238,9.166c-1.781,0.769-3.03,2.337-3.03,4.644 c0,2.953,1.86,4.429,4.253,4.429c2.02,0,3.125-0.477,4.685-2.065c0.516,0.747,0.685,1.109,1.629,1.894 c0.212,0.114,0.483,0.103,0.672-0.066l0.006,0.006c0.567-0.505,1.599-1.401,2.18-1.888c0.231-0.188,0.19-0.496,0.009-0.754 c-0.52-0.718-1.072-1.303-1.072-2.634V8.305c0-1.876,0.133-3.599-1.249-4.891C15.23,2.369,13.422,2,12.04,2 C9.336,2,6.318,3.01,5.686,6.351C5.618,6.706,5.877,6.893,6.109,6.945l2.754,0.298C9.121,7.23,9.308,6.977,9.357,6.72 c0.236-1.151,1.2-1.706,2.284-1.706c0.584,0,1.249,0.215,1.595,0.738c0.398,0.584,0.346,1.384,0.346,2.061V8.182z M13.049,14.088 c-0.451,0.8-1.169,1.291-1.967,1.291c-1.09,0-1.728-0.83-1.728-2.061c0-2.42,2.171-2.86,4.227-2.86v0.615 C13.582,12.181,13.608,13.104,13.049,14.088z M20.683,19.339C18.329,21.076,14.917,22,11.979,22c-4.118,0-7.826-1.522-10.632-4.057 c-0.22-0.199-0.024-0.471,0.241-0.317c3.027,1.762,6.771,2.823,10.639,2.823c2.608,0,5.476-0.541,8.115-1.66 C20.739,18.62,21.072,19.051,20.683,19.339z M21.336,21.043c-0.194,0.163-0.379,0.076-0.293-0.139 c0.284-0.71,0.92-2.298,0.619-2.684c-0.301-0.386-1.99-0.183-2.749-0.092c-0.23,0.027-0.266-0.173-0.059-0.319 c1.348-0.946,3.555-0.673,3.811-0.356C22.925,17.773,22.599,19.986,21.336,21.043z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-apple" viewBox="0 0 24 24">
|
||||
<path d="M20.07,17.586a10.874,10.874,0,0,1-1.075,1.933,9.822,9.822,0,0,1-1.385,1.674,2.687,2.687,0,0,1-1.78.784,4.462,4.462,0,0,1-1.644-.393,4.718,4.718,0,0,0-1.77-.391,4.878,4.878,0,0,0-1.82.391A4.9,4.9,0,0,1,9.021,22a2.53,2.53,0,0,1-1.82-.8A10.314,10.314,0,0,1,5.752,19.46,11.987,11.987,0,0,1,4.22,16.417a11.143,11.143,0,0,1-.643-3.627,6.623,6.623,0,0,1,.87-3.465A5.1,5.1,0,0,1,6.268,7.483a4.9,4.9,0,0,1,2.463-.695,5.8,5.8,0,0,1,1.9.443,6.123,6.123,0,0,0,1.511.444,9.04,9.04,0,0,0,1.675-.523,5.537,5.537,0,0,1,2.277-.4,4.835,4.835,0,0,1,3.788,1.994,4.213,4.213,0,0,0-2.235,3.827,4.222,4.222,0,0,0,1.386,3.181,4.556,4.556,0,0,0,1.385.909q-.167.483-.353.927ZM16.211,2.4a4.267,4.267,0,0,1-1.094,2.8,3.726,3.726,0,0,1-3.1,1.528A3.114,3.114,0,0,1,12,6.347a4.384,4.384,0,0,1,1.16-2.828,4.467,4.467,0,0,1,1.414-1.061A4.215,4.215,0,0,1,16.19,2a3.633,3.633,0,0,1,.021.4Z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-apple-podcasts" viewBox="0 0 24 24">
|
||||
<path d="M20.9988 7.98575C20.9978 7.80475 20.9955 7.6235 20.9907 7.4425C20.98 7.04825 20.9567 6.65025 20.8867 6.2605C20.8155 5.8645 20.6995 5.496 20.5163 5.13625C20.3363 4.78275 20.1012 4.4595 19.821 4.17925C19.5407 3.899 19.2173 3.66375 18.8638 3.48375C18.5043 3.30075 18.1357 3.1845 17.74 3.1135C17.35 3.04325 16.952 3.02025 16.5575 3.0095C16.3765 3.0045 16.1955 3.0025 16.0142 3.0015C15.7992 3 15.5843 3 15.3693 3H8.63075C8.41575 3 8.20075 3 7.98575 3.00125C7.80475 3.00225 7.6235 3.0045 7.4425 3.00925C7.048 3.02 6.65 3.04325 6.26 3.11325C5.86425 3.1845 5.496 3.3005 5.13625 3.4835C4.78275 3.6635 4.4595 3.8985 4.179 4.179C3.89875 4.4595 3.6635 4.78275 3.48375 5.13625C3.3005 5.496 3.1845 5.8645 3.11325 6.2605C3.04325 6.6505 3.02 7.04825 3.00925 7.4425C3.00425 7.6235 3.00225 7.8045 3.00125 7.98575C3 8.20075 3 8.41575 3 8.63075V15.3695C3 15.5845 3 15.7995 3.00125 16.0145C3.00225 16.1955 3.0045 16.3767 3.00925 16.5577C3.02 16.952 3.04325 17.35 3.11325 17.7397C3.1845 18.1357 3.3005 18.5043 3.48375 18.864C3.66375 19.2175 3.89875 19.5407 4.179 19.821C4.4595 20.1015 4.78275 20.3365 5.13625 20.5163C5.49575 20.6993 5.86425 20.8155 6.26 20.8865C6.65 20.9567 7.048 20.9797 7.4425 20.9905C7.6235 20.9955 7.8045 20.9975 7.98575 20.9985C8.20075 21 8.41575 21 8.63075 21H15.3695C15.5845 21 15.7995 21 16.0145 20.9988C16.1955 20.9978 16.3767 20.9955 16.5577 20.9907C16.9522 20.98 17.3502 20.9567 17.7402 20.8867C18.136 20.8155 18.5043 20.6995 18.864 20.5165C19.2175 20.3365 19.5408 20.1015 19.8213 19.8213C20.1015 19.5408 20.3368 19.2175 20.5165 18.8643C20.6998 18.5045 20.8157 18.136 20.887 17.74C20.957 17.35 20.9802 16.9522 20.991 16.558C20.996 16.377 20.998 16.196 20.999 16.0147C21 15.7992 21 15.5843 21 15.3693V8.63075C21 8.41575 21 8.20075 20.9988 7.98575ZM13.3787 14.9288C13.3357 15.433 13.2545 16.1055 13.148 16.7902C13.0722 17.2775 13.0108 17.5408 12.9548 17.729C12.864 18.0343 12.5248 18.3013 11.9943 18.3013C11.4638 18.3013 11.1245 18.0343 11.0337 17.729C10.9777 17.5408 10.9162 17.2775 10.8405 16.7902C10.7342 16.1055 10.6527 15.433 10.6097 14.9288C10.5647 14.3995 10.5413 14.0685 10.583 13.6842C10.6045 13.4857 10.6725 13.3465 10.8015 13.2105C11.0485 12.95 11.4823 12.783 11.9943 12.783C12.5063 12.783 12.9403 12.95 13.187 13.2105C13.316 13.3465 13.384 13.4857 13.4055 13.6842C13.4473 14.0687 13.4237 14.3998 13.3787 14.9288ZM9.84925 13.65C9.901 13.6985 9.9285 13.7675 9.92475 13.838C9.91275 14.0533 9.917 14.2625 9.9315 14.499C9.93525 14.5617 9.86475 14.6022 9.81275 14.5667C8.777 13.8595 8.1005 12.6638 8.11775 11.314C8.144 9.262 9.78975 7.571 11.8413 7.4915C14.0485 7.406 15.8717 9.17625 15.8717 11.3645C15.8717 12.6933 15.1993 13.868 14.1768 14.5665C14.1248 14.602 14.054 14.5617 14.058 14.499C14.0722 14.2627 14.0767 14.0535 14.0645 13.8383C14.0605 13.7675 14.0883 13.6985 14.14 13.65C14.7498 13.0777 15.1313 12.265 15.1313 11.3647C15.1313 9.59475 13.6565 8.1625 11.8708 8.2315C10.2278 8.29525 8.9025 9.63725 8.85925 11.2805C8.83425 12.214 9.2205 13.0597 9.84925 13.65ZM13.3413 10.8925C13.3413 11.6362 12.7383 12.239 11.9943 12.239C11.2503 12.239 10.6473 11.6362 10.6473 10.8925C10.6473 10.1487 11.2503 9.546 11.9943 9.546C12.7383 9.546 13.3413 10.1487 13.3413 10.8925ZM13.9097 16.824C13.8545 16.8435 13.7985 16.7975 13.8073 16.7397C13.837 16.5417 13.8652 16.343 13.891 16.1473C13.9002 16.0783 13.944 16.0183 14.0077 15.9905C15.7915 15.2118 17.0413 13.4315 17.0413 11.3645C17.0413 8.56875 14.7548 6.29675 11.9528 6.31925C9.212 6.3415 6.974 8.575 6.9475 11.315C6.92725 13.4027 8.18275 15.2052 9.9805 15.9902C10.0445 16.0182 10.0885 16.0778 10.0978 16.147C10.1235 16.3428 10.1517 16.5417 10.1815 16.7397C10.1902 16.7977 10.1342 16.8435 10.079 16.824C7.8045 16.0243 6.17575 13.8423 6.20725 11.2915C6.24625 8.1425 8.8275 5.58775 11.9775 5.579C15.1765 5.57 17.7817 8.16875 17.7817 11.3647C17.7817 13.884 16.1625 16.032 13.9097 16.824Z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-bandcamp" viewBox="0 0 24 24">
|
||||
<path d="M15.27 17.289 3 17.289 8.73 6.711 21 6.711 15.27 17.289"/>
|
||||
</symbol>
|
||||
<symbol id="icon-behance" viewBox="0 0 24 24">
|
||||
<path d="M7.799,5.698c0.589,0,1.12,0.051,1.606,0.156c0.482,0.102,0.894,0.273,1.241,0.507c0.344,0.235,0.612,0.546,0.804,0.938 c0.188,0.387,0.281,0.871,0.281,1.443c0,0.619-0.141,1.137-0.421,1.551c-0.284,0.413-0.7,0.751-1.255,1.014 c0.756,0.218,1.317,0.601,1.689,1.146c0.374,0.549,0.557,1.205,0.557,1.975c0,0.623-0.12,1.161-0.359,1.612 c-0.241,0.457-0.569,0.828-0.973,1.114c-0.408,0.288-0.876,0.5-1.399,0.637C9.052,17.931,8.514,18,7.963,18H2V5.698H7.799 M7.449,10.668c0.481,0,0.878-0.114,1.192-0.345c0.311-0.228,0.463-0.603,0.463-1.119c0-0.286-0.051-0.523-0.152-0.707 C8.848,8.315,8.711,8.171,8.536,8.07C8.362,7.966,8.166,7.894,7.94,7.854c-0.224-0.044-0.457-0.06-0.697-0.06H4.709v2.874H7.449z M7.6,15.905c0.267,0,0.521-0.024,0.759-0.077c0.243-0.053,0.457-0.137,0.637-0.261c0.182-0.12,0.332-0.283,0.441-0.491 C9.547,14.87,9.6,14.602,9.6,14.278c0-0.633-0.18-1.084-0.533-1.357c-0.356-0.27-0.83-0.404-1.413-0.404H4.709v3.388L7.6,15.905z M16.162,15.864c0.367,0.358,0.897,0.538,1.583,0.538c0.493,0,0.92-0.125,1.277-0.374c0.354-0.248,0.571-0.514,0.654-0.79h2.155 c-0.347,1.072-0.872,1.838-1.589,2.299C19.534,18,18.67,18.23,17.662,18.23c-0.701,0-1.332-0.113-1.899-0.337 c-0.567-0.227-1.041-0.544-1.439-0.958c-0.389-0.415-0.689-0.907-0.904-1.484c-0.213-0.574-0.32-1.21-0.32-1.899 c0-0.666,0.11-1.288,0.329-1.863c0.222-0.577,0.529-1.075,0.933-1.492c0.406-0.42,0.885-0.751,1.444-0.994 c0.558-0.241,1.175-0.363,1.857-0.363c0.754,0,1.414,0.145,1.98,0.44c0.563,0.291,1.026,0.686,1.389,1.181 c0.363,0.493,0.622,1.057,0.783,1.69c0.16,0.632,0.217,1.292,0.171,1.983h-6.428C15.557,14.84,15.795,15.506,16.162,15.864 M18.973,11.184c-0.291-0.321-0.783-0.496-1.384-0.496c-0.39,0-0.714,0.066-0.973,0.2c-0.254,0.132-0.461,0.297-0.621,0.491 c-0.157,0.197-0.265,0.405-0.328,0.628c-0.063,0.217-0.101,0.413-0.111,0.587h3.98C19.478,11.969,19.265,11.509,18.973,11.184z M15.057,7.738h4.985V6.524h-4.985L15.057,7.738z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-blogger" viewBox="0 0 24 24">
|
||||
<path d="M14.722,14.019c0,0.361-0.293,0.654-0.654,0.654H9.977c-0.361,0-0.654-0.293-0.654-0.654s0.293-0.654,0.654-0.654h4.091C14.429,13.365,14.722,13.658,14.722,14.019z M9.981,10.698h2.038c0.382,0,0.692-0.31,0.692-0.692c0-0.382-0.31-0.692-0.692-0.692H9.981c-0.382,0-0.692,0.31-0.692,0.692C9.289,10.388,9.599,10.698,9.981,10.698z M21,5v14c0,1.105-0.895,2-2,2H5c-1.105,0-2-0.895-2-2V5c0-1.105,0.895-2,2-2h14C20.105,3,21,3.895,21,5z M17.544,11.39c0-0.398-0.322-0.72-0.72-0.72h-0.607l-0.013,0.001c-0.38,0-0.692-0.295-0.718-0.668l-0.001-0.008c0-1.988-1.611-3.599-3.599-3.599h-1.816c-1.988,0-3.599,1.611-3.599,3.599v3.947c0,1.987,1.611,3.599,3.599,3.599h3.874c1.988,0,3.599-1.611,3.599-3.599L17.544,11.39z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-bluesky" viewBox="0 0 24 24">
|
||||
<path d="M21.2 3.3C20.7 3.1 19.8 2.8 17.6 4.3C15.4 6 12.9 9.2 12 11C11.1 9.2 8.6 6 6.3 4.3C4.1 2.7 3.3 3 2.7 3.3C2.1 3.6 2 4.6 2 5.1C2 5.6 2.3 9.8 2.5 10.5C3.2 12.8 5.6 13.6 7.8 13.3C4.5 13.8 1.6 15 5.4 19.2C9.6 23.5 11.1 18.3 11.9 15.6C12.7 18.3 13.6 23.3 18.3 19.2C21.9 15.6 19.3 13.8 16 13.3C18.2 13.5 20.6 12.8 21.3 10.5C21.7 9.8 22 5.7 22 5.1C22 4.6 21.9 3.6 21.2 3.3Z" />
|
||||
</symbol>
|
||||
<symbol id="icon-chain" viewBox="0 0 24 24">
|
||||
<path d="M19.647,16.706a1.134,1.134,0,0,0-.343-.833l-2.549-2.549a1.134,1.134,0,0,0-.833-.343,1.168,1.168,0,0,0-.883.392l.233.226q.2.189.264.264a2.922,2.922,0,0,1,.184.233.986.986,0,0,1,.159.312,1.242,1.242,0,0,1,.043.337,1.172,1.172,0,0,1-1.176,1.176,1.237,1.237,0,0,1-.337-.043,1,1,0,0,1-.312-.159,2.76,2.76,0,0,1-.233-.184q-.073-.068-.264-.264l-.226-.233a1.19,1.19,0,0,0-.4.895,1.134,1.134,0,0,0,.343.833L15.837,19.3a1.13,1.13,0,0,0,.833.331,1.18,1.18,0,0,0,.833-.318l1.8-1.789a1.12,1.12,0,0,0,.343-.821Zm-8.615-8.64a1.134,1.134,0,0,0-.343-.833L8.163,4.7a1.134,1.134,0,0,0-.833-.343,1.184,1.184,0,0,0-.833.331L4.7,6.473a1.12,1.12,0,0,0-.343.821,1.134,1.134,0,0,0,.343.833l2.549,2.549a1.13,1.13,0,0,0,.833.331,1.184,1.184,0,0,0,.883-.38L8.728,10.4q-.2-.189-.264-.264A2.922,2.922,0,0,1,8.28,9.9a.986.986,0,0,1-.159-.312,1.242,1.242,0,0,1-.043-.337A1.172,1.172,0,0,1,9.254,8.079a1.237,1.237,0,0,1,.337.043,1,1,0,0,1,.312.159,2.761,2.761,0,0,1,.233.184q.073.068.264.264l.226.233a1.19,1.19,0,0,0,.4-.895ZM22,16.706a3.343,3.343,0,0,1-1.042,2.488l-1.8,1.789a3.536,3.536,0,0,1-4.988-.025l-2.525-2.537a3.384,3.384,0,0,1-1.017-2.488,3.448,3.448,0,0,1,1.078-2.561l-1.078-1.078a3.434,3.434,0,0,1-2.549,1.078,3.4,3.4,0,0,1-2.5-1.029L3.029,9.794A3.4,3.4,0,0,1,2,7.294,3.343,3.343,0,0,1,3.042,4.806l1.8-1.789A3.384,3.384,0,0,1,7.331,2a3.357,3.357,0,0,1,2.5,1.042l2.525,2.537a3.384,3.384,0,0,1,1.017,2.488,3.448,3.448,0,0,1-1.078,2.561l1.078,1.078a3.551,3.551,0,0,1,5.049-.049l2.549,2.549A3.4,3.4,0,0,1,22,16.706Z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-codepen" viewBox="0 0 24 24">
|
||||
<path d="M22.016,8.84c-0.002-0.013-0.005-0.025-0.007-0.037c-0.005-0.025-0.008-0.048-0.015-0.072 c-0.003-0.015-0.01-0.028-0.013-0.042c-0.008-0.02-0.015-0.04-0.023-0.062c-0.007-0.015-0.013-0.028-0.02-0.042 c-0.008-0.02-0.018-0.037-0.03-0.057c-0.007-0.013-0.017-0.027-0.025-0.038c-0.012-0.018-0.023-0.035-0.035-0.052 c-0.01-0.013-0.02-0.025-0.03-0.037c-0.015-0.017-0.028-0.032-0.043-0.045c-0.01-0.012-0.022-0.023-0.035-0.035 c-0.015-0.015-0.032-0.028-0.048-0.04c-0.012-0.01-0.025-0.02-0.037-0.03c-0.005-0.003-0.01-0.008-0.015-0.012l-9.161-6.096 c-0.289-0.192-0.666-0.192-0.955,0L2.359,8.237C2.354,8.24,2.349,8.245,2.344,8.249L2.306,8.277 c-0.017,0.013-0.033,0.027-0.048,0.04C2.246,8.331,2.234,8.342,2.222,8.352c-0.015,0.015-0.028,0.03-0.042,0.047 c-0.012,0.013-0.022,0.023-0.03,0.037C2.139,8.453,2.125,8.471,2.115,8.488C2.107,8.501,2.099,8.514,2.09,8.526 C2.079,8.548,2.069,8.565,2.06,8.585C2.054,8.6,2.047,8.613,2.04,8.626C2.032,8.648,2.025,8.67,2.019,8.69 c-0.005,0.013-0.01,0.027-0.013,0.042C1.999,8.755,1.995,8.778,1.99,8.803C1.989,8.817,1.985,8.828,1.984,8.84 C1.978,8.879,1.975,8.915,1.975,8.954v6.093c0,0.037,0.003,0.075,0.008,0.112c0.002,0.012,0.005,0.025,0.007,0.038 c0.005,0.023,0.008,0.047,0.015,0.072c0.003,0.015,0.008,0.028,0.013,0.04c0.007,0.022,0.013,0.042,0.022,0.063 c0.007,0.015,0.013,0.028,0.02,0.04c0.008,0.02,0.018,0.038,0.03,0.058c0.007,0.013,0.015,0.027,0.025,0.038 c0.012,0.018,0.023,0.035,0.035,0.052c0.01,0.013,0.02,0.025,0.03,0.037c0.013,0.015,0.028,0.032,0.042,0.045 c0.012,0.012,0.023,0.023,0.035,0.035c0.015,0.013,0.032,0.028,0.048,0.04l0.038,0.03c0.005,0.003,0.01,0.007,0.013,0.01 l9.163,6.095C11.668,21.953,11.833,22,12,22c0.167,0,0.332-0.047,0.478-0.144l9.163-6.095l0.015-0.01 c0.013-0.01,0.027-0.02,0.037-0.03c0.018-0.013,0.035-0.028,0.048-0.04c0.013-0.012,0.025-0.023,0.035-0.035 c0.017-0.015,0.03-0.032,0.043-0.045c0.01-0.013,0.02-0.025,0.03-0.037c0.013-0.018,0.025-0.035,0.035-0.052 c0.008-0.013,0.018-0.027,0.025-0.038c0.012-0.02,0.022-0.038,0.03-0.058c0.007-0.013,0.013-0.027,0.02-0.04 c0.008-0.022,0.015-0.042,0.023-0.063c0.003-0.013,0.01-0.027,0.013-0.04c0.007-0.025,0.01-0.048,0.015-0.072 c0.002-0.013,0.005-0.027,0.007-0.037c0.003-0.042,0.007-0.079,0.007-0.117V8.954C22.025,8.915,22.022,8.879,22.016,8.84z M12.862,4.464l6.751,4.49l-3.016,2.013l-3.735-2.492V4.464z M11.138,4.464v4.009l-3.735,2.494L4.389,8.954L11.138,4.464z M3.699,10.562L5.853,12l-2.155,1.438V10.562z M11.138,19.536l-6.749-4.491l3.015-2.011l3.735,2.492V19.536z M12,14.035L8.953,12 L12,9.966L15.047,12L12,14.035z M12.862,19.536v-4.009l3.735-2.492l3.016,2.011L12.862,19.536z M20.303,13.438L18.147,12 l2.156-1.438L20.303,13.438z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-deviantart" viewBox="0 0 24 24">
|
||||
<path d="M 18.19 5.636 18.19 2 18.188 2 14.553 2 14.19 2.366 12.474 5.636 11.935 6 5.81 6 5.81 10.994 9.177 10.994 9.477 11.357 5.81 18.363 5.81 22 5.811 22 9.447 22 9.81 21.634 11.526 18.364 12.065 18 18.19 18 18.19 13.006 14.823 13.006 14.523 12.641 18.19 5.636z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-digg" viewBox="0 0 24 24">
|
||||
<path d="M4.5,5.4h2.2V16H1V8.5h3.5V5.4L4.5,5.4z M4.5,14.2v-4H3.2v4H4.5z M7.6,8.5V16h2.2V8.5C9.8,8.5,7.6,8.5,7.6,8.5z M7.6,5.4 v2.2h2.2V5.4C9.8,5.4,7.6,5.4,7.6,5.4z M10.7,8.5h5.7v10.1h-5.7v-1.8h3.5V16h-3.5C10.7,16,10.7,8.5,10.7,8.5z M14.2,14.2v-4h-1.3v4 H14.2z M17.3,8.5H23v10.1h-5.7v-1.8h3.5V16h-3.5C17.3,16,17.3,8.5,17.3,8.5z M20.8,14.2v-4h-1.3v4H20.8z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-discord" viewBox="0 0 24 24">
|
||||
<path d="M10.227 9.957c-.559 0-1 .48-1 1.063 0 .585.453 1.066 1 1.066.558 0 1-.48 1-1.066.007-.582-.442-1.063-1-1.063zm3.574 0c-.559 0-.996.48-.996 1.063 0 .585.449 1.066.996 1.066.558 0 1-.48 1-1.066 0-.582-.442-1.063-1-1.063zm0 0 M18.563 1.918H5.438c-1.11 0-2.008.879-2.008 1.973v12.957c0 1.093.898 1.972 2.007 1.972h11.11l-.52-1.773 1.254 1.14 1.184 1.075 2.105 1.82V3.891c0-1.094-.898-1.973-2.008-1.973zM14.78 14.434s-.351-.414-.644-.778c1.281-.355 1.773-1.14 1.773-1.14a5.745 5.745 0 0 1-1.129.566c-.488.2-.96.336-1.418.41a7.07 7.07 0 0 1-2.539-.008 8.133 8.133 0 0 1-1.441-.414 6.219 6.219 0 0 1-.715-.324c-.027-.02-.059-.027-.086-.047a.113.113 0 0 1-.039-.031c-.176-.094-.273-.16-.273-.16s.468.765 1.71 1.129c-.293.363-.656.797-.656.797-2.164-.067-2.984-1.457-2.984-1.457 0-3.086 1.41-5.586 1.41-5.586 1.41-1.036 2.75-1.008 2.75-1.008l.098.113c-1.762.5-2.575 1.258-2.575 1.258s.215-.117.579-.277c1.046-.454 1.878-.579 2.222-.606.059-.008.11-.02.168-.02a8.728 8.728 0 0 1 1.977-.019c.933.106 1.93.375 2.949.922 0 0-.773-.719-2.438-1.219l.137-.152s1.34-.028 2.75 1.008c0 0 1.414 2.5 1.414 5.586 0 0-.836 1.39-3 1.457zm0 0"/>
|
||||
</symbol>
|
||||
<symbol id="icon-dribbble" viewBox="0 0 24 24">
|
||||
<path d="M12,22C6.486,22,2,17.514,2,12S6.486,2,12,2c5.514,0,10,4.486,10,10S17.514,22,12,22z M20.434,13.369 c-0.292-0.092-2.644-0.794-5.32-0.365c1.117,3.07,1.572,5.57,1.659,6.09C18.689,17.798,20.053,15.745,20.434,13.369z M15.336,19.876c-0.127-0.749-0.623-3.361-1.822-6.477c-0.019,0.006-0.038,0.013-0.056,0.019c-4.818,1.679-6.547,5.02-6.701,5.334 c1.448,1.129,3.268,1.803,5.243,1.803C13.183,20.555,14.311,20.313,15.336,19.876z M5.654,17.724 c0.193-0.331,2.538-4.213,6.943-5.637c0.111-0.036,0.224-0.07,0.337-0.102c-0.214-0.485-0.448-0.971-0.692-1.45 c-4.266,1.277-8.405,1.223-8.778,1.216c-0.003,0.087-0.004,0.174-0.004,0.261C3.458,14.207,4.29,16.21,5.654,17.724z M3.639,10.264 c0.382,0.005,3.901,0.02,7.897-1.041c-1.415-2.516-2.942-4.631-3.167-4.94C5.979,5.41,4.193,7.613,3.639,10.264z M9.998,3.709 c0.236,0.316,1.787,2.429,3.187,5c3.037-1.138,4.323-2.867,4.477-3.085C16.154,4.286,14.17,3.471,12,3.471 C11.311,3.471,10.641,3.554,9.998,3.709z M18.612,6.612C18.432,6.855,17,8.69,13.842,9.979c0.199,0.407,0.389,0.821,0.567,1.237 c0.063,0.148,0.124,0.295,0.184,0.441c2.842-0.357,5.666,0.215,5.948,0.275C20.522,9.916,19.801,8.065,18.612,6.612z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-dropbox" viewBox="0 0 24 24">
|
||||
<path d="M12,6.134L6.069,9.797L2,6.54l5.883-3.843L12,6.134z M2,13.054l5.883,3.843L12,13.459L6.069,9.797L2,13.054z M12,13.459 l4.116,3.439L22,13.054l-4.069-3.257L12,13.459z M22,6.54l-5.884-3.843L12,6.134l5.931,3.663L22,6.54z M12.011,14.2l-4.129,3.426 l-1.767-1.153v1.291l5.896,3.539l5.897-3.539v-1.291l-1.769,1.153L12.011,14.2z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-etsy" viewBox="0 0 24 24">
|
||||
<path d="M9.16033,4.038c0-.27174.02717-.43478.48913-.43478h6.22283c1.087,0,1.68478.92391,2.11957,2.663l.35326,1.38587h1.05978C19.59511,3.712,19.75815,2,19.75815,2s-2.663.29891-4.23913.29891h-7.962L3.29076,2.163v1.1413L4.731,3.57609c1.00543.19022,1.25.40761,1.33152,1.33152,0,0,.08152,2.71739.08152,7.20109s-.08152,7.17391-.08152,7.17391c0,.81522-.32609,1.11413-1.33152,1.30435l-1.44022.27174V22l4.2663-.13587h7.11957c1.60326,0,5.32609.13587,5.32609.13587.08152-.97826.625-5.40761.70652-5.89674H19.7038L18.644,18.52174c-.84239,1.90217-2.06522,2.038-3.42391,2.038H11.1712c-1.3587,0-2.01087-.54348-2.01087-1.712V12.65217s3.0163,0,3.99457.08152c.76087.05435,1.22283.27174,1.46739,1.33152l.32609,1.413h1.16848l-.08152-3.55978.163-3.587H15.02989l-.38043,1.57609c-.24457,1.03261-.40761,1.22283-1.46739,1.33152-1.38587.13587-4.02174.1087-4.02174.1087Z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-eventbrite" viewBox="0 0 24 24">
|
||||
<path style="fill-rule:evenodd;clip-rule:evenodd;" d="M18.041,3.931L5.959,3C4.325,3,3,4.325,3,5.959v12.083C3,19.675,4.325,21,5.959,21l12.083-0.931C19.699,19.983,21,18.744,21,17.11V6.89C21,5.256,19.741,4.027,18.041,3.931zM16.933,8.17c-0.082,0.215-0.192,0.432-0.378,0.551c-0.188,0.122-0.489,0.132-0.799,0.132c-1.521,0-3.062-0.048-4.607-0.048c-0.152,0.708-0.304,1.416-0.451,2.128c0.932-0.004,1.873,0.005,2.81,0.005c0.726,0,1.462-0.069,1.586,0.525c0.04,0.189-0.001,0.426-0.052,0.615c-0.105,0.38-0.258,0.676-0.625,0.783c-0.185,0.054-0.408,0.058-0.646,0.058c-1.145,0-2.345,0.017-3.493,0.02c-0.169,0.772-0.328,1.553-0.489,2.333c1.57-0.005,3.067-0.041,4.633-0.058c0.627-0.007,1.085,0.194,1.009,0.85c-0.031,0.262-0.098,0.497-0.211,0.725c-0.102,0.208-0.248,0.376-0.488,0.452c-0.237,0.075-0.541,0.064-0.862,0.078c-0.304,0.014-0.614,0.008-0.924,0.016c-0.309,0.009-0.619,0.022-0.919,0.022c-1.253,0-2.429,0.08-3.683,0.073c-0.603-0.004-1.014-0.249-1.124-0.757c-0.059-0.273-0.018-0.58,0.036-0.841c0.541-2.592,1.083-5.176,1.629-7.763c0.056-0.265,0.114-0.511,0.225-0.714C9.279,7.051,9.534,6.834,9.9,6.735c0.368-0.099,0.883-0.047,1.344-0.047c0.305,0,0.612,0.008,0.914,0.016c0.925,0.026,1.817,0.03,2.747,0.053c0.304,0.007,0.615,0.016,0.915,0.016c0.621,0,1.17,0.073,1.245,0.614C17.104,7.675,17.014,7.954,16.933,8.17z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-facebook" viewBox="0 0 24 24">
|
||||
<path d="M12,2C6.5,2,2,6.5,2,12c0,5,3.7,9.1,8.4,9.9v-7H7.9V12h2.5V9.8c0-2.5,1.5-3.9,3.8-3.9c1.1,0,2.2,0.2,2.2,0.2v2.5h-1.3 c-1.2,0-1.6,0.8-1.6,1.6V12h2.8l-0.4,2.9h-2.3v7C18.3,21.1,22,17,22,12C22,6.5,17.5,2,12,2z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-fediverse" viewBox="0 0 24 24">
|
||||
<path d="M5.85081 8.88733C5.63868 9.29358 5.30628 9.62442 4.89905 9.83466L10.1241 15.0801L11.3838 14.4417L5.85081 8.88733ZM12.7428 15.8059L11.4831 16.4443L14.1306 19.1022C14.3428 18.6958 14.6752 18.3649 15.0825 18.1547L12.7428 15.8059ZM18.788 10.9628L15.83 12.4619L16.0481 13.857L19.3951 12.1608C19.0742 11.8335 18.8622 11.4151 18.788 10.9628ZM14.1128 13.3322L7.11871 16.8768C7.43963 17.2041 7.65166 17.6225 7.72582 18.0748L14.3309 14.7273L14.1128 13.3322ZM11.8635 4.60095L8.48868 11.1895L9.48512 12.1898L13.0584 5.21403C12.6065 5.13759 12.1892 4.92348 11.8635 4.60095ZM7.61092 12.9031L5.90146 16.2403C6.35333 16.3168 6.77058 16.5309 7.0962 16.8534L8.60729 13.9033L7.61092 12.9031ZM4.87004 9.8493C4.52582 10.0216 4.14278 10.1017 3.75836 10.0817C3.68642 10.0777 3.61473 10.0702 3.54352 10.0593L4.54173 16.444C4.88595 16.2717 5.26899 16.1916 5.65342 16.2116C5.7253 16.2156 5.79694 16.2231 5.86809 16.2341L4.87004 9.8493ZM7.73111 18.1064C7.75395 18.2547 7.76177 18.4049 7.75437 18.5547C7.73734 18.8604 7.65743 19.1592 7.51964 19.4326L13.9033 20.457C13.8805 20.3087 13.8727 20.1585 13.88 20.0087C13.897 19.703 13.977 19.4042 14.1148 19.1308L7.73111 18.1064ZM19.4175 12.1841L16.471 17.9364C16.923 18.0128 17.3403 18.227 17.666 18.5496L20.6124 12.7973C20.1604 12.7208 19.7431 12.5067 19.4175 12.1841ZM15.3989 4.04834C15.1867 4.45466 14.8542 4.78556 14.4469 4.99581L19.01 9.57651C19.2221 9.17019 19.5546 8.83929 19.9619 8.62904L15.3989 4.04834ZM11.234 3.37973L5.46578 6.30295C5.78666 6.63022 5.99866 7.04859 6.07282 7.50088L11.841 4.57753C11.5202 4.25029 11.3082 3.83197 11.234 3.37973ZM14.4364 5.0011C14.0876 5.17976 13.6978 5.26314 13.3064 5.24282C13.2412 5.23884 13.1762 5.23202 13.1116 5.22237L13.6226 8.49422L15.0168 8.71794L14.4364 5.0011ZM13.9196 10.3964L15.1276 18.132C15.4678 17.9652 15.8448 17.888 16.2231 17.9077C16.3011 17.9121 16.3788 17.9207 16.4559 17.9333L15.3138 10.62L13.9196 10.3964ZM6.07692 7.52543C6.10063 7.67596 6.10884 7.82852 6.10141 7.98072C6.08459 8.28399 6.00588 8.5806 5.87013 8.85231L9.1445 9.37821L9.78804 8.12143L6.07692 7.52543ZM11.6889 8.42664L11.0452 9.68356L18.7819 10.9261C18.7596 10.7795 18.7521 10.631 18.7594 10.483C18.7766 10.1755 18.8575 9.87496 18.9968 9.60035L11.6889 8.42664Z"/>
|
||||
<path d="M13.3174 5.04077C14.433 5.10157 15.3867 4.24642 15.4474 3.13079C15.5082 2.01516 14.6531 1.06149 13.5374 1.00073C12.4218 0.93994 11.4682 1.79509 11.4074 2.91072C11.3466 4.02635 12.2018 4.98002 13.3174 5.04077ZM20.8714 12.6241C21.987 12.6848 22.9407 11.8297 23.0015 10.714C23.0623 9.59842 22.2071 8.64478 21.0915 8.58399C19.9759 8.52323 19.0222 9.37838 18.9614 10.494C18.9006 11.6096 19.7558 12.5633 20.8714 12.6241ZM15.992 22.1497C17.1076 22.2105 18.0613 21.3554 18.1221 20.2398C18.1828 19.1241 17.3277 18.1705 16.2121 18.1097C15.0965 18.0489 14.1428 18.9041 14.082 20.0197C14.0212 21.1353 14.8764 22.089 15.992 22.1497ZM5.42232 20.4537C6.53795 20.5144 7.49162 19.6593 7.55238 18.5437C7.61317 17.428 6.75802 16.4744 5.64239 16.4136C4.52677 16.3529 3.5731 17.208 3.51234 18.3236C3.45158 19.4392 4.3067 20.3929 5.42232 20.4537ZM3.76933 9.87973C4.88496 9.94052 5.83863 9.08537 5.89938 7.96974C5.96014 6.85411 5.10503 5.90045 3.98937 5.83969C2.87374 5.77893 1.9201 6.63405 1.85931 7.74967C1.79855 8.8653 2.6537 9.81897 3.76933 9.87973Z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-feed" viewBox="0 0 24 24">
|
||||
<path d="M2,8.667V12c5.515,0,10,4.485,10,10h3.333C15.333,14.637,9.363,8.667,2,8.667z M2,2v3.333 c9.19,0,16.667,7.477,16.667,16.667H22C22,10.955,13.045,2,2,2z M4.5,17C3.118,17,2,18.12,2,19.5S3.118,22,4.5,22S7,20.88,7,19.5 S5.882,17,4.5,17z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-flickr" viewBox="0 0 24 24">
|
||||
<path d="M6.5,7c-2.75,0-5,2.25-5,5s2.25,5,5,5s5-2.25,5-5S9.25,7,6.5,7z M17.5,7c-2.75,0-5,2.25-5,5s2.25,5,5,5s5-2.25,5-5 S20.25,7,17.5,7z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-foursquare" viewBox="0 0 24 24">
|
||||
<path d="M17.573,2c0,0-9.197,0-10.668,0S5,3.107,5,3.805s0,16.948,0,16.948c0,0.785,0.422,1.077,0.66,1.172 c0.238,0.097,0.892,0.177,1.285-0.275c0,0,5.035-5.843,5.122-5.93c0.132-0.132,0.132-0.132,0.262-0.132h3.26 c1.368,0,1.588-0.977,1.732-1.552c0.078-0.318,0.692-3.428,1.225-6.122l0.675-3.368C19.56,2.893,19.14,2,17.573,2z M16.495,7.22 c-0.053,0.252-0.372,0.518-0.665,0.518c-0.293,0-4.157,0-4.157,0c-0.467,0-0.802,0.318-0.802,0.787v0.508 c0,0.467,0.337,0.798,0.805,0.798c0,0,3.197,0,3.528,0s0.655,0.362,0.583,0.715c-0.072,0.353-0.407,2.102-0.448,2.295 c-0.04,0.193-0.262,0.523-0.655,0.523c-0.33,0-2.88,0-2.88,0c-0.523,0-0.683,0.068-1.033,0.503 c-0.35,0.437-3.505,4.223-3.505,4.223c-0.032,0.035-0.063,0.027-0.063-0.015V4.852c0-0.298,0.26-0.648,0.648-0.648 c0,0,8.228,0,8.562,0c0.315,0,0.61,0.297,0.528,0.683L16.495,7.22z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-ghost" viewBox="0 0 24 24">
|
||||
<path d="M10.203,20.997H3.005v-3.599h7.198V20.997z M20.995,17.398h-7.193v3.599h7.193V17.398z M20.998,10.2H3v3.599h17.998V10.2zM13.803,3.003H3.005v3.599h10.798V3.003z M21,3.003h-3.599v3.599H21V3.003z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-github" viewBox="0 0 24 24">
|
||||
<path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833
|
||||
c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"/></symbol>
|
||||
<symbol id="icon-goodreads" viewBox="0 0 24 24">
|
||||
<path d="M17.3,17.5c-0.2,0.8-0.5,1.4-1,1.9c-0.4,0.5-1,0.9-1.7,1.2C13.9,20.9,13.1,21,12,21c-0.6,0-1.3-0.1-1.9-0.2 c-0.6-0.1-1.1-0.4-1.6-0.7c-0.5-0.3-0.9-0.7-1.2-1.2c-0.3-0.5-0.5-1.1-0.5-1.7h1.5c0.1,0.5,0.2,0.9,0.5,1.2 c0.2,0.3,0.5,0.6,0.9,0.8c0.3,0.2,0.7,0.3,1.1,0.4c0.4,0.1,0.8,0.1,1.2,0.1c1.4,0,2.5-0.4,3.1-1.2c0.6-0.8,1-2,1-3.5v-1.7h0 c-0.4,0.8-0.9,1.4-1.6,1.9c-0.7,0.5-1.5,0.7-2.4,0.7c-1,0-1.9-0.2-2.6-0.5C8.7,15,8.1,14.5,7.7,14c-0.5-0.6-0.8-1.3-1-2.1 c-0.2-0.8-0.3-1.6-0.3-2.5c0-0.9,0.1-1.7,0.4-2.5c0.3-0.8,0.6-1.5,1.1-2c0.5-0.6,1.1-1,1.8-1.4C10.3,3.2,11.1,3,12,3 c0.5,0,0.9,0.1,1.3,0.2c0.4,0.1,0.8,0.3,1.1,0.5c0.3,0.2,0.6,0.5,0.9,0.8c0.3,0.3,0.5,0.6,0.6,1h0V3.4h1.5V15 C17.6,15.9,17.5,16.7,17.3,17.5z M13.8,14.1c0.5-0.3,0.9-0.7,1.3-1.1c0.3-0.5,0.6-1,0.8-1.6c0.2-0.6,0.3-1.2,0.3-1.9 c0-0.6-0.1-1.2-0.2-1.9c-0.1-0.6-0.4-1.2-0.7-1.7c-0.3-0.5-0.7-0.9-1.3-1.2c-0.5-0.3-1.1-0.5-1.9-0.5s-1.4,0.2-1.9,0.5 c-0.5,0.3-1,0.7-1.3,1.2C8.5,6.4,8.3,7,8.1,7.6C8,8.2,7.9,8.9,7.9,9.5c0,0.6,0.1,1.3,0.2,1.9C8.3,12,8.6,12.5,8.9,13 c0.3,0.5,0.8,0.8,1.3,1.1c0.5,0.3,1.1,0.4,1.9,0.4C12.7,14.5,13.3,14.4,13.8,14.1z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-google" viewBox="0 0 24 24">
|
||||
<path d="M12.02,10.18v3.72v0.01h5.51c-0.26,1.57-1.67,4.22-5.5,4.22c-3.31,0-6.01-2.75-6.01-6.12s2.7-6.12,6.01-6.12 c1.87,0,3.13,0.8,3.85,1.48l2.84-2.76C16.99,2.99,14.73,2,12.03,2c-5.52,0-10,4.48-10,10s4.48,10,10,10c5.77,0,9.6-4.06,9.6-9.77 c0-0.83-0.11-1.42-0.25-2.05H12.02z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-instagram" viewBox="0 0 24 24">
|
||||
<path d="M12,4.622c2.403,0,2.688,0.009,3.637,0.052c0.877,0.04,1.354,0.187,1.671,0.31c0.42,0.163,0.72,0.358,1.035,0.673 c0.315,0.315,0.51,0.615,0.673,1.035c0.123,0.317,0.27,0.794,0.31,1.671c0.043,0.949,0.052,1.234,0.052,3.637 s-0.009,2.688-0.052,3.637c-0.04,0.877-0.187,1.354-0.31,1.671c-0.163,0.42-0.358,0.72-0.673,1.035 c-0.315,0.315-0.615,0.51-1.035,0.673c-0.317,0.123-0.794,0.27-1.671,0.31c-0.949,0.043-1.233,0.052-3.637,0.052 s-2.688-0.009-3.637-0.052c-0.877-0.04-1.354-0.187-1.671-0.31c-0.42-0.163-0.72-0.358-1.035-0.673 c-0.315-0.315-0.51-0.615-0.673-1.035c-0.123-0.317-0.27-0.794-0.31-1.671C4.631,14.688,4.622,14.403,4.622,12 s0.009-2.688,0.052-3.637c0.04-0.877,0.187-1.354,0.31-1.671c0.163-0.42,0.358-0.72,0.673-1.035 c0.315-0.315,0.615-0.51,1.035-0.673c0.317-0.123,0.794-0.27,1.671-0.31C9.312,4.631,9.597,4.622,12,4.622 M12,3 C9.556,3,9.249,3.01,8.289,3.054C7.331,3.098,6.677,3.25,6.105,3.472C5.513,3.702,5.011,4.01,4.511,4.511 c-0.5,0.5-0.808,1.002-1.038,1.594C3.25,6.677,3.098,7.331,3.054,8.289C3.01,9.249,3,9.556,3,12c0,2.444,0.01,2.751,0.054,3.711 c0.044,0.958,0.196,1.612,0.418,2.185c0.23,0.592,0.538,1.094,1.038,1.594c0.5,0.5,1.002,0.808,1.594,1.038 c0.572,0.222,1.227,0.375,2.185,0.418C9.249,20.99,9.556,21,12,21s2.751-0.01,3.711-0.054c0.958-0.044,1.612-0.196,2.185-0.418 c0.592-0.23,1.094-0.538,1.594-1.038c0.5-0.5,0.808-1.002,1.038-1.594c0.222-0.572,0.375-1.227,0.418-2.185 C20.99,14.751,21,14.444,21,12s-0.01-2.751-0.054-3.711c-0.044-0.958-0.196-1.612-0.418-2.185c-0.23-0.592-0.538-1.094-1.038-1.594 c-0.5-0.5-1.002-0.808-1.594-1.038c-0.572-0.222-1.227-0.375-2.185-0.418C14.751,3.01,14.444,3,12,3L12,3z M12,7.378 c-2.552,0-4.622,2.069-4.622,4.622S9.448,16.622,12,16.622s4.622-2.069,4.622-4.622S14.552,7.378,12,7.378z M12,15 c-1.657,0-3-1.343-3-3s1.343-3,3-3s3,1.343,3,3S13.657,15,12,15z M16.804,6.116c-0.596,0-1.08,0.484-1.08,1.08 s0.484,1.08,1.08,1.08c0.596,0,1.08-0.484,1.08-1.08S17.401,6.116,16.804,6.116z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-linkedin" viewBox="0 0 24 24">
|
||||
<path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-mail" viewBox="0 0 24 24">
|
||||
<path d="M20,4H4C2.895,4,2,4.895,2,6v12c0,1.105,0.895,2,2,2h16c1.105,0,2-0.895,2-2V6C22,4.895,21.105,4,20,4z M20,8.236l-8,4.882 L4,8.236V6h16V8.236z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-mastodon" viewBox="0 0 24 24">
|
||||
<path style="fill-rule:evenodd" d="M20.617 13.92c-.265 1.36-2.37 2.85-4.788 3.14-1.262.15-2.503.288-3.827.228-2.165-.1-3.873-.517-3.873-.517 0 .212.013.412.04.6.28 2.136 2.118 2.264 3.858 2.324 1.756.06 3.32-.433 3.32-.433l.072 1.59s-1.228.658-3.417.78c-1.207.066-2.705-.03-4.45-.493-3.785-1-4.436-5.036-4.536-9.13-.03-1.215-.01-2.36-.01-3.32 0-4.186 2.74-5.413 2.74-5.413 1.384-.635 3.757-.902 6.225-.923h.06c2.467.022 4.842.29 6.225.924 0 0 2.742 1.227 2.742 5.413 0 0 .034 3.09-.383 5.233zm-2.854-4.91v5.07h-2.008V9.16c0-1.037-.436-1.563-1.31-1.563-.964 0-1.447.624-1.447 1.86v2.692h-1.996V9.455c0-1.235-.484-1.86-1.45-1.86-.872 0-1.308.527-1.308 1.564v4.92H6.236V9.01c0-1.034.263-1.858.793-2.467.546-.61 1.26-.92 2.15-.92 1.027 0 1.805.394 2.32 1.184l.5.84.5-.84c.514-.79 1.292-1.185 2.32-1.185.888 0 1.604.312 2.15.92.53.61.793 1.434.793 2.47z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-medium" viewBox="0 0 24 24">
|
||||
<path d="M5.727 8.027a.623.623 0 0 0-.204-.527L4.02 5.687v-.273H8.69l3.614 7.926 3.175-7.926h4.457v.274l-1.285 1.234a.367.367 0 0 0-.144.36v9.066a.374.374 0 0 0 .144.363l1.258 1.234v.27h-6.324v-.27l1.3-1.265c.13-.13.13-.164.13-.36V8.988l-3.621 9.196h-.489L6.691 8.988v6.164c-.035.258.051.52.235.707l1.691 2.055v.27h-4.8v-.27l1.69-2.055a.814.814 0 0 0 .22-.707zm0 0"/>
|
||||
</symbol>
|
||||
<symbol id="icon-meetup" viewBox="0 0 24 24">
|
||||
<path d="M19.24775,14.722a3.57032,3.57032,0,0,1-2.94457,3.52073,3.61886,3.61886,0,0,1-.64652.05634c-.07314-.0008-.10187.02846-.12507.09547A2.38881,2.38881,0,0,1,13.49453,20.094a2.33092,2.33092,0,0,1-1.827-.50716.13635.13635,0,0,0-.19878-.00408,3.191,3.191,0,0,1-2.104.60248,3.26309,3.26309,0,0,1-3.00324-2.71993,2.19076,2.19076,0,0,1-.03512-.30865c-.00156-.08579-.03413-.1189-.11608-.13493a2.86421,2.86421,0,0,1-1.23189-.56111,2.945,2.945,0,0,1-1.166-2.05749,2.97484,2.97484,0,0,1,.87524-2.50774.112.112,0,0,0,.02091-.16107,2.7213,2.7213,0,0,1-.36648-1.48A2.81256,2.81256,0,0,1,6.57673,7.58838a.35764.35764,0,0,0,.28869-.22819,4.2208,4.2208,0,0,1,6.02892-1.90111.25161.25161,0,0,0,.22023.0243,3.65608,3.65608,0,0,1,3.76031.90678A3.57244,3.57244,0,0,1,17.95918,8.626a2.97339,2.97339,0,0,1,.01829.57356.10637.10637,0,0,0,.0853.12792,1.97669,1.97669,0,0,1,1.27939,1.33733,2.00266,2.00266,0,0,1-.57112,2.12652c-.05284.05166-.04168.08328-.01173.13489A3.51189,3.51189,0,0,1,19.24775,14.722Zm-6.35959-.27836a1.6984,1.6984,0,0,0,1.14556,1.61113,3.82039,3.82039,0,0,0,1.036.17935,1.46888,1.46888,0,0,0,.73509-.12255.44082.44082,0,0,0,.26057-.44274.45312.45312,0,0,0-.29211-.43375.97191.97191,0,0,0-.20678-.063c-.21326-.03806-.42754-.0701-.63973-.11215a.54787.54787,0,0,1-.50172-.60926,2.75864,2.75864,0,0,1,.1773-.901c.1763-.535.414-1.045.64183-1.55913A12.686,12.686,0,0,0,15.85,10.47863a1.58461,1.58461,0,0,0,.04861-.87208,1.04531,1.04531,0,0,0-.85432-.83981,1.60658,1.60658,0,0,0-1.23654.16594.27593.27593,0,0,1-.36286-.03413c-.085-.0747-.16594-.15379-.24918-.23055a.98682.98682,0,0,0-1.33577-.04933,6.1468,6.1468,0,0,1-.4989.41615.47762.47762,0,0,1-.51535.03566c-.17448-.09307-.35512-.175-.53531-.25665a1.74949,1.74949,0,0,0-.56476-.2016,1.69943,1.69943,0,0,0-1.61654.91787,8.05815,8.05815,0,0,0-.32952.80126c-.45471,1.2557-.82507,2.53825-1.20838,3.81639a1.24151,1.24151,0,0,0,.51532,1.44389,1.42659,1.42659,0,0,0,1.22008.17166,1.09728,1.09728,0,0,0,.66994-.69764c.44145-1.04111.839-2.09989,1.25981-3.14926.11581-.28876.22792-.57874.35078-.86438a.44548.44548,0,0,1,.69189-.19539.50521.50521,0,0,1,.15044.43836,1.75625,1.75625,0,0,1-.14731.50453c-.27379.69219-.55265,1.38236-.82766,2.074a2.0836,2.0836,0,0,0-.14038.42876.50719.50719,0,0,0,.27082.57722.87236.87236,0,0,0,.66145.02739.99137.99137,0,0,0,.53406-.532q.61571-1.20914,1.228-2.42031.28423-.55863.57585-1.1133a.87189.87189,0,0,1,.29055-.35253.34987.34987,0,0,1,.37634-.01265.30291.30291,0,0,1,.12434.31459.56716.56716,0,0,1-.04655.1915c-.05318.12739-.10286.25669-.16183.38156-.34118.71775-.68754,1.43273-1.02568,2.152A2.00213,2.00213,0,0,0,12.88816,14.44366Zm4.78568,5.28972a.88573.88573,0,0,0-1.77139.00465.8857.8857,0,0,0,1.77139-.00465Zm-14.83838-7.296a.84329.84329,0,1,0,.00827-1.68655.8433.8433,0,0,0-.00827,1.68655Zm10.366-9.43673a.83506.83506,0,1,0-.0091,1.67.83505.83505,0,0,0,.0091-1.67Zm6.85014,5.22a.71651.71651,0,0,0-1.433.0093.71656.71656,0,0,0,1.433-.0093ZM5.37528,6.17908A.63823.63823,0,1,0,6.015,5.54483.62292.62292,0,0,0,5.37528,6.17908Zm6.68214,14.80843a.54949.54949,0,1,0-.55052.541A.54556.54556,0,0,0,12.05742,20.98752Zm8.53235-8.49689a.54777.54777,0,0,0-.54027.54023.53327.53327,0,0,0,.532.52293.51548.51548,0,0,0,.53272-.5237A.53187.53187,0,0,0,20.58977,12.49063ZM7.82846,2.4715a.44927.44927,0,1,0,.44484.44766A.43821.43821,0,0,0,7.82846,2.4715Zm13.775,7.60492a.41186.41186,0,0,0-.40065.39623.40178.40178,0,0,0,.40168.40168A.38994.38994,0,0,0,22,10.48172.39946.39946,0,0,0,21.60349,10.07642ZM5.79193,17.96207a.40469.40469,0,0,0-.397-.39646.399.399,0,0,0-.396.405.39234.39234,0,0,0,.39939.389A.39857.39857,0,0,0,5.79193,17.96207Z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-nextdoor" viewBox="0 0 24 24">
|
||||
<path d="M11.8615 0.651877C6.11188 0.714092 1.22843 5.12326 0.698031 10.9732C0.132369 17.213 4.73317 22.7304 10.9732 23.2962C17.213 23.8619 22.7304 19.2611 23.2962 13.0211C23.8619 6.78111 19.2611 1.26369 13.0211 0.69803C12.6356 0.663073 12.2486 0.647668 11.8615 0.651877ZM12.5886 7.09625C15.2249 7.09625 17.2615 8.96861 17.2615 11.3538V16.3385C17.2615 16.4649 17.1572 16.5692 17.0308 16.5692H14.9365C14.8755 16.5684 14.8173 16.5438 14.7742 16.5007C14.7311 16.4576 14.7065 16.3994 14.7057 16.3385V11.7C14.7057 10.6698 13.9102 9.49606 12.5884 9.49606C11.2093 9.49606 10.4712 10.6698 10.4712 11.7V16.3385C10.4712 16.4649 10.3669 16.5692 10.2404 16.5692H8.14615C8.02062 16.5692 7.92111 16.464 7.92111 16.3385V11.8442C7.92111 11.7076 7.82345 11.5924 7.69034 11.5615C5.26634 11.0206 4.89988 9.66277 4.85188 7.66154C4.85095 7.60025 4.87809 7.53785 4.92111 7.49428C4.96412 7.45052 5.02135 7.42505 5.08265 7.42505L7.24043 7.43649C7.36228 7.43834 7.45957 7.53415 7.46529 7.65581C7.48929 8.47551 7.54615 9.39231 8.28462 9.39231C8.43785 9.39231 8.55102 9.17464 8.61932 9.07495C9.43348 7.87864 10.8864 7.09625 12.5886 7.09625Z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-patreon" viewBox="0 0 24 24">
|
||||
<path d="M20 7.40755C19.9969 5.10922 18.2543 3.22555 16.2097 2.54588C13.6708 1.70188 10.3222 1.82421 7.89775 2.99921C4.95932 4.42355 4.03626 7.54355 4.00186 10.6552C3.97363 13.2136 4.2222 19.9517 7.92225 19.9997C10.6715 20.0356 11.0809 16.3967 12.3529 14.6442C13.258 13.3974 14.4233 13.0452 15.8578 12.6806C18.3233 12.0537 20.0036 10.0551 20 7.40755Z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-pinterest" viewBox="0 0 24 24">
|
||||
<path d="M12.289,2C6.617,2,3.606,5.648,3.606,9.622c0,1.846,1.025,4.146,2.666,4.878c0.25,0.111,0.381,0.063,0.439-0.169 c0.044-0.175,0.267-1.029,0.365-1.428c0.032-0.128,0.017-0.237-0.091-0.362C6.445,11.911,6.01,10.75,6.01,9.668 c0-2.777,2.194-5.464,5.933-5.464c3.23,0,5.49,2.108,5.49,5.122c0,3.407-1.794,5.768-4.13,5.768c-1.291,0-2.257-1.021-1.948-2.277 c0.372-1.495,1.089-3.112,1.089-4.191c0-0.967-0.542-1.775-1.663-1.775c-1.319,0-2.379,1.309-2.379,3.059 c0,1.115,0.394,1.869,0.394,1.869s-1.302,5.279-1.54,6.261c-0.405,1.666,0.053,4.368,0.094,4.604 c0.021,0.126,0.167,0.169,0.25,0.063c0.129-0.165,1.699-2.419,2.142-4.051c0.158-0.59,0.817-2.995,0.817-2.995 c0.43,0.784,1.681,1.446,3.013,1.446c3.963,0,6.822-3.494,6.822-7.833C20.394,5.112,16.849,2,12.289,2"/>
|
||||
</symbol>
|
||||
<symbol id="icon-pocket-casts" viewBox="0 0 24 24">
|
||||
<path d="M12 2C17.523 2 22 6.47704 22 12C22 17.523 17.523 22 12 22C6.47704 22 2 17.523 2 12C2 6.47704 6.47704 2 12 2ZM12 4.22266C7.70445 4.22266 4.22266 7.70445 4.22266 12C4.22269 16.2955 7.70447 19.7773 12 19.7773V17.833C8.77836 17.833 6.16702 15.2216 6.16699 12C6.16699 8.77834 8.77834 6.16699 12 6.16699C15.2217 6.16699 17.833 8.77834 17.833 12H19.7773C19.7773 7.70445 16.2955 4.22266 12 4.22266ZM12 7.33301C9.42267 7.33301 7.33301 9.42267 7.33301 12C7.33304 14.5773 9.42269 16.667 12 16.667V14.9697C10.3599 14.9697 9.0303 13.6401 9.03027 12C9.03027 10.3599 10.3599 9.03027 12 9.03027C13.6401 9.03028 14.9697 10.3599 14.9697 12H16.667C16.667 9.42267 14.5773 7.33301 12 7.33301Z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-ravelry" viewBox="0 0 23 20">
|
||||
<path d="M12.098 19.34a.25.25 0 01-.118-.043 13.986 13.986 0 01-.394-.258c-.164-.11-.477-.352-.934-.723-.46-.375-.882-.761-1.27-1.168-.39-.406-.796-.925-1.218-1.562a8.521 8.521 0 01-.976-1.926c-.125-.023-.758-.16-1.907-.414A8.785 8.785 0 007.84 17.29a8.152 8.152 0 004.258 2.05zm-6.98-6.762l1.831.313A13.424 13.424 0 016.5 11.02a16.216 16.216 0 01-.207-1.622l-.043-.593c-.61.61-1.047 1.445-1.316 2.5.035.484.097.91.183 1.273zm1.198-6.797a9.064 9.064 0 00-.84 1.653c.32-.344.59-.598.81-.758zm15.649 4.844a8.8 8.8 0 00-.676-3.426 8.85 8.85 0 00-1.824-2.812 8.614 8.614 0 00-2.727-1.883 8.115 8.115 0 00-3.312-.695 8.131 8.131 0 00-3.059.586A8.412 8.412 0 007.754 4.05c-.219.433-.383 1.027-.488 1.785a5.407 5.407 0 011.554-.93 7.481 7.481 0 011.727-.48 16.642 16.642 0 011.558-.153c.489-.02.883-.015 1.18.012l.438.035c.238.008.43.063.574.172a.66.66 0 01.27.367c.03.141.054.278.07.414a.8.8 0 01-.012.317 12.781 12.781 0 00-2.477-.004 7.093 7.093 0 00-1.992.484 9.6 9.6 0 00-1.554.801A12.46 12.46 0 007.176 7.97c.031.27.07.613.125 1.031.054.422.183 1.082.386 1.988.204.903.43 1.57.676 2.004.895.043 1.793-.012 2.696-.164.902-.152 1.683-.351 2.336-.598a20.681 20.681 0 001.77-.746c.526-.254.925-.472 1.19-.66l.407-.265c.156-.121.3-.196.43-.23a.367.367 0 01.331.058c.094.07.157.199.184.383.102.722-.039 1.171-.426 1.351-1.508.723-3.203 1.219-5.086 1.496-.976.149-2.129.207-3.449.176a7.673 7.673 0 001.195 1.973c.504.597 1 1.07 1.493 1.418.496.343.968.636 1.421.878.454.243.825.407 1.106.489l.426.133c1.039.171 1.992.113 2.863-.168 1.414-.739 2.555-1.813 3.418-3.227.867-1.414 1.297-2.969 1.297-4.664zm.805-.414c-.102 1.004-.247 1.793-.434 2.367-.508 1.547-1.168 2.836-1.977 3.867-.808 1.032-1.964 1.973-3.468 2.828-.348.247-.645.41-.895.493-.52.195-1.113.254-1.773.18-.262.019-.528.03-.797.03-2.055 0-3.883-.64-5.492-1.93-1.61-1.288-2.68-2.929-3.22-4.933-.007 0-.019 0-.042-.004-.024-.004-.04-.007-.055-.007-.043.375-.035.793.028 1.257.062.465.156.891.285 1.282.125.39.254.757.39 1.093.133.34.25.606.344.801l.152.29c.059.09.254.394.586.913a4.327 4.327 0 01-1.355-1.187 5.669 5.669 0 01-.856-1.563 14.087 14.087 0 01-.43-1.531 9.012 9.012 0 01-.19-1.2l-.02-.468c-.035-.016-.16-.059-.367-.137-.207-.078-.383-.148-.528-.203-.144-.054-.336-.133-.578-.226a9.221 9.221 0 01-.625-.282c-.176-.09-.36-.183-.543-.285-.187-.097-.34-.199-.465-.3a1.27 1.27 0 01-.27-.286c.138.075.321.172.548.285.23.118.64.286 1.23.508.594.223 1.121.364 1.586.426l.023-.36c.079-1.109.418-2.187 1.024-3.234A9.226 9.226 0 016.5 4.621c.203-.855.5-1.652.883-2.39.11-.208.226-.376.347-.5.125-.13.305-.247.536-.36 1.148-.55 2.25-.937 3.304-1.16A9.935 9.935 0 0114.86.09c1.136.14 2.25.5 3.34 1.082 1.593.855 2.804 2.105 3.624 3.75.82 1.644 1.137 3.406.946 5.289zm0 0"/>
|
||||
</symbol>
|
||||
<symbol id="icon-reddit" viewBox="0 0 24 24">
|
||||
<path d="M12 2C17.5227 2 22 6.47734 22 12C22 17.5227 17.5227 22 12 22H3.44824C2.914 21.9998 2.64634 21.3537 3.02441 20.9756L4.92871 19.0713C3.11934 17.2619 2 14.7617 2 12C2 6.47734 6.47734 2 12 2ZM15.6562 4.66602C14.8516 4.66602 14.1807 5.23652 14.0244 5.99512C12.6768 6.13965 11.624 7.28281 11.624 8.66797V8.67578C10.1585 8.7375 8.82028 9.15496 7.75781 9.81348C7.36328 9.50801 6.86758 9.32617 6.33008 9.32617C5.04039 9.32628 3.99522 10.3714 3.99512 11.6611C3.99512 12.5971 4.54531 13.4037 5.33984 13.7764C5.41733 16.4872 8.37138 18.668 12.0049 18.668C15.6383 18.6678 18.5955 16.4847 18.6689 13.7715C19.4572 13.3965 20.0029 12.5926 20.0029 11.6621C20.0029 10.3723 18.9577 9.32725 17.668 9.32715C17.1329 9.32715 16.6398 9.50748 16.2461 9.81055C15.1743 9.14732 13.8211 8.73033 12.3408 8.6748V8.66797C12.341 7.67597 13.0781 6.85292 14.0342 6.71777L14.0723 6.85156C14.2906 7.51749 14.9172 7.99902 15.6562 7.99902C16.5765 7.99892 17.3223 7.25228 17.3223 6.33203C17.3221 5.41196 16.5763 4.66612 15.6562 4.66602ZM12.0049 14.9902C12.8165 14.9902 13.5931 15.0299 14.3125 15.1025C14.4349 15.1151 14.5132 15.2425 14.4658 15.3564C14.0635 16.3181 13.1133 16.994 12.0049 16.9941C10.8963 16.9941 9.94707 16.3182 9.54395 15.3564C9.49636 15.2425 9.57385 15.1153 9.69629 15.1025C10.415 15.0299 11.1932 14.9902 12.0049 14.9902ZM8.91895 11.6465C9.57275 11.6465 10.0731 12.333 10.0342 13.1797C9.99512 14.0264 9.50703 14.3348 8.85254 14.335C8.1979 14.335 7.62509 13.9903 7.66406 13.1436C7.70312 12.2968 8.26521 11.6467 8.91895 11.6465ZM15.0908 11.6465C15.7453 11.6467 16.3074 12.2968 16.3457 13.1436C16.3847 13.9903 15.8111 14.335 15.1572 14.335C14.5035 14.3348 14.0146 14.0272 13.9756 13.1797C13.9367 12.333 14.4362 11.6465 15.0908 11.6465Z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-slideshare" viewBox="0 0 24 24">
|
||||
<path d="M11.738,10.232a2.142,2.142,0,0,1-.721,1.619,2.556,2.556,0,0,1-3.464,0,2.183,2.183,0,0,1,0-3.243,2.572,2.572,0,0,1,3.464,0A2.136,2.136,0,0,1,11.738,10.232Zm5.7,0a2.15,2.15,0,0,1-.715,1.619,2.563,2.563,0,0,1-3.469,0,2.183,2.183,0,0,1,0-3.243,2.58,2.58,0,0,1,3.469,0A2.144,2.144,0,0,1,17.439,10.232Zm2.555,2.045V4.7a2.128,2.128,0,0,0-.363-1.4,1.614,1.614,0,0,0-1.261-.415H5.742a1.656,1.656,0,0,0-1.278.386A2.246,2.246,0,0,0,4.129,4.7v7.643a8.212,8.212,0,0,0,1,.454q.516.193.92.318a6.847,6.847,0,0,0,.92.21q.516.085.806.125a6.615,6.615,0,0,0,.795.045l.665.006q.16,0,.642-.023t.506-.023a1.438,1.438,0,0,1,1.079.307,1.134,1.134,0,0,0,.114.1,7.215,7.215,0,0,0,.693.579q.079-1.033,1.34-.988.057,0,.415.017l.488.023q.13.006.517.011t.6-.011l.619-.051a5.419,5.419,0,0,0,.693-.1l.7-.153a5.353,5.353,0,0,0,.761-.221q.345-.131.766-.307a8.727,8.727,0,0,0,.818-.392Zm1.851-.057a10.4,10.4,0,0,1-4.225,2.862,6.5,6.5,0,0,1-.261,5.281,3.524,3.524,0,0,1-2.078,1.681,2.452,2.452,0,0,1-2.067-.17,1.915,1.915,0,0,1-.931-1.863l-.011-3.7V16.3l-.279-.068q-.188-.045-.267-.057l-.011,3.839a1.9,1.9,0,0,1-.943,1.863,2.481,2.481,0,0,1-2.078.17,3.519,3.519,0,0,1-2.067-1.7,6.546,6.546,0,0,1-.25-5.258A10.4,10.4,0,0,1,2.152,12.22a.56.56,0,0,1-.045-.715q.238-.3.681.011l.125.079a.767.767,0,0,1,.125.091V3.8a1.987,1.987,0,0,1,.534-1.4,1.7,1.7,0,0,1,1.295-.579H19.141a1.7,1.7,0,0,1,1.295.579,1.985,1.985,0,0,1,.534,1.4v7.882l.238-.17q.443-.307.681-.011a.56.56,0,0,1-.045.715Z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-sms" viewBox="0 0 24 24">
|
||||
<path d="M17.696 4C20.069 4 22 5.973 22 8.398v4.357c0 2.04-1.368 3.783-3.261 4.266v4.427l-5.234-4.295h-7.2C3.93 17.153 2 15.18 2 12.755V8.398C2 5.973 3.931 4 6.304 4h11.392ZM7.028 8.515c-.98 0-1.66.562-1.66 1.349-.009.497.322.91.985 1.178l.39.142c.242.097.305.171.305.297 0 .162-.131.251-.442.251s-.76-.135-1.004-.284l-.112.046-.215.868c.359.258.832.364 1.33.364 1.104 0 1.764-.523 1.764-1.333-.008-.574-.305-.956-.954-1.216l-.393-.146c-.266-.108-.341-.181-.341-.287 0-.152.131-.243.387-.243.274 0 .587.093.808.214l.109-.047.214-.837c-.315-.224-.741-.316-1.171-.316Zm10.302 0c-.98 0-1.66.562-1.66 1.349-.008.497.322.91.985 1.178l.39.142c.243.097.305.171.305.297 0 .162-.13.251-.442.251-.311 0-.76-.135-1.004-.284l-.112.046-.215.868c.359.258.832.364 1.33.364 1.104 0 1.764-.523 1.764-1.333-.008-.574-.305-.956-.954-1.216l-.393-.146c-.266-.108-.341-.181-.341-.287 0-.152.131-.243.387-.243.274 0 .587.093.808.214l.109-.047.214-.837c-.316-.224-.741-.316-1.171-.316Zm-3.733 0c-.297 0-.55.066-.78.202l-.144.098a1.823 1.823 0 0 0-.264.247l-.078.095-.027-.077c-.15-.34-.55-.565-1.033-.565l-.169.007a1.363 1.363 0 0 0-.896.42l-.08.09-.038-.363-.075-.067H8.994l-.075.079.024.634c.005.2.008.397.008.604v2.652l.075.075h1.178l.075-.075v-2.269c0-.113.012-.202.042-.274.083-.23.262-.392.496-.392.314 0 .483.267.483.753v2.182l.075.075h1.179l.075-.075v-2.277c0-.097.016-.213.043-.285.077-.224.26-.373.486-.373.33 0 .5.272.5.817v2.118l.074.075h1.179l.075-.075v-2.293c0-1.131-.537-1.763-1.39-1.763Z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-snapchat" viewBox="0 0 24 24">
|
||||
<path d="M12.065,2a5.526,5.526,0,0,1,3.132.892A5.854,5.854,0,0,1,17.326,5.4a5.821,5.821,0,0,1,.351,2.33q0,.612-.117,2.487a.809.809,0,0,0,.365.091,1.93,1.93,0,0,0,.664-.176,1.93,1.93,0,0,1,.664-.176,1.3,1.3,0,0,1,.729.234.7.7,0,0,1,.351.6.839.839,0,0,1-.41.7,2.732,2.732,0,0,1-.9.41,3.192,3.192,0,0,0-.9.378.728.728,0,0,0-.41.618,1.575,1.575,0,0,0,.156.56,6.9,6.9,0,0,0,1.334,1.953,5.6,5.6,0,0,0,1.881,1.315,5.875,5.875,0,0,0,1.042.3.42.42,0,0,1,.365.456q0,.911-2.852,1.341a1.379,1.379,0,0,0-.143.507,1.8,1.8,0,0,1-.182.605.451.451,0,0,1-.429.241,5.878,5.878,0,0,1-.807-.085,5.917,5.917,0,0,0-.833-.085,4.217,4.217,0,0,0-.807.065,2.42,2.42,0,0,0-.82.293,6.682,6.682,0,0,0-.755.5q-.351.267-.755.527a3.886,3.886,0,0,1-.989.436A4.471,4.471,0,0,1,11.831,22a4.307,4.307,0,0,1-1.256-.176,3.784,3.784,0,0,1-.976-.436q-.4-.26-.749-.527a6.682,6.682,0,0,0-.755-.5,2.422,2.422,0,0,0-.807-.293,4.432,4.432,0,0,0-.82-.065,5.089,5.089,0,0,0-.853.1,5,5,0,0,1-.762.1.474.474,0,0,1-.456-.241,1.819,1.819,0,0,1-.182-.618,1.411,1.411,0,0,0-.143-.521q-2.852-.429-2.852-1.341a.42.42,0,0,1,.365-.456,5.793,5.793,0,0,0,1.042-.3,5.524,5.524,0,0,0,1.881-1.315,6.789,6.789,0,0,0,1.334-1.953A1.575,1.575,0,0,0,6,12.9a.728.728,0,0,0-.41-.618,3.323,3.323,0,0,0-.9-.384,2.912,2.912,0,0,1-.9-.41.814.814,0,0,1-.41-.684.71.71,0,0,1,.338-.593,1.208,1.208,0,0,1,.716-.241,1.976,1.976,0,0,1,.625.169,2.008,2.008,0,0,0,.69.169.919.919,0,0,0,.416-.091q-.117-1.849-.117-2.474A5.861,5.861,0,0,1,6.385,5.4,5.516,5.516,0,0,1,8.625,2.819,7.075,7.075,0,0,1,12.062,2Z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-soundcloud" viewBox="0 0 24 24">
|
||||
<path d="M8.9,16.1L9,14L8.9,9.5c0-0.1,0-0.1-0.1-0.1c0,0-0.1-0.1-0.1-0.1c-0.1,0-0.1,0-0.1,0.1c0,0-0.1,0.1-0.1,0.1L8.3,14l0.1,2.1 c0,0.1,0,0.1,0.1,0.1c0,0,0.1,0.1,0.1,0.1C8.8,16.3,8.9,16.3,8.9,16.1z M11.4,15.9l0.1-1.8L11.4,9c0-0.1,0-0.2-0.1-0.2 c0,0-0.1,0-0.1,0s-0.1,0-0.1,0c-0.1,0-0.1,0.1-0.1,0.2l0,0.1l-0.1,5c0,0,0,0.7,0.1,2v0c0,0.1,0,0.1,0.1,0.1c0.1,0.1,0.1,0.1,0.2,0.1 c0.1,0,0.1,0,0.2-0.1c0.1,0,0.1-0.1,0.1-0.2L11.4,15.9z M2.4,12.9L2.5,14l-0.2,1.1c0,0.1,0,0.1-0.1,0.1c0,0-0.1,0-0.1-0.1L2.1,14 l0.1-1.1C2.2,12.9,2.3,12.9,2.4,12.9C2.3,12.9,2.4,12.9,2.4,12.9z M3.1,12.2L3.3,14l-0.2,1.8c0,0.1,0,0.1-0.1,0.1 c-0.1,0-0.1,0-0.1-0.1L2.8,14L3,12.2C3,12.2,3,12.2,3.1,12.2C3.1,12.2,3.1,12.2,3.1,12.2z M3.9,11.9L4.1,14l-0.2,2.1 c0,0.1,0,0.1-0.1,0.1c-0.1,0-0.1,0-0.1-0.1L3.5,14l0.2-2.1c0-0.1,0-0.1,0.1-0.1C3.9,11.8,3.9,11.8,3.9,11.9z M4.7,11.9L4.9,14 l-0.2,2.1c0,0.1-0.1,0.1-0.1,0.1c-0.1,0-0.1,0-0.1-0.1L4.3,14l0.2-2.2c0-0.1,0-0.1,0.1-0.1C4.7,11.7,4.7,11.8,4.7,11.9z M5.6,12 l0.2,2l-0.2,2.1c0,0.1-0.1,0.1-0.1,0.1c0,0-0.1,0-0.1,0c0,0,0-0.1,0-0.1L5.1,14l0.2-2c0,0,0-0.1,0-0.1s0.1,0,0.1,0 C5.5,11.9,5.5,11.9,5.6,12L5.6,12z M6.4,10.7L6.6,14l-0.2,2.1c0,0,0,0.1,0,0.1c0,0-0.1,0-0.1,0c-0.1,0-0.1-0.1-0.2-0.2L5.9,14 l0.2-3.3c0-0.1,0.1-0.2,0.2-0.2c0,0,0.1,0,0.1,0C6.4,10.7,6.4,10.7,6.4,10.7z M7.2,10l0.2,4.1l-0.2,2.1c0,0,0,0.1,0,0.1 c0,0-0.1,0-0.1,0c-0.1,0-0.2-0.1-0.2-0.2l-0.1-2.1L6.8,10c0-0.1,0.1-0.2,0.2-0.2c0,0,0.1,0,0.1,0S7.2,9.9,7.2,10z M8,9.6L8.2,14 L8,16.1c0,0.1-0.1,0.2-0.2,0.2c-0.1,0-0.2-0.1-0.2-0.2L7.5,14l0.1-4.4c0-0.1,0-0.1,0.1-0.1c0,0,0.1-0.1,0.1-0.1c0.1,0,0.1,0,0.1,0.1 C8,9.6,8,9.6,8,9.6z M11.4,16.1L11.4,16.1L11.4,16.1z M9.7,9.6L9.8,14l-0.1,2.1c0,0.1,0,0.1-0.1,0.2s-0.1,0.1-0.2,0.1 c-0.1,0-0.1,0-0.1-0.1s-0.1-0.1-0.1-0.2L9.2,14l0.1-4.4c0-0.1,0-0.1,0.1-0.2s0.1-0.1,0.2-0.1c0.1,0,0.1,0,0.2,0.1S9.7,9.5,9.7,9.6 L9.7,9.6z M10.6,9.8l0.1,4.3l-0.1,2c0,0.1,0,0.1-0.1,0.2c0,0-0.1,0.1-0.2,0.1c-0.1,0-0.1,0-0.2-0.1c0,0-0.1-0.1-0.1-0.2L10,14 l0.1-4.3c0-0.1,0-0.1,0.1-0.2c0,0,0.1-0.1,0.2-0.1c0.1,0,0.1,0,0.2,0.1S10.6,9.7,10.6,9.8z M12.4,14l-0.1,2c0,0.1,0,0.1-0.1,0.2 c-0.1,0.1-0.1,0.1-0.2,0.1c-0.1,0-0.1,0-0.2-0.1c-0.1-0.1-0.1-0.1-0.1-0.2l-0.1-1l-0.1-1l0.1-5.5v0c0-0.1,0-0.2,0.1-0.2 c0.1,0,0.1-0.1,0.2-0.1c0,0,0.1,0,0.1,0c0.1,0,0.1,0.1,0.1,0.2L12.4,14z M22.1,13.9c0,0.7-0.2,1.3-0.7,1.7c-0.5,0.5-1.1,0.7-1.7,0.7 h-6.8c-0.1,0-0.1,0-0.2-0.1c-0.1-0.1-0.1-0.1-0.1-0.2V8.2c0-0.1,0.1-0.2,0.2-0.3c0.5-0.2,1-0.3,1.6-0.3c1.1,0,2.1,0.4,2.9,1.1 c0.8,0.8,1.3,1.7,1.4,2.8c0.3-0.1,0.6-0.2,1-0.2c0.7,0,1.3,0.2,1.7,0.7C21.8,12.6,22.1,13.2,22.1,13.9L22.1,13.9z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-spotify" viewBox="0 0 24 24">
|
||||
<path d="M12,2C6.477,2,2,6.477,2,12c0,5.523,4.477,10,10,10c5.523,0,10-4.477,10-10C22,6.477,17.523,2,12,2 M16.586,16.424 c-0.18,0.295-0.563,0.387-0.857,0.207c-2.348-1.435-5.304-1.76-8.785-0.964c-0.335,0.077-0.67-0.133-0.746-0.469 c-0.077-0.335,0.132-0.67,0.469-0.746c3.809-0.871,7.077-0.496,9.713,1.115C16.673,15.746,16.766,16.13,16.586,16.424 M17.81,13.7 c-0.226,0.367-0.706,0.482-1.072,0.257c-2.687-1.652-6.785-2.131-9.965-1.166C6.36,12.917,5.925,12.684,5.8,12.273 C5.675,11.86,5.908,11.425,6.32,11.3c3.632-1.102,8.147-0.568,11.234,1.328C17.92,12.854,18.035,13.335,17.81,13.7 M17.915,10.865 c-3.223-1.914-8.54-2.09-11.618-1.156C5.804,9.859,5.281,9.58,5.131,9.086C4.982,8.591,5.26,8.069,5.755,7.919 c3.532-1.072,9.404-0.865,13.115,1.338c0.445,0.264,0.59,0.838,0.327,1.282C18.933,10.983,18.359,11.129,17.915,10.865"/>
|
||||
</symbol>
|
||||
<symbol id="icon-stackoverflow" viewBox="0 0 24 24">
|
||||
<path d="m 17.817128,20.228605 v -5.337217 h 1.771431 V 22 H 3.6 v -7.108612 h 1.771401 v 5.337217 z" />
|
||||
<path d="m 7.3267845,14.385359 8.6959295,1.817316 0.368168,-1.748385 -8.6959318,-1.817319 z m 1.1503197,-4.140944 8.0517968,3.749872 0.73617,-1.610385 -8.0518344,-3.7728517 z m 2.2315078,-3.9569154 6.832405,5.6822664 1.12738,-1.357316 -6.832576,-5.6822636 z m 4.417,-4.2099019 -1.426448,1.0581864 5.291191,7.1316119 1.426412,-1.0582745 z M 7.1427296,18.434189 h 8.8799844 v -1.7713 H 7.1427296 Z" />
|
||||
<path d="m 17.817128,20.228605 v -5.337217 h 1.771431 V 22 H 3.6 v -7.108612 h 1.771401 v 5.337217 z" />
|
||||
<path d="m 7.3267845,14.385359 8.6959295,1.817316 0.368168,-1.748385 -8.6959318,-1.817319 z m 1.1503197,-4.140944 8.0517968,3.749872 0.73617,-1.610385 -8.0518344,-3.7728517 z m 2.2315078,-3.9569154 6.832405,5.6822664 1.12738,-1.357316 -6.832576,-5.6822636 z m 4.417,-4.2099019 -1.426448,1.0581864 5.291191,7.1316119 1.426412,-1.0582745 z M 7.1427296,18.434189 h 8.8799844 v -1.7713 H 7.1427296 Z" />
|
||||
</symbol>
|
||||
<symbol id="icon-strava" viewBox="0 0 24 24">
|
||||
<path d="M15.387 17.944l-2.089-4.116h-3.065L15.387 24l5.15-10.172h-3.066m-7.008-5.599l2.836 5.598h4.172L10.463 0l-7 13.828h4.169"/>
|
||||
</symbol>
|
||||
<symbol id="icon-stumbleupon" viewBox="0 0 24 24">
|
||||
<path d="M12,4.294c-2.469,0-4.471,2.002-4.471,4.471v6.353c0,0.585-0.474,1.059-1.059,1.059c-0.585,0-1.059-0.474-1.059-1.059 v-2.824H2v2.941c0,2.469,2.002,4.471,4.471,4.471c2.469,0,4.471-2.002,4.471-4.471V8.765c0-0.585,0.474-1.059,1.059-1.059 s1.059,0.474,1.059,1.059v1.294l1.412,0.647l2-0.647V8.765C16.471,6.296,14.469,4.294,12,4.294z M13.059,12.353v2.882 c0,2.469,2.002,4.471,4.471,4.471S22,17.704,22,15.235v-2.824h-3.412v2.824c0,0.585-0.474,1.059-1.059,1.059 c-0.585,0-1.059-0.474-1.059-1.059v-2.882l-2,0.647L13.059,12.353z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-telegram" viewBox="0 0 24 24">
|
||||
<path d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2zm3.08 14.757s-.25.625-.936.325l-2.541-1.949-1.63 1.486s-.127.096-.266.036c0 0-.12-.011-.27-.486-.15-.475-.911-2.972-.911-2.972L6 12.349s-.387-.137-.425-.438c-.037-.3.437-.462.437-.462l10.03-3.934s.824-.362.824.238l-1.786 9.004z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-threads" viewBox="0 0 24 24">
|
||||
<path d="M16.0671 11.1235C15.9632 11.0737 15.8583 11.0261 15.7524 10.9806C15.5671 7.56725 13.702 5.61312 10.5702 5.59312H10.5278C8.6545 5.59312 7.09663 6.39262 6.13775 7.84762L7.86012 9.02913C8.57637 7.94225 9.70062 7.71063 10.5286 7.71063H10.5573C11.5884 7.71725 12.3665 8.01713 12.8701 8.60175C13.2366 9.02738 13.4817 9.61562 13.6031 10.358C12.6889 10.2026 11.7001 10.1547 10.6431 10.2155C7.66562 10.3869 5.75138 12.1235 5.88 14.5365C5.94525 15.7605 6.555 16.8135 7.59688 17.5014C8.47775 18.0829 9.61238 18.3673 10.7915 18.3029C12.3488 18.2175 13.5704 17.6234 14.4226 16.537C15.0699 15.712 15.4792 14.6429 15.66 13.2957C16.4021 13.7436 16.9521 14.333 17.2559 15.0415C17.7724 16.2459 17.8025 18.225 16.1876 19.8385C14.7728 21.252 13.072 21.8635 10.5016 21.8824C7.6505 21.8613 5.49412 20.9469 4.09225 19.1646C2.7795 17.4958 2.101 15.0852 2.07562 12C2.101 8.91475 2.77937 6.50425 4.09225 4.83537C5.49425 3.05312 7.6505 2.13875 10.5016 2.1175C13.3735 2.13875 15.5674 3.0575 17.023 4.84837C17.7368 5.72662 18.2749 6.83087 18.6296 8.11862L20.648 7.58012C20.218 5.99512 19.5414 4.62937 18.6206 3.49662C16.7545 1.20088 14.0252 0.024375 10.5087 0H10.4946C6.98525 0.02425 4.2865 1.20525 2.4735 3.51C0.86025 5.56063 0.0280001 8.41437 0.000125051 11.9915L0 12V12.0084C0.028 15.5855 0.86025 18.4393 2.4735 20.4901C4.2865 22.7948 6.98525 23.9757 10.4946 24H10.5087C13.6287 23.9784 15.828 23.1615 17.6397 21.3514C20.0101 18.9833 19.9387 16.0149 19.1575 14.1926C18.597 12.8859 17.5284 11.8245 16.0671 11.1235ZM10.68 16.1884C9.375 16.2619 8.01925 15.6761 7.9525 14.4215C7.90288 13.4913 8.6145 12.4533 10.7601 12.3296C11.0059 12.3154 11.247 12.3085 11.4839 12.3085C12.2633 12.3085 12.9924 12.3843 13.6552 12.5291C13.408 15.6169 11.9578 16.1183 10.68 16.1884Z" />
|
||||
</symbol>
|
||||
<symbol id="icon-tiktok" viewBox="0 0 24 24">
|
||||
<path d="M12.22 2H15.64C15.64 2 15.4502 6.39351 20.3898 6.70186V10.0981C20.3898 10.0981 17.7537 10.2636 15.64 8.64957L15.6769 15.6615C15.6769 16.9151 15.3052 18.1406 14.6087 19.1829C13.9123 20.2253 12.9224 21.0377 11.7642 21.5175C10.606 21.9972 9.33162 22.1228 8.10209 21.8782C6.87257 21.6337 5.74316 21.0301 4.85669 20.1437C3.97022 19.2573 3.3665 18.1279 3.12186 16.8984C2.87723 15.6689 3.00267 14.3945 3.48233 13.2363C3.96199 12.0781 4.77432 11.0881 5.8166 10.3916C6.85888 9.69502 8.0843 9.32318 9.33791 9.32307H10.2271V12.7231V12.7954C9.64757 12.6147 9.02578 12.6217 8.45043 12.8152C7.87508 13.0088 7.37556 13.3792 7.02314 13.8734C6.67071 14.3677 6.48338 14.9606 6.48786 15.5677C6.49235 16.1747 6.68842 16.7648 7.04811 17.2538C7.40781 17.7428 7.91274 18.1057 8.49089 18.2908C9.06903 18.4758 9.69086 18.4736 10.2676 18.2843C10.8444 18.0951 11.3467 17.7285 11.7029 17.2369C12.059 16.7454 12.2508 16.1538 12.2509 15.5468L12.22 2Z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-tumblr" viewBox="0 0 24 24">
|
||||
<path d="M16.749,17.396c-0.357,0.17-1.041,0.319-1.551,0.332c-1.539,0.041-1.837-1.081-1.85-1.896V9.847h3.861V6.937h-3.847V2.039 c0,0-2.77,0-2.817,0c-0.046,0-0.127,0.041-0.138,0.144c-0.165,1.499-0.867,4.13-3.783,5.181v2.484h1.945v6.282 c0,2.151,1.587,5.206,5.775,5.135c1.413-0.024,2.982-0.616,3.329-1.126L16.749,17.396z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-twitch" viewBox="0 0 24 24">
|
||||
<path d="M16.499,8.089h-1.636v4.91h1.636V8.089z M12,8.089h-1.637v4.91H12V8.089z M4.228,3.178L3,6.451v13.092h4.499V22h2.456 l2.454-2.456h3.681L21,14.636V3.178H4.228z M19.364,13.816l-2.864,2.865H12l-2.453,2.453V16.68H5.863V4.814h13.501V13.816z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-twitter" viewBox="0 0 24 24">
|
||||
<path d="M22.23,5.924c-0.736,0.326-1.527,0.547-2.357,0.646c0.847-0.508,1.498-1.312,1.804-2.27 c-0.793,0.47-1.671,0.812-2.606,0.996C18.324,4.498,17.257,4,16.077,4c-2.266,0-4.103,1.837-4.103,4.103 c0,0.322,0.036,0.635,0.106,0.935C8.67,8.867,5.647,7.234,3.623,4.751C3.27,5.357,3.067,6.062,3.067,6.814 c0,1.424,0.724,2.679,1.825,3.415c-0.673-0.021-1.305-0.206-1.859-0.513c0,0.017,0,0.034,0,0.052c0,1.988,1.414,3.647,3.292,4.023 c-0.344,0.094-0.707,0.144-1.081,0.144c-0.264,0-0.521-0.026-0.772-0.074c0.522,1.63,2.038,2.816,3.833,2.85 c-1.404,1.1-3.174,1.756-5.096,1.756c-0.331,0-0.658-0.019-0.979-0.057c1.816,1.164,3.973,1.843,6.29,1.843 c7.547,0,11.675-6.252,11.675-11.675c0-0.178-0.004-0.355-0.012-0.531C20.985,7.47,21.68,6.747,22.23,5.924z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-vimeo" viewBox="0 0 24 24">
|
||||
<path d="M22.396,7.164c-0.093,2.026-1.507,4.799-4.245,8.32C15.322,19.161,12.928,21,10.97,21c-1.214,0-2.24-1.119-3.079-3.359 c-0.56-2.053-1.119-4.106-1.68-6.159C5.588,9.243,4.921,8.122,4.206,8.122c-0.156,0-0.701,0.328-1.634,0.98L1.594,7.841 c1.027-0.902,2.04-1.805,3.037-2.708C6.001,3.95,7.03,3.327,7.715,3.264c1.619-0.156,2.616,0.951,2.99,3.321 c0.404,2.557,0.685,4.147,0.841,4.769c0.467,2.121,0.981,3.181,1.542,3.181c0.435,0,1.09-0.688,1.963-2.065 c0.871-1.376,1.338-2.422,1.401-3.142c0.125-1.187-0.343-1.782-1.401-1.782c-0.498,0-1.012,0.115-1.541,0.341 c1.023-3.35,2.977-4.977,5.862-4.884C21.511,3.066,22.52,4.453,22.396,7.164z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-vk" viewBox="0 0 24 24">
|
||||
<path d="M22,7.1c0.2,0.4-0.4,1.5-1.6,3.1c-0.2,0.2-0.4,0.5-0.7,0.9c-0.5,0.7-0.9,1.1-0.9,1.4c-0.1,0.3-0.1,0.6,0.1,0.8 c0.1,0.1,0.4,0.4,0.8,0.9h0l0,0c1,0.9,1.6,1.7,2,2.3c0,0,0,0.1,0.1,0.1c0,0.1,0,0.1,0.1,0.3c0,0.1,0,0.2,0,0.4 c0,0.1-0.1,0.2-0.3,0.3c-0.1,0.1-0.4,0.1-0.6,0.1l-2.7,0c-0.2,0-0.4,0-0.6-0.1c-0.2-0.1-0.4-0.1-0.5-0.2l-0.2-0.1 c-0.2-0.1-0.5-0.4-0.7-0.7s-0.5-0.6-0.7-0.8c-0.2-0.2-0.4-0.4-0.6-0.6C14.8,15,14.6,15,14.4,15c0,0,0,0-0.1,0c0,0-0.1,0.1-0.2,0.2 c-0.1,0.1-0.2,0.2-0.2,0.3c-0.1,0.1-0.1,0.3-0.2,0.5c-0.1,0.2-0.1,0.5-0.1,0.8c0,0.1,0,0.2,0,0.3c0,0.1-0.1,0.2-0.1,0.2l0,0.1 c-0.1,0.1-0.3,0.2-0.6,0.2h-1.2c-0.5,0-1,0-1.5-0.2c-0.5-0.1-1-0.3-1.4-0.6s-0.7-0.5-1.1-0.7s-0.6-0.4-0.7-0.6l-0.3-0.3 c-0.1-0.1-0.2-0.2-0.3-0.3s-0.4-0.5-0.7-0.9s-0.7-1-1.1-1.6c-0.4-0.6-0.8-1.3-1.3-2.2C2.9,9.4,2.5,8.5,2.1,7.5C2,7.4,2,7.3,2,7.2 c0-0.1,0-0.1,0-0.2l0-0.1c0.1-0.1,0.3-0.2,0.6-0.2l2.9,0c0.1,0,0.2,0,0.2,0.1S5.9,6.9,5.9,7L6,7c0.1,0.1,0.2,0.2,0.3,0.3 C6.4,7.7,6.5,8,6.7,8.4C6.9,8.8,7,9,7.1,9.2l0.2,0.3c0.2,0.4,0.4,0.8,0.6,1.1c0.2,0.3,0.4,0.5,0.5,0.7s0.3,0.3,0.4,0.4 c0.1,0.1,0.3,0.1,0.4,0.1c0.1,0,0.2,0,0.3-0.1c0,0,0,0,0.1-0.1c0,0,0.1-0.1,0.1-0.2c0.1-0.1,0.1-0.3,0.1-0.5c0-0.2,0.1-0.5,0.1-0.8 c0-0.4,0-0.8,0-1.3c0-0.3,0-0.5-0.1-0.8c0-0.2-0.1-0.4-0.1-0.5L9.6,7.6C9.4,7.3,9.1,7.2,8.7,7.1C8.6,7.1,8.6,7,8.7,6.9 C8.9,6.7,9,6.6,9.1,6.5c0.4-0.2,1.2-0.3,2.5-0.3c0.6,0,1,0.1,1.4,0.1c0.1,0,0.3,0.1,0.3,0.1c0.1,0.1,0.2,0.1,0.2,0.3 c0,0.1,0.1,0.2,0.1,0.3s0,0.3,0,0.5c0,0.2,0,0.4,0,0.6c0,0.2,0,0.4,0,0.7c0,0.3,0,0.6,0,0.9c0,0.1,0,0.2,0,0.4c0,0.2,0,0.4,0,0.5 c0,0.1,0,0.3,0,0.4s0.1,0.3,0.1,0.4c0.1,0.1,0.1,0.2,0.2,0.3c0.1,0,0.1,0,0.2,0c0.1,0,0.2,0,0.3-0.1c0.1-0.1,0.2-0.2,0.4-0.4 s0.3-0.4,0.5-0.7c0.2-0.3,0.5-0.7,0.7-1.1c0.4-0.7,0.8-1.5,1.1-2.3c0-0.1,0.1-0.1,0.1-0.2c0-0.1,0.1-0.1,0.1-0.1l0,0l0.1,0 c0,0,0,0,0.1,0s0.2,0,0.2,0l3,0c0.3,0,0.5,0,0.7,0S21.9,7,21.9,7L22,7.1z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-whatsapp" viewBox="0 0 24 24">
|
||||
<path d="M2.048,22l1.406-5.136c-0.867-1.503-1.324-3.208-1.323-4.955C2.133,6.446,6.579,2,12.042,2c2.651,0.001,5.14,1.033,7.011,2.906c1.871,1.873,2.901,4.363,2.9,7.011c-0.002,5.464-4.448,9.91-9.91,9.91c0,0,0,0,0,0h-0.004c-1.659-0.001-3.288-0.417-4.736-1.206L2.048,22z M7.545,18.828l0.301,0.179c1.265,0.751,2.714,1.148,4.193,1.148h0.003c4.54,0,8.235-3.695,8.237-8.237c0.001-2.201-0.855-4.271-2.41-5.828c-1.555-1.557-3.623-2.415-5.824-2.416c-4.544,0-8.239,3.695-8.241,8.237c-0.001,1.556,0.435,3.072,1.259,4.384l0.196,0.312l-0.832,3.04L7.545,18.828z M17.035,14.274c-0.062-0.103-0.227-0.165-0.475-0.289c-0.248-0.124-1.465-0.723-1.692-0.806c-0.227-0.083-0.392-0.124-0.557,0.124c-0.165,0.248-0.64,0.806-0.784,0.971c-0.144,0.165-0.289,0.186-0.536,0.062c-0.248-0.124-1.046-0.385-1.991-1.229c-0.736-0.657-1.233-1.468-1.378-1.715c-0.144-0.248-0.015-0.382,0.109-0.505c0.111-0.111,0.248-0.289,0.371-0.434c0.124-0.145,0.165-0.248,0.248-0.413c0.083-0.165,0.041-0.31-0.021-0.434c-0.062-0.124-0.557-1.343-0.763-1.839C9.364,7.284,9.159,7.35,9.007,7.342c-0.144-0.007-0.31-0.009-0.475-0.009c-0.165,0-0.433,0.062-0.66,0.31C7.646,7.891,7.006,8.49,7.006,9.709c0,1.219,0.887,2.396,1.011,2.562c0.124,0.165,1.746,2.666,4.23,3.739c0.591,0.255,1.052,0.408,1.412,0.522c0.593,0.189,1.133,0.162,1.56,0.098c0.476-0.071,1.465-0.599,1.671-1.177C17.096,14.873,17.096,14.378,17.035,14.274z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-woocommerce" viewBox="0 0 24 24">
|
||||
<path d="M12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2ZM5.96289 8.48242C5.18274 8.48255 4.78715 8.84526 4.78711 9.51562C4.78716 10.186 5.20472 10.5711 5.96289 10.5713H6.80957V14.583C6.80963 15.7152 7.5685 16.3857 8.67871 16.3857C9.56882 16.3856 10.2837 15.9465 10.8223 14.9355L12.0205 12.6924V14.5947C12.0207 15.7156 12.7461 16.3857 13.8672 16.3857C14.7463 16.3856 15.3951 16.0014 16.0215 14.9355L18.7803 10.2744C19.3848 9.25229 18.9565 8.4827 17.627 8.48242C16.9124 8.48242 16.4499 8.71367 16.0322 9.49414L14.1309 13.0664V9.88965C14.1309 8.94438 13.68 8.48252 12.8447 8.48242C12.1852 8.48242 11.6577 8.76825 11.251 9.55957L9.45898 13.0664V9.92285C9.45898 8.91172 9.04118 8.48258 8.03027 8.48242H5.96289Z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-wordpress" viewBox="0 0 24 24">
|
||||
<path d="M12.158,12.786L9.46,20.625c0.806,0.237,1.657,0.366,2.54,0.366c1.047,0,2.051-0.181,2.986-0.51 c-0.024-0.038-0.046-0.079-0.065-0.124L12.158,12.786z M3.009,12c0,3.559,2.068,6.634,5.067,8.092L3.788,8.341 C3.289,9.459,3.009,10.696,3.009,12z M18.069,11.546c0-1.112-0.399-1.881-0.741-2.48c-0.456-0.741-0.883-1.368-0.883-2.109 c0-0.826,0.627-1.596,1.51-1.596c0.04,0,0.078,0.005,0.116,0.007C16.472,3.904,14.34,3.009,12,3.009 c-3.141,0-5.904,1.612-7.512,4.052c0.211,0.007,0.41,0.011,0.579,0.011c0.94,0,2.396-0.114,2.396-0.114 C7.947,6.93,8.004,7.642,7.52,7.699c0,0-0.487,0.057-1.029,0.085l3.274,9.739l1.968-5.901l-1.401-3.838 C9.848,7.756,9.389,7.699,9.389,7.699C8.904,7.67,8.961,6.93,9.446,6.958c0,0,1.484,0.114,2.368,0.114 c0.94,0,2.397-0.114,2.397-0.114c0.485-0.028,0.542,0.684,0.057,0.741c0,0-0.488,0.057-1.029,0.085l3.249,9.665l0.897-2.996 C17.841,13.284,18.069,12.316,18.069,11.546z M19.889,7.686c0.039,0.286,0.06,0.593,0.06,0.924c0,0.912-0.171,1.938-0.684,3.22 l-2.746,7.94c2.673-1.558,4.47-4.454,4.47-7.771C20.991,10.436,20.591,8.967,19.889,7.686z M12,22C6.486,22,2,17.514,2,12 C2,6.486,6.486,2,12,2c5.514,0,10,4.486,10,10C22,17.514,17.514,22,12,22z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-yelp" viewBox="0 0 24 24">
|
||||
<path d="M12.271,16.718v1.417q-.011,3.257-.067,3.4a.707.707,0,0,1-.569.446,4.637,4.637,0,0,1-2.024-.424A4.609,4.609,0,0,1,7.8,20.565a.844.844,0,0,1-.19-.4.692.692,0,0,1,.044-.29,3.181,3.181,0,0,1,.379-.524q.335-.412,2.019-2.409.011,0,.669-.781a.757.757,0,0,1,.44-.274.965.965,0,0,1,.552.039.945.945,0,0,1,.418.324.732.732,0,0,1,.139.468Zm-1.662-2.8a.783.783,0,0,1-.58.781l-1.339.435q-3.067.981-3.257.981a.711.711,0,0,1-.6-.4,2.636,2.636,0,0,1-.19-.836,9.134,9.134,0,0,1,.011-1.857,3.559,3.559,0,0,1,.335-1.389.659.659,0,0,1,.625-.357,22.629,22.629,0,0,1,2.253.859q.781.324,1.283.524l.937.379a.771.771,0,0,1,.4.34A.982.982,0,0,1,10.609,13.917Zm9.213,3.313a4.467,4.467,0,0,1-1.021,1.8,4.559,4.559,0,0,1-1.512,1.417.671.671,0,0,1-.7-.078q-.156-.112-2.052-3.2l-.524-.859a.761.761,0,0,1-.128-.513.957.957,0,0,1,.217-.513.774.774,0,0,1,.926-.29q.011.011,1.327.446,2.264.736,2.7.887a2.082,2.082,0,0,1,.524.229.673.673,0,0,1,.245.68Zm-7.5-7.049q.056,1.137-.6,1.361-.647.19-1.272-.792L6.237,4.08a.7.7,0,0,1,.212-.691,5.788,5.788,0,0,1,2.314-1,5.928,5.928,0,0,1,2.5-.352.681.681,0,0,1,.547.5q.034.2.245,3.407T12.327,10.181Zm7.384,1.2a.679.679,0,0,1-.29.658q-.167.112-3.67.959-.747.167-1.015.257l.011-.022a.769.769,0,0,1-.513-.044.914.914,0,0,1-.413-.357.786.786,0,0,1,0-.971q.011-.011.836-1.137,1.394-1.908,1.673-2.275a2.423,2.423,0,0,1,.379-.435A.7.7,0,0,1,17.435,8a4.482,4.482,0,0,1,1.372,1.489,4.81,4.81,0,0,1,.9,1.868v.034Z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-x" viewBox="0 0 24 24">
|
||||
<path d="M14.1173 9.62177L20.4459 2H18.9463L13.4511 8.61788L9.06215 2H4L10.637 12.0074L4 20H5.49977L11.3028 13.0113L15.9379 20H21L14.1169 9.62177H14.1173ZM12.0632 12.0956L11.3907 11.0991L6.04016 3.16971H8.34371L12.6617 9.56895L13.3341 10.5655L18.947 18.8835H16.6434L12.0632 12.096V12.0956Z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-xanga" viewBox="0 0 24 24">
|
||||
<path d="M9,9h6v6H9V9z M3,9h6V3H3V9z M15,9h6V3h-6V9z M15,21h6v-6h-6V21z M3,21h6v-6H3V21z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-youtube" viewBox="0 0 24 24">
|
||||
<path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"/>
|
||||
</symbol>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 67 KiB |
Reference in New Issue
Block a user