diff --git a/recipes/README.txt b/recipes/README.txt deleted file mode 100644 index 5fdb32d1e..000000000 --- a/recipes/README.txt +++ /dev/null @@ -1,9 +0,0 @@ -Recipes allow the automation of Drupal module and theme installation and -configuration. - -WHAT TO PLACE IN THIS DIRECTORY? --------------------------------- - -Placing downloaded and custom recipes in this directory separates downloaded and -custom recipes from Drupal core's recipes. This allows Drupal core to be updated -without overwriting these files. diff --git a/recipes/drupal_cms_seo_tools/LICENSE.txt b/recipes/drupal_cms_seo_tools/LICENSE.txt deleted file mode 100644 index 94fb84639..000000000 --- a/recipes/drupal_cms_seo_tools/LICENSE.txt +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/recipes/drupal_cms_seo_tools/composer.json b/recipes/drupal_cms_seo_tools/composer.json deleted file mode 100644 index 582a26cd2..000000000 --- a/recipes/drupal_cms_seo_tools/composer.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "drupal/drupal_cms_seo_tools", - "description": "Adds common search engine optimisation tools such as meta tags, XML sitemap, robots.txt management and more.", - "type": "drupal-recipe", - "license": ["GPL-2.0-or-later"], - "require": { - "drupal/bpmn_io": "^2.0.6", - "drupal/core": ">=10.4", - "drupal/eca": "^2.1.4", - "drupal/field_group": "^3.6", - "drupal/focal_point": "^2.1", - "drupal/metatag": "^2", - "drupal/robotstxt": "^1.6", - "drupal/seo_checklist": "^5.2.1", - "drupal/simple_sitemap": "^4.2.2", - "drupal/sitemap": "^2", - "drupal/token_or": "^2.2", - "drupal/yoast_seo": "^2.1" - }, - "suggest": { - "drupal/drupal_cms_analytics": "Adds recipes for tracking website traffic.", - "drupal/drupal_cms_accessibility_tools": "Adds automated checks to help ensure content conforms to web accessibility guidelines." - }, - "version": "1.1.0" -} diff --git a/recipes/drupal_cms_seo_tools/config/eca.eca.node_sitemap_settings.yml b/recipes/drupal_cms_seo_tools/config/eca.eca.node_sitemap_settings.yml deleted file mode 100644 index c65637d52..000000000 --- a/recipes/drupal_cms_seo_tools/config/eca.eca.node_sitemap_settings.yml +++ /dev/null @@ -1,200 +0,0 @@ -langcode: en -status: true -dependencies: - module: - - eca_base - - eca_config - - eca_content - - eca_misc - - eca_user -id: node_sitemap_settings -modeller: bpmn_io -label: 'Automatically configure sitemap settings for content types' -version: 1.0.0 -weight: 0 -events: - Event_save_config: - plugin: 'config:save' - label: 'Create node bundle' - configuration: - config_name: node.type. - sync_mode: 'no' - write_mode: new - successors: - - - id: Activity_switch_user - condition: Flow_path_is_not_add_bundle - Event_applied_seo_tools: - plugin: 'drupal:recipe_applied' - label: 'SEO Tools applied' - configuration: - recipe_base_path: drupal_cms_seo_tools - successors: - - - id: Activity_1ghfkn0 - condition: '' -conditions: - Flow_number_of_bundles: - plugin: eca_count - configuration: - negate: false - case: false - left: bundles - right: '0' - operator: greaterthan - type: numeric - Flow_path_is_not_add_bundle: - plugin: eca_scalar - configuration: - case: false - left: '[current-page:url:path]' - right: /admin/structure/types/add - operator: equal - type: value - negate: true - Flow_config_is_empty: - plugin: eca_scalar - configuration: - negate: false - case: false - left: '[priority]' - right: priority - operator: contains - type: value - Flow_config_exists: - plugin: eca_scalar - configuration: - case: false - left: '[priority]' - right: priority - operator: contains - type: value - negate: true -gateways: - Gateway_AND_1: - type: 0 - successors: - - - id: Activity_get_bundle_id - condition: Flow_number_of_bundles -actions: - Activity_set_bundle_id_to_token: - plugin: eca_token_set_value - label: 'Remember bundle id' - configuration: - token_name: bundle - token_value: '[config:type]' - use_yaml: false - successors: - - - id: Activity_read_sitemap_config_for_bundle - condition: '' - Activity_set_index: - plugin: eca_config_write - label: 'Set index' - configuration: - config_value: '1' - use_yaml: false - save_config: true - config_name: 'simple_sitemap.bundle_settings.default.node.[bundle]' - config_key: index - successors: - - - id: Activity_set_priority - condition: '' - Activity_set_priority: - plugin: eca_config_write - label: 'Set priority' - configuration: - config_value: '0.9' - use_yaml: false - save_config: true - config_name: 'simple_sitemap.bundle_settings.default.node.[bundle]' - config_key: priority - successors: - - - id: Activity_set_changefreq - condition: '' - Activity_set_changefreq: - plugin: eca_config_write - label: 'Set changefreq' - configuration: - config_value: daily - use_yaml: false - save_config: true - config_name: 'simple_sitemap.bundle_settings.default.node.[bundle]' - config_key: changefreq - successors: - - - id: Activity_set_include_images - condition: '' - Activity_set_include_images: - plugin: eca_config_write - label: 'Set include_images' - configuration: - config_value: '0' - use_yaml: false - save_config: true - config_name: 'simple_sitemap.bundle_settings.default.node.[bundle]' - config_key: include_images - successors: - - - id: Gateway_AND_1 - condition: '' - Activity_get_list_of_bundles: - plugin: eca_get_bundle_list - label: 'Get bundles' - configuration: - token_name: bundles - type: node - mode: ids - successors: - - - id: Gateway_AND_1 - condition: '' - Activity_get_bundle_id: - plugin: eca_list_remove - label: 'Get next bundle ID' - configuration: - value: '' - token_name: bundle - method: first - index: '' - list_token: bundles - successors: - - - id: Activity_read_sitemap_config_for_bundle - condition: '' - Activity_read_sitemap_config_for_bundle: - plugin: eca_config_read - label: 'Read sitemap setting' - configuration: - token_name: priority - include_overridden: true - config_name: 'simple_sitemap.bundle_settings.default.node.[bundle]' - config_key: priority - successors: - - - id: Activity_set_index - condition: Flow_config_is_empty - - - id: Gateway_AND_1 - condition: Flow_config_exists - Activity_switch_user: - plugin: eca_switch_account - label: 'Switch user' - configuration: - user_id: '1' - successors: - - - id: Activity_set_bundle_id_to_token - condition: '' - Activity_1ghfkn0: - plugin: eca_switch_account - label: 'Switch user' - configuration: - user_id: '1' - successors: - - - id: Activity_get_list_of_bundles - condition: '' diff --git a/recipes/drupal_cms_seo_tools/config/field.storage.node.field_seo_analysis.yml b/recipes/drupal_cms_seo_tools/config/field.storage.node.field_seo_analysis.yml deleted file mode 100644 index 8cf8d78ce..000000000 --- a/recipes/drupal_cms_seo_tools/config/field.storage.node.field_seo_analysis.yml +++ /dev/null @@ -1,18 +0,0 @@ -langcode: en -status: true -dependencies: - module: - - node - - yoast_seo -id: node.field_seo_analysis -field_name: field_seo_analysis -entity_type: node -type: yoast_seo -settings: { } -module: yoast_seo -locked: false -cardinality: 1 -translatable: true -indexes: { } -persist_with_no_fields: false -custom_storage: false diff --git a/recipes/drupal_cms_seo_tools/config/field.storage.node.field_seo_description.yml b/recipes/drupal_cms_seo_tools/config/field.storage.node.field_seo_description.yml deleted file mode 100644 index 371aede8c..000000000 --- a/recipes/drupal_cms_seo_tools/config/field.storage.node.field_seo_description.yml +++ /dev/null @@ -1,18 +0,0 @@ -langcode: en -status: true -dependencies: - module: - - node -id: node.field_seo_description -field_name: field_seo_description -entity_type: node -type: string_long -settings: - case_sensitive: false -module: core -locked: false -cardinality: 1 -translatable: true -indexes: { } -persist_with_no_fields: false -custom_storage: false diff --git a/recipes/drupal_cms_seo_tools/config/field.storage.node.field_seo_image.yml b/recipes/drupal_cms_seo_tools/config/field.storage.node.field_seo_image.yml deleted file mode 100644 index 4bac119a5..000000000 --- a/recipes/drupal_cms_seo_tools/config/field.storage.node.field_seo_image.yml +++ /dev/null @@ -1,19 +0,0 @@ -langcode: en -status: true -dependencies: - module: - - media - - node -id: node.field_seo_image -field_name: field_seo_image -entity_type: node -type: entity_reference -settings: - target_type: media -module: core -locked: false -cardinality: 1 -translatable: true -indexes: { } -persist_with_no_fields: false -custom_storage: false diff --git a/recipes/drupal_cms_seo_tools/config/field.storage.node.field_seo_title.yml b/recipes/drupal_cms_seo_tools/config/field.storage.node.field_seo_title.yml deleted file mode 100644 index 80becb89e..000000000 --- a/recipes/drupal_cms_seo_tools/config/field.storage.node.field_seo_title.yml +++ /dev/null @@ -1,20 +0,0 @@ -langcode: en -status: true -dependencies: - module: - - node -id: node.field_seo_title -field_name: field_seo_title -entity_type: node -type: string -settings: - max_length: 255 - case_sensitive: false - is_ascii: false -module: core -locked: false -cardinality: 1 -translatable: true -indexes: { } -persist_with_no_fields: false -custom_storage: false diff --git a/recipes/drupal_cms_seo_tools/config/image.style.social_media_facebook.yml b/recipes/drupal_cms_seo_tools/config/image.style.social_media_facebook.yml deleted file mode 100644 index 72a374063..000000000 --- a/recipes/drupal_cms_seo_tools/config/image.style.social_media_facebook.yml +++ /dev/null @@ -1,22 +0,0 @@ -langcode: en -status: true -dependencies: - module: - - focal_point -name: social_media_facebook -label: 'Social media - Facebook' -effects: - 338d92b4-4580-4118-aa11-96fb253e343e: - uuid: 338d92b4-4580-4118-aa11-96fb253e343e - id: focal_point_scale_and_crop - weight: 1 - data: - width: 1200 - height: 630 - crop_type: focal_point - 8ddd479d-03db-45d3-8591-a7b72e13bb21: - uuid: 8ddd479d-03db-45d3-8591-a7b72e13bb21 - id: image_convert - weight: 2 - data: - extension: webp diff --git a/recipes/drupal_cms_seo_tools/config/image.style.social_media_x.yml b/recipes/drupal_cms_seo_tools/config/image.style.social_media_x.yml deleted file mode 100644 index f972980df..000000000 --- a/recipes/drupal_cms_seo_tools/config/image.style.social_media_x.yml +++ /dev/null @@ -1,22 +0,0 @@ -langcode: en -status: true -dependencies: - module: - - focal_point -name: social_media_x -label: 'Social media - X (Twitter)' -effects: - 7de498f6-16e8-4f33-aa2b-afc30ad91155: - uuid: 7de498f6-16e8-4f33-aa2b-afc30ad91155 - id: focal_point_scale_and_crop - weight: 1 - data: - width: 1600 - height: 900 - crop_type: focal_point - 94553ea6-7659-4f21-b586-3dd07fb21e88: - uuid: 94553ea6-7659-4f21-b586-3dd07fb21e88 - id: image_convert - weight: 2 - data: - extension: webp diff --git a/recipes/drupal_cms_seo_tools/config/metatag.metatag_defaults.front.yml b/recipes/drupal_cms_seo_tools/config/metatag.metatag_defaults.front.yml deleted file mode 100644 index 3bbddf2f0..000000000 --- a/recipes/drupal_cms_seo_tools/config/metatag.metatag_defaults.front.yml +++ /dev/null @@ -1,28 +0,0 @@ -langcode: en -status: true -id: front -label: 'Front page' -tags: - canonical_url: '[site:url]' - description: '[node:field_seo_description|node:field_description]' - image_src: '[node:field_seo_image:entity:field_media_image:social_media_facebook|node:field_image:entity:field_media_image:social_media_facebook]' - og_description: '[node:field_seo_description|node:field_description]' - og_image: '[node:field_seo_image:entity:field_media_image:social_media_facebook|node:field_image:entity:field_media_image:social_media_facebook]' - og_image_alt: '[node:field_seo_image:entity:field_media_image:alt|node:field_image:entity:field_media_image:alt]' - og_image_height: '[node:field_seo_image:entity:field_media_image:social_media_facebook:height|node:field_image:entity:field_media_image:social_media_facebook:height]' - og_image_type: '[node:field_seo_image:entity:field_media_image:social_media_facebook:mimetype|node:field_image:entity:field_media_image:social_media_facebook:mimetype]' - og_image_width: '[node:field_seo_image:entity:field_media_image:social_media_facebook:width|node:field_image:entity:field_media_image:social_media_facebook:width]' - og_site_name: '[site:name]' - og_title: '[node:field_seo_title|node:title]' - og_type: website - og_updated_time: '[node:changed:custom:c]' - og_url: '[current-page:url:absolute]' - referrer: unsafe-url - rights: 'Copyright ©[date:html_year] All rights reserved.' - shortlink: '[site:url]' - title: '[node:field_seo_title|node:title] | [site:name]' - twitter_cards_description: '[node:field_seo_description|node:field_description]' - twitter_cards_image: '[node:field_seo_image:entity:field_media_image:social_media_x:url|node:field_image:entity:field_media_image:social_media_x:url]' - twitter_cards_image_alt: '[node:field_seo_image:entity:field_media_image:alt|node:field_image:entity:field_media_image:alt]' - twitter_cards_title: '[node:field_seo_title|node:title]' - twitter_cards_type: summary_large_image diff --git a/recipes/drupal_cms_seo_tools/config/metatag.metatag_defaults.global.yml b/recipes/drupal_cms_seo_tools/config/metatag.metatag_defaults.global.yml deleted file mode 100644 index 4ba5204f5..000000000 --- a/recipes/drupal_cms_seo_tools/config/metatag.metatag_defaults.global.yml +++ /dev/null @@ -1,13 +0,0 @@ -langcode: en -status: true -id: global -label: Global -tags: - referrer: unsafe-url - title: '[current-page:title] | [site:name]' - canonical_url: '[current-page:url:absolute]' - shortlink: '[current-page:url:unaliased]' - rights: 'Copyright ©[date:html_year] All rights reserved.' - og_url: '[current-page:url:absolute]' - og_site_name: '[site:name]' - twitter_cards_type: summary diff --git a/recipes/drupal_cms_seo_tools/config/metatag.metatag_defaults.node.yml b/recipes/drupal_cms_seo_tools/config/metatag.metatag_defaults.node.yml deleted file mode 100644 index b4b592356..000000000 --- a/recipes/drupal_cms_seo_tools/config/metatag.metatag_defaults.node.yml +++ /dev/null @@ -1,28 +0,0 @@ -langcode: en -status: true -id: node -label: Content -tags: - canonical_url: '[current-page:url:absolute]' - description: '[node:field_seo_description|node:field_description]' - image_src: '[node:field_seo_image:entity:field_media_image:social_media_facebook|node:field_featured_image:entity:field_media_image:social_media_facebook]' - og_description: '[node:field_seo_description|node:field_description]' - og_image: '[node:field_seo_image:entity:field_media_image:social_media_facebook|node:field_featured_image:entity:field_media_image:social_media_facebook]' - og_image_alt: '[node:field_seo_image:entity:field_media_image:alt|node:field_featured_image:entity:field_media_image:alt]' - og_image_height: '[node:field_seo_image:entity:field_media_image:social_media_facebook:height|node:field_featured_image:entity:field_media_image:social_media_facebook:height]' - og_image_type: '[node:field_seo_image:entity:field_media_image:social_media_facebook:mimetype|node:field_featured_image:entity:field_media_image:social_media_facebook:mimetype]' - og_image_width: '[node:field_seo_image:entity:field_media_image:social_media_facebook:width|node:field_featured_image:entity:field_media_image:social_media_facebook:width]' - og_site_name: '[site:name]' - og_title: '[node:field_seo_title|node:title]' - og_type: article - og_updated_time: '[node:changed:custom:c]' - og_url: '[current-page:url:absolute]' - referrer: unsafe-url - rights: 'Copyright ©[date:html_year] All rights reserved.' - shortlink: '[site:url]' - title: '[node:field_seo_title|node:title] | [site:name]' - twitter_cards_description: '[node:field_seo_description|node:field_description]' - twitter_cards_image: '[node:field_seo_image:entity:field_media_image:social_media_x:url|node:field_featured_image:entity:field_media_image:social_media_x:url]' - twitter_cards_image_alt: '[node:field_seo_image:entity:field_media_image:alt|node:field_featured_image:entity:field_media_image:alt]' - twitter_cards_title: '[node:field_seo_title|node:title]' - twitter_cards_type: summary_large_image diff --git a/recipes/drupal_cms_seo_tools/recipe.yml b/recipes/drupal_cms_seo_tools/recipe.yml deleted file mode 100644 index 17021f2a1..000000000 --- a/recipes/drupal_cms_seo_tools/recipe.yml +++ /dev/null @@ -1,236 +0,0 @@ -name: SEO Tools -description: Adds common search engine optimisation tools such as meta tags, XML sitemap, robots.txt management and more. -type: Drupal CMS -recipes: - - core/recipes/image_media_type -install: - - eca_base - - eca_config - - eca_content - - eca_misc - - eca_user - - field_group - - focal_point - - layout_builder - - menu_link_content - - metatag - - metatag_open_graph - - metatag_twitter_cards - - node - - robotstxt - - seo_checklist - - simple_sitemap - - sitemap - - token_or - - yoast_seo -config: - # Treat all field storages strictly, since they influence the database layout. - strict: - - field.storage.node.field_seo_analysis - - field.storage.node.field_seo_description - - field.storage.node.field_seo_image - - field.storage.node.field_seo_title - import: - metatag: - # Exclude Global, Front and Node as we create those in the config folder. - - metatag.metatag_defaults.403.yml - - metatag.metatag_defaults.404.yml - - metatag.metatag_defaults.taxonomy_term.yml - - metatag.metatag_defaults.user.yml - simple_sitemap: '*' - actions: - # Add SEO fields to all content types that are installed. - field.storage.node.field_seo_analysis: - addToAllBundles: - label: 'SEO analysis' - description: 'Pick the main keyword this page is about.' - field.storage.node.field_seo_description: - addToAllBundles: - label: 'SEO description' - description: 'Write a description for search engines and social media sites.' - field.storage.node.field_seo_image: - addToAllBundles: - label: 'SEO image' - description: 'Upload an image to be used when the page is shared on social media sites.' - # Ensure all instances of `field_seo_image` reference image media. - field.field.node.*.field_seo_image: - setSettings: - handler: 'default:media' - handler_settings: - target_bundles: - image: image - field.storage.node.field_seo_title: - addToAllBundles: - label: 'SEO title' - description: 'Use this field to overwrite the default HTML page title for SEO.' - # Configure the fields on the edit forms. - core.entity_form_display.node.*.default: - # Configure field group. - setThirdPartySettings: - - module: field_group - key: group_seo - value: - children: - - field_seo_title - - field_seo_description - - field_seo_image - - field_seo_analysis - label: 'Search Engine Optimization (SEO) Information' - region: content - parent_name: '' - weight: 50 - format_type: details - format_settings: - classes: '' - show_empty_fields: false - id: group_seo - label_as_html: false - open: false - description: '' - required_fields: false - setComponents: - - - name: field_seo_analysis - options: - type: yoast_seo_widget - weight: 18 - region: content - settings: - render_theme: NULL - render_view_mode: default - edit_title: 0 - edit_description: 0 - - - name: field_seo_description - options: - type: string_textarea - weight: 16 - region: content - settings: - rows: 5 - placeholder: '' - - - name: field_seo_image - options: - type: media_library_widget - weight: 17 - region: content - settings: - media_types: { } - - - name: field_seo_title - options: - type: string_textfield - weight: 15 - region: content - settings: - size: 60 - placeholder: '' - robotstxt.settings: - # We add Drupal core's robots.txt and XML Sitemap. - simpleConfigUpdate: - content: | - # - # robots.txt - # - # This file is to prevent the crawling and indexing of certain parts - # of your site by web crawlers and spiders run by sites like Yahoo! - # and Google. By telling these "robots" where not to go on your site, - # you save bandwidth and server resources. - # - # This file will be ignored unless it is at the root of your host: - # Used: http://example.com/robots.txt - # Ignored: http://example.com/site/robots.txt - # - # For more information about the robots.txt standard, see: - # http://www.robotstxt.org/robots - User-agent: * - # CSS, JS, Images - Allow: /core/*.css$ - Allow: /core/*.css? - Allow: /core/*.js$ - Allow: /core/*.js? - Allow: /core/*.gif - Allow: /core/*.jpg - Allow: /core/*.jpeg - Allow: /core/*.png - Allow: /core/*.svg - Allow: /profiles/*.css$ - Allow: /profiles/*.css? - Allow: /profiles/*.js$ - Allow: /profiles/*.js? - Allow: /profiles/*.gif - Allow: /profiles/*.jpg - Allow: /profiles/*.jpeg - Allow: /profiles/*.png - Allow: /profiles/*.svg - # Directories - Disallow: /core/ - Disallow: /profiles/ - # Files - Disallow: /README.md - Disallow: /composer/Metapackage/README.txt - Disallow: /composer/Plugin/ProjectMessage/README.md - Disallow: /composer/Plugin/Scaffold/README.md - Disallow: /composer/Plugin/VendorHardening/README.txt - Disallow: /composer/Template/README.txt - Disallow: /modules/README.txt - Disallow: /sites/README.txt - Disallow: /themes/README.txt - # Paths (clean URLs) - Disallow: /admin/ - Disallow: /comment/reply/ - Disallow: /filter/tips - Disallow: /node/add/ - Disallow: /search/ - Disallow: /user/register - Disallow: /user/password - Disallow: /user/login - Disallow: /user/logout - Disallow: /media/oembed - Disallow: /*/media/oembed - # Paths (no clean URLs) - Disallow: /index.php/admin/ - Disallow: /index.php/comment/reply/ - Disallow: /index.php/filter/tips - Disallow: /index.php/node/add/ - Disallow: /index.php/search/ - Disallow: /index.php/user/password - Disallow: /index.php/user/register - Disallow: /index.php/user/login - Disallow: /index.php/user/logout - Disallow: /index.php/media/oembed - Disallow: /index.php/*/media/oembed - # XML sitemap - Sitemap: /sitemap.xml - sitemap.settings: - simpleConfigUpdate: - plugins.frontpage: - base_plugin: frontpage - enabled: true - weight: 0 - settings: - title: 'Front page' - rss: null - id: frontpage - provider: sitemap - plugins.menu:main: - base_plugin: menu - enabled: true - weight: 0 - settings: - title: '' - show_disabled: false - id: 'menu:main' - provider: sitemap - system.performance: - simpleConfigUpdate: - # Ensure caching is on and set to 15 minutes for Lighthouse. - cache.page.max_age: 900 - # Ensure CSS and JS are preprocessed. - css.preprocess: true - js.preprocess: true - user.role.anonymous: - grantPermission: 'access sitemap' - user.role.authenticated: - grantPermission: 'access sitemap' diff --git a/recipes/drupal_cms_seo_tools/tests/src/Functional/ComponentValidationTest.php b/recipes/drupal_cms_seo_tools/tests/src/Functional/ComponentValidationTest.php deleted file mode 100644 index c38e2a9cf..000000000 --- a/recipes/drupal_cms_seo_tools/tests/src/Functional/ComponentValidationTest.php +++ /dev/null @@ -1,139 +0,0 @@ -drupalCreateContentType(['type' => 'test'])->id(); - } - - private function applyRecipe(mixed ...$arguments): void { - $dir = realpath(__DIR__ . '/../../..'); - $this->traitApplyRecipe($dir, ...$arguments); - } - - public function test(): void { - // The recipe should apply cleanly. - $this->applyRecipe(); - // Apply it again to prove that it is idempotent. - $this->applyRecipe(); - - // There should be an SEO image field on our test content type, referencing - // image media. - $field_settings = FieldConfig::loadByName('node', 'test', 'field_seo_image')?->getSettings(); - $this->assertIsArray($field_settings); - $this->assertSame('default:media', $field_settings['handler']); - $this->assertContains('image', $field_settings['handler_settings']['target_bundles']); - - // Check sitemap works as expected for anonymous users. - $this->checkSitemap(); - - // Check sitemap works as expected for authenticated users too. - $authenticated = $this->createUser(); - $this->drupalLogin($authenticated); - $this->checkSitemap(); - } - - public function testAutomaticSitemapSettings(): void { - $this->applyRecipe(); - - // We should have Simple Sitemap settings for the extant content type. - $settings = $this->container->get('config.storage') - ->listAll('simple_sitemap.bundle_settings'); - $this->assertSame(['simple_sitemap.bundle_settings.default.node.test'], $settings); - - $get_settings = function (string $node_type): Config { - return $this->config("simple_sitemap.bundle_settings.default.node.$node_type"); - }; - // If we create a new content type programmatically, Simple Sitemap settings - // should be generated for it automatically. - $node_type = $this->drupalCreateContentType()->id(); - $this->assertFalse($get_settings($node_type)->isNew()); - - // If we create a new content type in the UI, Simple Sitemap settings should - // NOT be automatically generated. - $account = $this->createUser([ - 'administer content types', - 'administer sitemap settings', - ]); - $this->drupalLogin($account); - $this->drupalGet('/admin/structure/types/add'); - $node_type = $this->randomMachineName(); - $this->submitForm([ - 'name' => $node_type, - 'type' => $node_type, - 'simple_sitemap[default][index]' => 0, - ], 'Save'); - $this->assertTrue($get_settings($node_type)->isNew()); - - // Extant settings should not be changed... - $get_settings('test')->set('priority', '0.3')->save(); - $this->assertSame('0.3', $get_settings('test')->get('priority')); - // ...even if we reapply the recipe... - $this->applyRecipe(); - $this->assertSame('0.3', $get_settings('test')->get('priority')); - // ...or sync config (here, we are simulating that the priority was changed - // by a config sync). - $this->container->get(ConfigInstallerInterface::class)->setSyncing(TRUE); - $get_settings('test')->set('priority', '0.2')->save(); - $this->assertSame('0.2', $get_settings('test')->get('priority')); - } - - /** - * Checks that the sitemap is accessible and contains the expected links. - */ - private function checkSitemap(): void { - // Create a main menu link to ensure it shows up in the site map. - $node = $this->drupalCreateNode(['type' => 'test']); - $menu_link = MenuLinkContent::create([ - 'title' => $node->getTitle(), - 'link' => 'internal:' . $node->toUrl()->toString(), - 'menu_name' => 'main', - ]); - $menu_link->save(); - - $this->drupalGet('/sitemap'); - - $assert_session = $this->assertSession(); - $assert_session->statusCodeEquals(200); - $assert_session->linkByHrefNotExists('/rss.xml'); - - $site_map = $assert_session->elementExists('css', '.sitemap'); - $site_name = $this->config('system.site')->get('name'); - $this->assertTrue($site_map->hasLink("Front page of $site_name"), 'Front page link does not appear in the site map.'); - $this->assertTrue($site_map->hasLink($menu_link->label()), 'Main menu links do not appear in the site map.'); - } - -} diff --git a/recipes/drupal_cms_seo_tools/tests/src/Functional/ContentMetaTagsTest.php b/recipes/drupal_cms_seo_tools/tests/src/Functional/ContentMetaTagsTest.php deleted file mode 100644 index 961b20e44..000000000 --- a/recipes/drupal_cms_seo_tools/tests/src/Functional/ContentMetaTagsTest.php +++ /dev/null @@ -1,160 +0,0 @@ -getRandomGenerator(); - - $uri = uniqid('public://') . '.' . $extension; - $uri = $random->image($uri, '100x100', '200x200'); - $this->assertFileExists($uri); - $file = File::create(['uri' => $uri]); - $file->save(); - - $media = Media::create([ - 'name' => $random->word(16), - 'bundle' => 'image', - 'field_media_image' => [ - 'target_id' => $file->id(), - 'alt' => $random->machineName(), - ], - ]); - $media->save(); - - return $media; - } - - /** - * @testWith ["drupal/drupal_cms_blog", "blog"] - * ["drupal/drupal_cms_case_study", "case_study"] - * ["drupal/drupal_cms_events", "event"] - * ["drupal/drupal_cms_news", "news"] - * ["drupal/drupal_cms_page", "page"] - * ["drupal/drupal_cms_person", "person"] - * ["drupal/drupal_cms_project", "project"] - */ - public function testMetaTagsForContentType(string $recipe, string $node_type): void { - $dir = InstalledVersions::getInstallPath($recipe); - $this->applyRecipe($dir); - - $dir = realpath(__DIR__ . '/../../..'); - $this->applyRecipe($dir); - - // If we create a node of this content type, all expected meta tags should - // be there. - $random = $this->getRandomGenerator(); - $node = $this->drupalCreateNode([ - 'type' => $node_type, - 'field_featured_image' => $this->generateImage('png'), - 'field_description' => $random->sentences(4), - 'moderation_state' => 'published', - ]); - $node_url = $node->toUrl(); - $this->drupalGet($node_url); - $assert_session = $this->assertSession(); - $assert_session->statusCodeEquals(200); - - $save_node = function () use ($node): void { - $node->save(); - $this->container->get('cache.page')->deleteAll(); - $this->getSession()->reload(); - }; - - // Assert the meta tags which are static, or don't have any configured - // overrides. - $absolute_node_url = $node_url->setAbsolute()->toString(); - $assert_session->elementAttributeContains('css', 'link[rel="canonical"]', 'href', $absolute_node_url); - $site_name = $this->config('system.site')->get('name'); - $assert_session->elementAttributeContains('css', 'meta[property="og:site_name"]', 'content', $site_name); - $assert_session->elementAttributeContains('css', 'meta[property="og:type"]', 'content', 'article'); - $assert_session->elementAttributeContains('css', 'meta[property="og:url"]', 'content', $absolute_node_url); - $assert_session->elementAttributeContains('css', 'meta[name="referrer"]', 'content', 'unsafe-url'); - $assert_session->elementAttributeContains('css', 'link[rel="shortlink"]', 'href', Url::fromRoute('')->setAbsolute()->toString()); - $assert_session->elementAttributeContains('css', 'meta[name="rights"]', 'content', sprintf('Copyright ©%s All rights reserved.', date('Y'))); - $assert_session->elementAttributeContains('css', 'meta[name="twitter:card"]', 'content', 'summary_large_image'); - $original_changed_time = $node->getChangedTime(); - $assert_session->elementAttributeContains('css', 'meta[property="og:updated_time"]', 'content', date('c', $original_changed_time)); - - // Re-saving the node should update the og:updated_time meta tag. - $updated_changed_time = $original_changed_time + 30; - $node->setChangedTime($updated_changed_time); - $save_node(); - $assert_session->elementAttributeContains('css', 'meta[property="og:updated_time"]', 'content', date('c', $updated_changed_time)); - - // Assert the meta tags for field_featured_image, and that field_seo_image - // takes precedence over it. - $assert_image = function (Media $image) use ($assert_session): void { - /** @var \Drupal\file\FileInterface $file */ - $file = $image->field_media_image->entity; - $name = $file->getFilename(); - - $facebook_dimensions = []; - ImageStyle::load('social_media_facebook') - ?->transformDimensions($facebook_dimensions, $file->getFileUri()); - $this->assertArrayHasKey('width', $facebook_dimensions); - $this->assertArrayHasKey('height', $facebook_dimensions); - - $assert_session->elementAttributeContains('css', 'link[rel="image_src"]', 'href', $name); - $assert_session->elementAttributeContains('css', 'meta[property="og:image"]', 'content', $name); - $alt_text = $image->field_media_image->alt; - $assert_session->elementAttributeContains('css', 'meta[property="og:image:alt"]', 'content', $alt_text); - $assert_session->elementAttributeContains('css', 'meta[property="og:image:width"]', 'content', (string) $facebook_dimensions['width']); - $assert_session->elementAttributeContains('css', 'meta[property="og:image:height"]', 'content', (string) $facebook_dimensions['height']); - $assert_session->elementAttributeContains('css', 'meta[property="og:image:type"]', 'content', 'image/webp'); - $assert_session->elementAttributeContains('css', 'meta[name="twitter:image"]', 'content', $name); - $assert_session->elementAttributeContains('css', 'meta[name="twitter:image:alt"]', 'content', $alt_text); - }; - $assert_image($node->field_featured_image->entity); - $node->set('field_seo_image', $this->generateImage('jpg')); - $save_node(); - $assert_image($node->field_seo_image->entity); - - // Assert the meta tags for the node title and that field_seo_title takes - // precedence over it. - $assert_title = function (string $title) use ($assert_session, $site_name): void { - $assert_session->elementAttributeContains('css', 'meta[property="og:title"]', 'content', $title); - $assert_session->elementAttributeContains('css', 'meta[name="twitter:title"]', 'content', $title); - $assert_session->titleEquals("$title | $site_name"); - }; - $assert_title($node->getTitle()); - $seo_title = $this->randomMachineName(); - $node->set('field_seo_title', $seo_title); - $save_node(); - $assert_title($seo_title); - - // Assert the meta tags for field_description and that field_seo_description - // takes precedence over it. - $assert_description = function (string $description) use ($assert_session): void { - $assert_session->elementAttributeContains('css', 'meta[name="description"]', 'content', $description); - $assert_session->elementAttributeContains('css', 'meta[property="og:description"]', 'content', $description); - $assert_session->elementAttributeContains('css', 'meta[name="twitter:description"]', 'content', $description); - }; - $assert_description($node->field_description->value); - $node->set('field_seo_description', $random->sentences(4)); - $save_node(); - $assert_description($node->field_seo_description->value); - } - -}