├── templates
├── partials
│ ├── microdata.html.twig
│ └── seo_data.html.twig
└── forms
│ └── fields
│ ├── seobutton
│ └── seobutton.html.twig
│ ├── json
│ └── json.html.twig
│ ├── schema
│ └── schema.html.twig
│ ├── twitter
│ └── twitter.html.twig
│ ├── google
│ └── google.html.twig
│ └── facebook
│ └── facebook.html.twig
├── assets
├── logoseo.png
├── twitter.gif
├── twitter.png
├── facebook.gif
├── gravlogo3.png
├── article_json.png
├── logofacebook.jpg
└── demoseoplugin.gif
├── seo.yaml
├── LICENSE
├── languages
├── en.yaml
├── ro.yaml
├── nl.yaml
└── de.yaml
├── blueprints.yaml
├── CHANGELOG.md
├── README.md
├── css
└── yoast-seo.min.css
├── seo.php
└── blueprints
└── seo.yaml
/templates/partials/microdata.html.twig:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/logoseo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulmassen/grav-plugin-seo/HEAD/assets/logoseo.png
--------------------------------------------------------------------------------
/assets/twitter.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulmassen/grav-plugin-seo/HEAD/assets/twitter.gif
--------------------------------------------------------------------------------
/assets/twitter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulmassen/grav-plugin-seo/HEAD/assets/twitter.png
--------------------------------------------------------------------------------
/assets/facebook.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulmassen/grav-plugin-seo/HEAD/assets/facebook.gif
--------------------------------------------------------------------------------
/assets/gravlogo3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulmassen/grav-plugin-seo/HEAD/assets/gravlogo3.png
--------------------------------------------------------------------------------
/assets/article_json.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulmassen/grav-plugin-seo/HEAD/assets/article_json.png
--------------------------------------------------------------------------------
/assets/logofacebook.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulmassen/grav-plugin-seo/HEAD/assets/logofacebook.jpg
--------------------------------------------------------------------------------
/templates/forms/fields/seobutton/seobutton.html.twig:
--------------------------------------------------------------------------------
1 | Here is some text
--------------------------------------------------------------------------------
/assets/demoseoplugin.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paulmassen/grav-plugin-seo/HEAD/assets/demoseoplugin.gif
--------------------------------------------------------------------------------
/seo.yaml:
--------------------------------------------------------------------------------
1 |
2 | enabled: true # Set to false to disable this plugin completely
3 | article: true
4 | restaurant: true
5 | event: true
6 | organization: true
7 | musicevent: true
8 | person: true
9 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | MIT LICENSE
3 | -----------
4 |
5 | Copyright (c) 2017 Paul Massendari, https://github.com/paulmassen/grav-plugin-seo
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 |
25 |
--------------------------------------------------------------------------------
/templates/forms/fields/json/json.html.twig:
--------------------------------------------------------------------------------
1 | {% if field.security is empty or authorize(array(field.security)) %}
2 |
3 | {% if field.title or field.underline %}
4 |
{% if grav.twig.twig.filters['tu'] is defined %}{{ field.title|tu }}{% else %}{{ field.title|t }}{% endif %}
5 | {% endif %}
6 |
7 | {% set context = admin.page(true) %}
8 |
43 | Envoyer
44 |
45 | {% if field.text %}
46 | {% endif %}
47 |
48 | {% if field.fields %}
49 |
50 | {% for field in field.fields %}
51 | {% if field.type %}
52 | {% set value = data.value(field.name) %}
53 | {% include ["forms/fields/#{field.type}/#{field.type}.html.twig", 'forms/fields/text/text.html.twig'] %}
54 | {% endif %}
55 | {% endfor %}
56 |
57 | {% endif %}
58 |
59 | {% endif %}
--------------------------------------------------------------------------------
/templates/forms/fields/schema/schema.html.twig:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/templates/partials/seo_data.html.twig:
--------------------------------------------------------------------------------
1 | {% set settings = config.plugins.seo.header %}
2 |
3 |
4 |
5 |
6 |
7 | {# if settings.robots or page.header.robots is defined %}
8 |
9 | {% endif #}
10 |
11 | {# #}
12 | {# twitter #}
13 |
14 | {% if page.header.facebookenable != "0" %}
15 |
16 |
17 | {% if page.header.facebookimg %}
18 |
19 | {% else %}
20 |
21 | {% endif %}
22 |
23 | {% endif %}
24 |
25 |
26 | {% if header.articleenabled %}
27 | {% set fullimagepath = page.url(true) ~ "/" ~ header.article.image.url %}
28 | {% set fulllogopath = page.url(true) ~ "/" ~ header.article.publisher.logo.url %}
29 | {% set article = header.article|merge({'image' : {
30 | 'url': fullimagepath,
31 | '@type': 'ImageObject',
32 | 'height': header.article.image.height,
33 | 'width': header.article.image.width
34 |
35 | } }) %}
36 | {% set article = article|merge({'publisher': { '@type': 'Organization', 'name': header.article.publisher.name, 'logo':{'@type': 'ImageObject', 'url': fulllogopath } } }) %}
37 |
40 | {% endif %}
41 | {% if header.personenabled %}
42 |
45 | {% endif %}
46 | {% if header.eventenabled %}
47 |
50 | {% endif %}
51 | {% if header.musicalbumenabled %}
52 | {% set fullalbumimgpath = page.url(true) ~ "/" ~ header.musicalbum.image %}
53 | {% set musicalbum = header.musicalbum|merge({'image' : fullalbumimgpath }) %}
54 |
57 | {% endif %}
58 | {% if header.restaurantenabled %}
59 | {% set fullrestaurantimgpath = page.url(true) ~ "/" ~ header.restaurant.image %}
60 | {% set restaurant = header.restaurant|merge({'image' : fullrestaurantimgpath }) %}
61 |
64 | {% endif %}
65 | {% if header.musiceventenabled %}
66 |
74 | {% endif %}
75 |
76 |
--------------------------------------------------------------------------------
/templates/forms/fields/twitter/twitter.html.twig:
--------------------------------------------------------------------------------
1 |
2 | {% if admin.route %}
3 | {% set context = admin.page(true) %}
4 | {% endif %}
5 | {% if field.title or field.underline %}
6 | {% if grav.twig.twig.filters['tu'] is defined %}{{ field.title|tu }}{% else %}{{ field.title|t }}{% endif %}
7 | {% endif %}
8 |
9 | {% set context = admin.page(true) %}
10 |
22 |
23 |
24 |
25 |
44 | {% if field.text %}
45 | {% endif %}
46 |
47 | {% if field.fields %}
48 |
49 | {% for field in field.fields %}
50 | {% if field.type %}
51 | {% set value = data.value(field.name) %}
52 | {% include ["forms/fields/#{field.type}/#{field.type}.html.twig", 'forms/fields/text/text.html.twig'] %}
53 | {% endif %}
54 | {% endfor %}
55 |
56 | {% endif %}
57 |
--------------------------------------------------------------------------------
/templates/forms/fields/google/google.html.twig:
--------------------------------------------------------------------------------
1 | {% if admin.route %}
2 | {% set context = admin.page(true) %}
3 | {% endif %}
4 | {% set title = (context.header.title ?: context.title) %}
5 | {% if field.title or field.underline %}
6 | {% if grav.twig.twig.filters['tu'] is defined %}{{ field.title|tu }}{% else %}{{ field.title|t }}{% endif %}
7 | {% endif %}
8 |
9 |
10 |
11 |
12 |
14 |
{{context.url(true)|replace({"//":"//", "/":" › " }) }}
15 |
{{ context.header.googledesc|default(context.summary|striptags|truncate(140)) }}
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
36 | {% if field.text %}
37 | {{ field.text|raw }}
38 | {% endif %}
39 |
40 | {% if field.fields %}
41 |
42 | {% for field in field.fields %}
43 | {% if field.type %}
44 | {% set value = data.value(field.name) %}
45 | {% include ["forms/fields/#{field.type}/#{field.type}.html.twig", 'forms/fields/text/text.html.twig'] %}
46 | {% endif %}
47 | {% endfor %}
48 |
49 | {% endif %}
50 |
51 |
--------------------------------------------------------------------------------
/languages/en.yaml:
--------------------------------------------------------------------------------
1 | PLUGIN_SEO:
2 | ROBOTS: "Select robots meta value"
3 | CANONICAL_URL: "Canonical URL"
4 | PLUGIN_STATUS: "Plugin status"
5 | STATUS_HELP: "Set to false to disable this plugin completely."
6 | GOOGLE_DESC: "Override Description"
7 | GOOGLE_TITLE: "Override Title"
8 | GOOGLE_PREVIEWDESC: "Here is a preview of your page on Google results"
9 | TWITTER_ENABLE: "Activate twitter card"
10 | TWITTER_CARD_SELECT: "Select twitter card type"
11 | TWITTER_CARD_GALLERY: "Select "
12 | TWITTER_CARD_PHOTO: "Photo"
13 | TWITTER_CARD_PRODUCT: "Product"
14 | TWITTER_CARD_SUMMARY: "Summary"
15 | TWITTER_CARD_PLAYER: "Player"
16 | TWITTER_CARD_APP: "App"
17 | TWITTER_CARD_SUMLARGIMG: "Summary Large Image"
18 | TWITTER_CARD_SECTITLE: "Twitter Card"
19 | TWITTER_SHAREIMG: "Twitter Image"
20 | TWITTER_TITLE: "Twitter title"
21 | TWITTER_DESCRIPTION: "Twitter Description"
22 | TWITTER_PREVIEWDESC: "Here is a preview of your page as shared on twitter"
23 | FACEBOOK_ENABLE: "Enable facebook"
24 | FACEBOOK_TITLE: "Facebook Title"
25 | FACEBOOK_DESC: "Facebook Description"
26 | FACEBOOK_SHAREIMG: "Facebook Share Image"
27 | FACEBOOK_PREVIEWDESC: "Here is a preview of your page as shared on Facebook"
28 | IMAGE_HEIGHT_PX: "Image Height (px)"
29 | IMAGE_WIDTH_PX: "Image Width (px)"
30 | ARTICLE_IMAGE: "Article Image"
31 | DATE_PUBLISHED: "Published date"
32 | DATE_MODIFIED: "Modification date"
33 | ARTICLE_DESCRIPTION: "Article Description"
34 | HEADLINE: "Headline"
35 | ADD_ARTICLE_MICRODATA: "Add Article Microdata"
36 | ARTICLE_AUTHOR: "Article Author"
37 | ARTICLE_PLACEHOLDER: "Will use page title if left empty"
38 | ARTICLE_DESC_PLACEHOLDER: "Will use summary if left empty"
39 | ARTICLE_PUBLISHER: "Article Publisher"
40 | ENABLEMUSICEVENT: "Enable Music Event"
41 | PUBLISHER_LOGO: "Publisher Logo"
42 | PUBLISHER_NAME: "Publisher Name"
43 | ARTICLE_BODY: "Full Article Body"
44 | ADDMUSICEVENT: "Add Music Event Microdata"
45 | LOCATION_NAME: "Location Name"
46 | LOCATION_ADDRESS: "Location Address"
47 | MUSICEVENT_NAME: "Music Event Name"
48 | MUSICEVENT_DESCRIPTION: "Description"
49 | MUSICEVENT_IMAGE: "Event Image"
50 | MUSICEVENT_URL: "Music Event Url"
51 | PREORDER: "Preorder"
52 | OUTOFSTOCK: "Out of Stock"
53 | PRESALE: "Pre Sale"
54 | INSTOCK: "In Stock"
55 | DISCONTINUED: "Discontinued"
56 | INSTOREONLY: "In Store Only"
57 | SOLDOUT: "Sold Out"
58 | ONLINEONLY: "Online Only"
59 | TICKET_URL: "Ticket URL"
60 | VALID_FROM: "Valid From"
61 | MUSICEVENT_PRICE: "Price"
62 | PRICE_CURRENCY: "Price Currency"
63 | ADD_PERFORMER: "Add Performer"
64 | PERFORMER_TYPE: "Performer Type"
65 | MUSICGROUP: "Music Group"
66 | PERSON: "Person"
67 | PERFORMER_NAME: "Performer Name"
68 | MUSICEVENT_DATE_START: "Start Date"
69 | MUSICEVENT_DATE_END: "End Date"
70 | WORK_PERFORMED: "Works Performed"
71 | WORK_PERFORMED_NAME: "Name of work"
72 | ADD_PERSON: "Add Person Microdata"
73 | PERSON_NAME: "Person Name"
74 | PERSON_JOB_TITLE: "Job Title"
75 | PERSON_ADDRESS_LOCALITY: "Address Locality"
76 | PERSON_ADDRESS_REGION: "Address Region"
77 | ADD_EVENT: "Add Event Microdata"
78 | EVENT_NAME: "Event Name"
79 | ENABLEEVENT: "Enable Event Microdata"
80 | EVENT_START_DATE: "Event Start Date"
81 | EVENT_END_DATE: "Event End Date"
82 | EVENT_DESCRIPTION: "Event Description"
83 | EVENT_LOCATION_NAME: "Event Location Name"
84 | EVENT_LOCATION_STREET_ADDRESS: "Event Location Street Address"
85 | EVENT_LOCATION_ADDRESS_LOCALITY: "Event Location Address Locality"
86 | EVENT_LOCATION_ADDRESS_REGION: "Event Location Region"
87 | EVENT_OFFER_PRICE: "Event Offer Price"
88 | EVENT_OFFER_CURRENCY: "Event Offer Currency"
89 | EVENT_OFFER_URL: "Event Offer Url"
90 | ADD_MUSICALBUM: "Add Music Album Microdata"
91 | MUSICALBUM_NAME: "Music Album Name"
92 | MUSICALBUM_NAMEOFBAND: "Name of Band"
93 | MUSICALBUM_IMAGE: "Image"
94 | MUSICALBUM_URL: "Album URL"
95 | MUSICALBUM_GENRE: "Genre"
96 | MUSICALBUM_TRACK_NUMBER: "Track Number"
97 | MUSICALBUM_ADD_TRACK: "Add Track"
98 | MUSICALBUM_TRACK_POSITION: "Track Position"
99 | MUSICALBUM_TRACK_NAME: "Track Name"
100 | MUSICALBUM_TRACK_URL: "Track URL"
101 | MUSICALBUM_TRACK_DURATION: "Track Duration"
102 | LOCATION_URL: "Location Url"
103 | ADD_RESTAURANT: "Add Restaurant Microdata"
104 | RESTAURANT_NAME: "Restaurant Name"
105 | RESTAURANT_ACCEPT_RESERVATION: "Accept Reservation"
106 | RESTAURANT_MENU_URL: "Menu URL"
107 | RESTAURANT_IMAGE: "Image"
108 | RESTAURANT_CUISINE: "Cuisine"
109 | RESTAURANT_PRICE_RANGE: "Price Range"
110 | RESTAURANT_POSTAL_CODE: "Postal Code"
111 | RESTAURANT_STREET: "Street"
112 | RESTAURANT_LOCALITY: "Locality"
113 | LOCATION_URL_PLACEHOLDER: "Url to the venue website"
114 | RESTAURANT_REGION: "Region"
115 | RESTAURANT_TELEPHONE: "Telephone"
116 | ENABLE_PERSON: "Enable Person Microdata"
117 | ENABLEORGA: "Enable Organization Microdata"
118 | MUSICEVENT_URL_PLACEHOLDER: "Url to the official page of this music event"
--------------------------------------------------------------------------------
/languages/ro.yaml:
--------------------------------------------------------------------------------
1 | PLUGIN_SEO:
2 | ROBOTS: "Selectează valoare pentru roboții meta"
3 | CANONICAL_URL: "URL canonical"
4 | PLUGIN_STATUS: "Status modul"
5 | STATUS_HELP: "Setează ”fals” pentru a dezactiva acest modul complet."
6 | GOOGLE_DESC: "Adaugă descrierea pentru Google"
7 | GOOGLE_TITLE: "Setează titlul pentru Google"
8 | GOOGLE_PREVIEWDESC: "Acesta este previzualizarea paginii așa cum apare în rezultatele Google"
9 | TWITTER_ENABLE: "Activează cardul Twitter"
10 | TWITTER_CARD_SELECT: "Selectează tipul de card Twitter"
11 | TWITTER_CARD_GALLERY: "Selectează "
12 | TWITTER_CARD_PHOTO: "Imagine"
13 | TWITTER_CARD_PRODUCT: "Produs"
14 | TWITTER_CARD_SUMMARY: "Rezumat"
15 | TWITTER_CARD_PLAYER: "Jucător"
16 | TWITTER_CARD_APP: "Aplicație"
17 | TWITTER_CARD_SUMLARGIMG: "Imagine mare pentu Rezumat"
18 | TWITTER_CARD_SECTITLE: "Cardul Twitter"
19 | TWITTER_SHAREIMG: "Imaginea Twitter"
20 | TWITTER_TITLE: "Titlul Twitter"
21 | TWITTER_DESCRIPTION: "Descrierea Twitter"
22 | TWITTER_PREVIEWDESC: "Acesta este previzualizarea paginii așa cum apare pe Twitter"
23 | FACEBOOK_ENABLE: "Activează Facebook"
24 | FACEBOOK_TITLE: "Titlul Facebook"
25 | FACEBOOK_DESC: "Descrierea Facebook"
26 | FACEBOOK_SHAREIMG: "Imaginea pentru Facebook"
27 | FACEBOOK_PREVIEWDESC: "Acesta este previzualizarea paginii așa cum apare pe Facebook"
28 | IMAGE_HEIGHT_PX: "Înălțimea Imaginii (px)"
29 | IMAGE_WIDTH_PX: "Lățimea Imaginii (px)"
30 | ARTICLE_IMAGE: "Imaginea Articolului"
31 | DATE_PUBLISHED: "Data publicării"
32 | DATE_MODIFIED: "Data modificării"
33 | ARTICLE_DESCRIPTION: "Descrierea articolului"
34 | HEADLINE: "Titlu"
35 | ADD_ARTICLE_MICRODATA: "Adaugă Microdata pentru articol"
36 | ARTICLE_AUTHOR: "Autorul articolului"
37 | ARTICLE_PUBLISHER: "Publicistul articolului"
38 | ENABLEMUSICEVENT: "Activează Evenimentul Muzică"
39 | PUBLISHER_LOGO: "Logo-ul publicistului"
40 | PUBLISHER_NAME: "Numele publicistului"
41 | ARTICLE_BODY: "Conținutul complet al articolului"
42 | ADDMUSICEVENT: "Adaugă Microdata pentru evenimentul muzical"
43 | LOCATION_NAME: "Numele locației"
44 | LOCATION_ADDRESS: "Adresa locației"
45 | MUSICEVENT_NAME: "Numele evenimentului muzical"
46 | MUSICEVENT_DESCRIPTION: "Descrierea"
47 | MUSICEVENT_IMAGE: "Imaginea evenimentului"
48 | MUSICEVENT_URL: "Link-ul evenimentului"
49 | PREORDER: "Precomandă"
50 | OUTOFSTOCK: "Nu este în stoc"
51 | PRESALE: "Prevânzare"
52 | INSTOCK: "În stoc"
53 | DISCONTINUED: "Nu mai este disponibil"
54 | INSTOREONLY: "Doar în magazin"
55 | SOLDOUT: "Toate copiile vândute"
56 | ONLINEONLY: "Doar pe internet"
57 | TICKET_URL: "Link pentru bilete"
58 | VALID_FROM: "Valid de la"
59 | MUSICEVENT_PRICE: "Preț"
60 | PRICE_CURRENCY: "Moneda prețului"
61 | ADD_PERFORMER: "Adaugă artist"
62 | PERFORMER_TYPE: "Tipul artisului"
63 | MUSICGROUP: "Grupul muzical"
64 | PERSON: "Persoană"
65 | PERFORMER_NAME: "Numele artistului"
66 | MUSICEVENT_DATE_START: "Ora de începere"
67 | MUSICEVENT_DATE_END: "Ora de terminare"
68 | WORK_PERFORMED: "Listă cântece"
69 | WORK_PERFORMED_NAME: "Numele cântecelor"
70 | ADD_PERSON: "Adaugă Microdata pentru persoană"
71 | PERSON_NAME: "Numele persoanei"
72 | PERSON_JOB_TITLE: "Funcția"
73 | PERSON_ADDRESS_LOCALITY: "Localitatea"
74 | PERSON_ADDRESS_REGION: "Regiunea / Județul"
75 | ADD_EVENT: "Adaugă Microdata pentru eveniment"
76 | EVENT_NAME: "Numele evenimentului"
77 | EVENT_START_DATE: "Data de începere"
78 | EVENT_END_DATE: "Data de terminare"
79 | EVENT_DESCRIPTION: "Descrierea evenimentului"
80 | EVENT_LOCATION_NAME: "Locația evenimentului"
81 | EVENT_LOCATION_STREET_ADDRESS: "Strada"
82 | EVENT_LOCATION_ADDRESS_LOCALITY: "Localitatea"
83 | EVENT_LOCATION_ADDRESS_REGION: "Regiunea / Județul"
84 | EVENT_OFFER_PRICE: "Oferta de preț pentru eveniment"
85 | EVENT_OFFER_CURRENCY: "Moneda prețului"
86 | EVENT_OFFER_URL: "Link-ul evenimentului"
87 | ADD_MUSICALBUM: "Adaugă Microdata pentru album"
88 | MUSICALBUM_NAME: "Numele albumului"
89 | MUSICALBUM_NAMEOFBAND: "Numele formației"
90 | MUSICALBUM_IMAGE: "Imaginea"
91 | MUSICALBUM_URL: "Link-ul album"
92 | MUSICALBUM_GENRE: "Tipul de muzică"
93 | MUSICALBUM_TRACK_NUMBER: "Numărul cântecului"
94 | MUSICALBUM_ADD_TRACK: "Adaugă cântec"
95 | MUSICALBUM_TRACK_POSITION: "Poziția cântecului"
96 | MUSICALBUM_TRACK_NAME: "Numele cântecului"
97 | MUSICALBUM_TRACK_URL: "Link-ul cântecului"
98 | MUSICALBUM_TRACK_DURATION: "Durata cântecului"
99 | LOCATION_URL: "Link-ul Locației"
100 | ADD_RESTAURANT: "Adaugă Microdata pentru Restaurant"
101 | RESTAURANT_NAME: "Numele Restaurantului"
102 | RESTAURANT_ACCEPT_RESERVATION: "Acceptă Rezervări"
103 | RESTAURANT_MENU_URL: "Link-ul meniului"
104 | RESTAURANT_IMAGE: "Imaginea"
105 | RESTAURANT_CUISINE: "Tip de bucătărie"
106 | RESTAURANT_PRICE_RANGE: "Prețuri"
107 | RESTAURANT_POSTAL_CODE: "Codul Poștal"
108 | RESTAURANT_STREET: "Strada"
109 | RESTAURANT_LOCALITY: "Localitatea"
110 | RESTAURANT_REGION: "Regiunea / Județul"
111 | RESTAURANT_TELEPHONE: "Număr de Telefon"
112 |
--------------------------------------------------------------------------------
/languages/nl.yaml:
--------------------------------------------------------------------------------
1 | PLUGIN_SEO:
2 | ROBOTS: "Selecteer robots meta waarde"
3 | CANONICAL_URL: "Canonical URL"
4 | PLUGIN_STATUS: "Plugin status"
5 | STATUS_HELP: "Zet op false om deze plugin volledig stop te zetten."
6 | GOOGLE_DESC: "Overschrijf omschrijving"
7 | GOOGLE_TITLE: "Overschrijf titel"
8 | GOOGLE_PREVIEWDESC: "Hier is een preview van jouw pagina in de google resultaten."
9 | TWITTER_ENABLE: "Activeer twitter kaart"
10 | TWITTER_CARD_SELECT: "Selecteer twitter kaart type"
11 | TWITTER_CARD_GALLERY: "Selecteer"
12 | TWITTER_CARD_PHOTO: "Foto"
13 | TWITTER_CARD_PRODUCT: "Product"
14 | TWITTER_CARD_SUMMARY: "Samenvatting"
15 | TWITTER_CARD_PLAYER: "Speler"
16 | TWITTER_CARD_APP: "App"
17 | TWITTER_CARD_SUMLARGIMG: "Samenvatting grootte afbeelding"
18 | TWITTER_CARD_SECTITLE: "Twitter kaart"
19 | TWITTER_SHAREIMG: "Twitter Afbeelding"
20 | TWITTER_TITLE: "Twitter titel"
21 | TWITTER_DESCRIPTION: "Twitter Omschrijving"
22 | TWITTER_PREVIEWDESC: "Hier is een preview van jouw pagina op twitter"
23 | FACEBOOK_ENABLE: "Activeer facebook"
24 | FACEBOOK_TITLE: "Facebook Titel"
25 | FACEBOOK_DESC: "Facebook Omschrijving"
26 | FACEBOOK_SHAREIMG: "Facebook Deel Afbeelding"
27 | FACEBOOK_PREVIEWDESC: "Hier is een preview van jouw pagina op Facebook"
28 | IMAGE_HEIGHT_PX: "Hoogte afbeelding (px)"
29 | IMAGE_WIDTH_PX: "Afbeelding breedte (px)"
30 | ARTICLE_IMAGE: "Artikel afbeelding"
31 | DATE_PUBLISHED: "Publicatie datum"
32 | DATE_MODIFIED: "Modificatie datum"
33 | ARTICLE_DESCRIPTION: "Artikel Omschrijving"
34 | HEADLINE: "Kopstuk"
35 | ADD_ARTICLE_MICRODATA: "Voeg artike microdata toe"
36 | ARTICLE_AUTHOR: "Auteur artikel"
37 | ARTICLE_PLACEHOLDER: "Pagina titel zal gebruikt worden indien leeg"
38 | ARTICLE_DESC_PLACEHOLDER: "Samenvatting zal gebruikt worden indien leeg"
39 | ARTICLE_PUBLISHER: "Auteur artikel"
40 | ENABLEMUSICEVENT: "Activeer muziek event"
41 | PUBLISHER_LOGO: "Auteur Logo"
42 | PUBLISHER_NAME: "Auteur Naam"
43 | ARTICLE_BODY: "Artiekel inhoud"
44 | ADDMUSICEVENT: "Voeg muziek microdata event toe"
45 | LOCATION_NAME: "Locatie Naam"
46 | LOCATION_ADDRESS: "Locatie adres"
47 | MUSICEVENT_NAME: "Naam muziek event"
48 | MUSICEVENT_DESCRIPTION: "Omschrijving"
49 | MUSICEVENT_IMAGE: "Afbeelding event"
50 | MUSICEVENT_URL: "Muziek Event Url"
51 | PREORDER: "Preorder"
52 | OUTOFSTOCK: "Niet in Stock"
53 | PRESALE: "Voorverkoop"
54 | INSTOCK: "In Stock"
55 | DISCONTINUED: "Stopgezet"
56 | INSTOREONLY: "In Store Only"
57 | SOLDOUT: "Uitverkocht"
58 | ONLINEONLY: "Alleen online"
59 | TICKET_URL: "Ticket URL"
60 | VALID_FROM: "Geldig vanaf"
61 | MUSICEVENT_PRICE: "Prijs"
62 | PRICE_CURRENCY: "Prijs valuta"
63 | ADD_PERFORMER: "Voeg artiest toe"
64 | PERFORMER_TYPE: "Artiest Type"
65 | MUSICGROUP: "Muziek groep"
66 | PERSON: "Persoon"
67 | PERFORMER_NAME: "Artiest naam"
68 | MUSICEVENT_DATE_START: "Start datum"
69 | MUSICEVENT_DATE_END: "Eind Datum"
70 | WORK_PERFORMED: "Works Performed"
71 | WORK_PERFORMED_NAME: "Naam werk"
72 | ADD_PERSON: "Voeg persoon microdata toe"
73 | PERSON_NAME: "Persoon Naam"
74 | PERSON_JOB_TITLE: "Job Titel"
75 | PERSON_ADDRESS_LOCALITY: "Adres Locality"
76 | PERSON_ADDRESS_REGION: "Adres regio"
77 | ADD_EVENT: "Voeg Event Microdata toe"
78 | EVENT_NAME: "Event Naam"
79 | ENABLEEVENT: "Voeg Event Microdata toe"
80 | EVENT_START_DATE: "Event Start Datum"
81 | EVENT_END_DATE: "Event Eind Datum"
82 | EVENT_DESCRIPTION: "Event Omschrijving"
83 | EVENT_LOCATION_NAME: "Event locatie naam"
84 | EVENT_LOCATION_STREET_ADDRESS: "Event Locatie Straat adres"
85 | EVENT_LOCATION_ADDRESS_LOCALITY: "Event locatie adres Locality"
86 | EVENT_LOCATION_ADDRESS_REGION: "Event locatie regio"
87 | EVENT_OFFER_PRICE: "Event Prijs"
88 | EVENT_OFFER_CURRENCY: "Event Valuta"
89 | EVENT_OFFER_URL: "Event aanbieding Url"
90 | ADD_MUSICALBUM: "Voeg Music Album Microdata toe"
91 | MUSICALBUM_NAME: "Muziek Album Naam"
92 | MUSICALBUM_NAMEOFBAND: "Naam Band"
93 | MUSICALBUM_IMAGE: "Afbeelding"
94 | MUSICALBUM_URL: "Album URL"
95 | MUSICALBUM_GENRE: "Genre"
96 | MUSICALBUM_TRACK_NUMBER: "Muzieknummer"
97 | MUSICALBUM_ADD_TRACK: "Voeg Track toe"
98 | MUSICALBUM_TRACK_POSITION: "Track Positie"
99 | MUSICALBUM_TRACK_NAME: "Track Naam"
100 | MUSICALBUM_TRACK_URL: "Track URL"
101 | MUSICALBUM_TRACK_DURATION: "Track looptijd"
102 | LOCATION_URL: "Locatie Url"
103 | ADD_RESTAURANT: "Voeg Restaurant Microdata toe"
104 | RESTAURANT_NAME: "Restaurant Naam"
105 | RESTAURANT_ACCEPT_RESERVATION: "Accepteer Reservatie"
106 | RESTAURANT_MENU_URL: "Menu URL"
107 | RESTAURANT_IMAGE: "Afbeelding"
108 | RESTAURANT_CUISINE: "Keuken"
109 | RESTAURANT_PRICE_RANGE: "Prijs"
110 | RESTAURANT_POSTAL_CODE: "Post code"
111 | RESTAURANT_STREET: "Straat"
112 | RESTAURANT_LOCALITY: "Plaats"
113 | LOCATION_URL_PLACEHOLDER: "Url naar het menu op de website"
114 | RESTAURANT_REGION: "Regio"
115 | RESTAURANT_TELEPHONE: "Telefoon"
116 | ENABLE_PERSON: "Voeg persoon Microdata toe"
117 | ENABLEORGA: "Voeg Organisatie Microdata toe"
118 | MUSICEVENT_URL_PLACEHOLDER: "Url naar de officiële pagina van het muziek event"
--------------------------------------------------------------------------------
/blueprints.yaml:
--------------------------------------------------------------------------------
1 | name: "SEO"
2 | version: "3.0.0"
3 | description: "Manage your site’s meta tags for display in search engine results or social media networks. Includes an easy-to-use live preview feature."
4 | icon: "google"
5 | testing: true
6 | author:
7 | name: "Paul Massendari"
8 | email: "paul@massendari.com"
9 | homepage: "https://github.com/paulmassen/grav-plugin-seo"
10 | keywords: ["seo", "meta", "microdata", "schema", "plugin"]
11 | bugs: "https://github.com/paulmassen/grav-plugin-seo/issues"
12 | license: "MIT/GPL"
13 | dependencies:
14 | - { name: grav, version: '>=1.7.0' }
15 | - { name: admin, version: '>=1.10.0' }
16 |
17 | form:
18 | validation: strict
19 | fields:
20 | plugin_section:
21 | type: section
22 | title: General Settings
23 | underline: true
24 | enabled:
25 | type: toggle
26 | label: PLUGIN_ADMIN.PLUGIN_STATUS
27 | highlight: 1
28 | default: 1
29 | options:
30 | 1: PLUGIN_ADMIN.ENABLED
31 | 0: PLUGIN_ADMIN.DISABLED
32 | validate:
33 | type: bool
34 | facebookid:
35 | type: text
36 | label: Facebook App ID
37 | twitterid:
38 | type: text
39 | label: Twitter ID
40 | placeholder: '@yourusername'
41 | twitter_default:
42 | type: toggle
43 | label: On page creation, enable twitter metadata?
44 | default: 1
45 | highlight: 1
46 | options:
47 | 1: PLUGIN_ADMIN.ENABLED
48 | 0: PLUGIN_ADMIN.DISABLED
49 | facebook_default:
50 | type: toggle
51 | label: On page creation, enable facebook metadata?
52 | default: 1
53 | highlight: 1
54 | options:
55 | 1: PLUGIN_ADMIN.ENABLED
56 | 0: PLUGIN_ADMIN.DISABLED
57 |
58 | microdata_section:
59 | type: section
60 | title: Microdata Settings
61 | underline: true
62 | md_columns:
63 | type: columns
64 | fields:
65 | mdcolumn1:
66 | type: column
67 | fields:
68 | article:
69 | type: toggle
70 | label: Enable Article Microdata
71 | highlight: 1
72 | default: 1
73 | options:
74 | 1: PLUGIN_ADMIN.ENABLED
75 | 0: PLUGIN_ADMIN.DISABLED
76 | validate:
77 | type: bool
78 | event:
79 | type: toggle
80 | label: Enable Event Microdata
81 | highlight: 1
82 | default: 1
83 | options:
84 | 1: PLUGIN_ADMIN.ENABLED
85 | 0: PLUGIN_ADMIN.DISABLED
86 | validate:
87 | type: bool
88 | restaurant:
89 | type: toggle
90 | label: Enable Restaurant Microdata
91 | highlight: 1
92 | default: 1
93 | options:
94 | 1: PLUGIN_ADMIN.ENABLED
95 | 0: PLUGIN_ADMIN.DISABLED
96 | validate:
97 | type: bool
98 | musicevent:
99 | type: toggle
100 | label: Enable Music Event Microdata
101 | highlight: 1
102 | default: 1
103 | options:
104 | 1: PLUGIN_ADMIN.ENABLED
105 | 0: PLUGIN_ADMIN.DISABLED
106 | validate:
107 | type: bool
108 | customjson:
109 | type: toggle
110 | label: Enable Custom Json Microdata
111 | highlight: 1
112 | default: 1
113 | options:
114 | 1: PLUGIN_ADMIN.ENABLED
115 | 0: PLUGIN_ADMIN.DISABLED
116 | validate:
117 | type: bool
118 | mdcolumn2:
119 | type: column
120 | fields:
121 | person:
122 | type: toggle
123 | label: Enable Person Microdata
124 | highlight: 1
125 | default: 1
126 | options:
127 | 1: PLUGIN_ADMIN.ENABLED
128 | 0: PLUGIN_ADMIN.DISABLED
129 | validate:
130 | type: bool
131 | organization:
132 | type: toggle
133 | label: Enable Organization Microdata
134 | highlight: 1
135 | default: 1
136 | options:
137 | 1: PLUGIN_ADMIN.ENABLED
138 | 0: PLUGIN_ADMIN.DISABLED
139 | validate:
140 | type: bool
141 | musicalbum:
142 | type: toggle
143 | label: Enable Music Album Microdata
144 | highlight: 1
145 | default: 1
146 | options:
147 | 1: PLUGIN_ADMIN.ENABLED
148 | 0: PLUGIN_ADMIN.DISABLED
149 | validate:
150 | type: bool
151 | product:
152 | type: toggle
153 | label: Enable Product Microdata
154 | highlight: 1
155 | default: 1
156 | options:
157 | 1: PLUGIN_ADMIN.ENABLED
158 | 0: PLUGIN_ADMIN.DISABLED
159 | validate:
160 | type: bool
161 |
162 |
--------------------------------------------------------------------------------
/languages/de.yaml:
--------------------------------------------------------------------------------
1 | PLUGIN_SEO:
2 | ROBOTS: "Robots-Meta-Wert auswählen"
3 | CANONICAL_URL: "Kanonische URL"
4 | PLUGIN_STATUS: "Plugin-Status"
5 | STATUS_HELP: "Auf false setzen, um dieses Plugin komplett zu deaktivieren"
6 | GOOGLE_DESC: "Beschreibung überschreiben"
7 | GOOGLE_TITLE: "Überschreibungs-Titel"
8 | GOOGLE_PREVIEWDESC: "Hier sehen Sie eine Vorschau auf Ihre Seite in den Google-Ergebnissen"
9 | TWITTER_ENABLE: "Twitter-Karte aktivieren"
10 | TWITTER_CARD_SELECT: "Twitter-Kartentyp auswählen"
11 | TWITTER_CARD_GALLERY: "Wählen Sie "
12 | TWITTER_CARD_PHOTO: "Foto"
13 | TWITTER_CARD_PRODUCT: "Produkt"
14 | TWITTER_CARD_SUMMARY: "Zusammenfassung"
15 | TWITTER_CARD_PLAYER: "Spieler"
16 | TWITTER_CARD_APP: "Anwendung"
17 | TWITTER_CARD_SUMLARGIMG: "Zusammenfassung großes Bild"
18 | TWITTER_CARD_SECTITLE: "Twitter-Karte"
19 | TWITTER_SHAREIMG: "Twitter-Bild"
20 | TWITTER_TITLE: "Twitter-Titel"
21 | TWITTER_DESCRIPTION: "Twitter-Beschreibung"
22 | TWITTER_PREVIEWDESC: "Hier ist eine Vorschau Ihrer Seite, wie sie auf Twitter geteilt wird"
23 | FACEBOOK_ENABLE: "Facebook aktivieren"
24 | FACEBOOK_TITLE: "Facebook-Titel"
25 | FACEBOOK_DESC: "Facebook Beschreibung"
26 | FACEBOOK_SHAREIMG: "Facebook-Freigabebild"
27 | FACEBOOK_PREVIEWDESC: "Hier ist eine Vorschau Ihrer Seite, wie sie auf Facebook geteilt wird"
28 | IMAGE_HEIGHT_PX: "Bildhöhe (px)"
29 | IMAGE_WIDTH_PX: "Bildbreite (px)"
30 | ARTICLE_IMAGE: "Artikel-Bild"
31 | DATE_PUBLISHED: "Veröffentlichungsdatum"
32 | DATE_MODIFIED: "Änderungsdatum"
33 | ARTICLE_DESCRIPTION: "Artikelbeschreibung"
34 | HEADLINE: "Überschrift"
35 | ADD_ARTICLE_MICRODATA: "Artikel-Mikrodaten hinzufügen"
36 | ARTICLE_AUTHOR: "Artikel-Autor"
37 | ARTICLE_PLACEHOLDER: "Wird Seitentitel verwenden, wenn leer gelassen"
38 | ARTICLE_DESC_PLACEHOLDER: "Verwendet Zusammenfassung, wenn leer gelassen"
39 | ARTICLE_PUBLISHER: "Artikel-Herausgeber"
40 | ENABLEMUSICEVENT: "Musik-Ereignis einschalten"
41 | PUBLISHER_LOGO: "Herausgeber-Logo"
42 | VERLAG_NAME: "Verlagsname"
43 | ARTICLE_BODY: "Vollständiger Artikeltext"
44 | ADDMUSICEVENT: "Musikereignis-Mikrodaten hinzufügen"
45 | LOCATION_NAME: "Ortsname"
46 | LOCATION_ADDRESS: "Location-Adresse"
47 | MUSIKEVENT_NAME: "Name des Musikevents"
48 | MUSICEVENT_DESCRIPTION: "Beschreibung"
49 | MUSICEVENT_IMAGE: "Event-Bild"
50 | MUSICEVENT_URL: "Musik-Event Url"
51 | PREORDER: "Vorbestellung"
52 | OUTOFSTOCK: "Nicht auf Lager"
53 | PRESALE: "Vorverkauf"
54 | INSTOCK: "Auf Lager"
55 | DISCONTINUED: "Abgekündigt"
56 | INSTOREONLY: "Nur im Lager"
57 | OUTOFSTOCK: "Nicht auf Lager"
58 | SOLDOUT: "Ausverkauft"
59 | ONLINEONLY: "Nur online"
60 | TICKET_URL: "Ticket-URL"
61 | VALID_FROM: "Gültig von"
62 | MUSICEVENT_PRICE: "Preis"
63 | PRICE_CURRENCY: "Preis-Währung"
64 | ADD_PERFORMER: "Darsteller hinzufügen"
65 | PERFORMER_TYPE: "Darsteller-Typ"
66 | MUSICGROUP: "Musikgruppe"
67 | PERSON: "Person"
68 | PERFORMER_NAME: "Name des Interpreten"
69 | MUSICEVENT_DATE_START: "Startdatum"
70 | MUSICEVENT_DATE_END: "Enddatum"
71 | WORK_PERFORMED: "Aufgeführte Werke"
72 | WERK_AUFGEFUEHRT_NAME: "Name der Arbeit"
73 | ADD_PERSON: "Personen-Mikrodaten hinzufügen"
74 | PERSON_NAME: "Name der Person"
75 | PERSON_JOB_TITLE: "Berufsbezeichnung"
76 | PERSON_ADDRESS_LOCALITY: "Ort"
77 | PERSON_ADDRESS_REGION: "Region"
78 | ADD_EVENT: "Ereignis-Mikrodaten hinzufügen"
79 | EVENT_NAME: "Ereignis-Name"
80 | ENABLEEVENT: "Veranstaltungs-Mikrodaten einschalten"
81 | EVENT_START_DATE: "Ereignis-Startdatum"
82 | EVENT_END_DATE: "Ereignis-Enddatum"
83 | EVENT_DESCRIPTION: "Ereignisbeschreibung"
84 | EVENT_LOCATION_NAME: "Name des Veranstaltungsortes"
85 | EVENT_LOCATION_STREET_ADDRESS: "Straße und Hausnummer Veranstaltungsortes"
86 | EVENT_LOCATION_ADDRESS_LOCALITY: "Postleitzahl und Ort der Veranstaltung"
87 | EVENT_LOCATION_ADDRESS_REGION: "Region des Veranstaltungsortes"
88 | EVENT_OFFER_PRICE: "Veranstaltungsangebotspreis"
89 | EVENT_OFFER_CURRENCY: "Veranstaltungsangebot Währung"
90 | EVENT_OFFER_URL: "Webseite der Veranstaltung"
91 | ADD_MUSICALBUM: "Musikalbum-Mikrodaten hinzufügen"
92 | MUSICALBUM_NAME: "Musikalbum-Name"
93 | MUSICALBUM_NAMEOFBAND: "Name der Band"
94 | MUSICALBUM_IMAGE: "Bild"
95 | MUSICALBUM_URL: "Album-URL"
96 | MUSICALBUM_GENRE: "Genre"
97 | MUSICALBUM_TRACK_NUMBER: "Titelnummer"
98 | MUSICALBUM_ADD_TRACK: "Track hinzufügen"
99 | MUSICALBUM_TRACK_POSITION: "Track-Position"
100 | MUSICALBUM_TRACK_NAME: "Track-Titel"
101 | MUSICALBUM_TRACK_URL: "Track-URL"
102 | MUSICALBUM_TRACK_DURATION: "Spieldauer"
103 | LOCATION_URL: "Standort-URL"
104 | ADD_RESTAURANT: "Restaurant-Mikrodaten hinzufügen"
105 | RESTAURANT_NAME: "Restaurantname"
106 | RESTAURANT_ACCEPT_RESERVATION: "Reservierung akzeptieren"
107 | RESTAURANT_MENU_URL: "Menü-URL"
108 | RESTAURANT_IMAGE: "Bild"
109 | RESTAURANT_CUISINE: "Küche"
110 | RESTAURANT_PRICE_RANGE: "Preisspanne"
111 | RESTAURANT_POSTAL_CODE: "Postleitzahl"
112 | RESTAURANT_STREET: "Straße"
113 | RESTAURANT_LOCALITY: "Ortschaft"
114 | LOCATION_URL_PLACEHOLDER: "Url zur Website des Veranstaltungsorts"
115 | RESTAURANT_REGION: "Region"
116 | RESTAURANT_TELEFON: "Telefon"
117 | ENABLE_PERSON: "Personen-Mikrodaten einschalten"
118 | ENABLEORGA: "Organisations-Mikrodaten aktivieren"
119 | MUSICEVENT_URL_PLACEHOLDER: "Url zur offiziellen Seite dieser Musikveranstaltung"
120 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # v2.3.6
2 | ## 09/14/2018
3 | 1. [](#new)
4 | * New field allows to add previously generated metadata
5 |
6 | # v2.3.5
7 | ## 09/14/2018
8 | 1. [](#fix)
9 | * Changed the currency field from a select field to a text field to allow rare currencies
10 | * Fixed the button to validate the page microdata
11 |
12 | # v2.3.4
13 | ## 03/19/2018
14 | 1. [](#fix)
15 | * Fixed whoops on opengraph image
16 |
17 | # v2.3.2
18 | ## 01/26/2018
19 | 1. [](#fix)
20 | * Fixed opengraph and twitter error
21 | * Fixed facebook default not fetched from plugin configuration
22 |
23 |
24 | # v2.3.1
25 | ## 01/26/2018
26 | 1. [](#fix)
27 | * Fixed whoops on twitter image
28 |
29 | # v2.3.0
30 | ## 01/26/2018
31 | 1. [](#fix)
32 | * Fixed tag not stripped from description
33 | * Added areaserved to organization and restaurant microdata
34 | * Fixed event date problem
35 |
36 | # v2.2.0
37 | ## 01/26/2018
38 | 1. [](#new)
39 | * Fixed script and style tags in page content causing problem
40 | * Few languages fixes
41 | * Re-added date modified and date published that mysteriously disappeared
42 |
43 | # v2.1.9
44 | ## 01/09/2018
45 | 1. [](#new)
46 | * Fixed Changelog causing trouble with GPM
47 |
48 | # v2.1.8
49 | ## 01/08/2018
50 | 1. [](#new)
51 | * Added Nederland translation
52 | * Fixed founder field causing crash when empty
53 | * Fixed default twitter image not being displayed
54 | * Fixed default values for opengraph and twitter
55 | * Small changes in microdata blueprints
56 |
57 | # v2.1.7
58 | ## 12/17/2017
59 | 1. [](#new)
60 | * Added product microdata
61 |
62 | # v2.1.6
63 | ## 12/12/2017
64 | 1. [](#new)
65 | * Added better styling for the fieldset field
66 | * Added icons on fieldsets fields
67 | * Added some required fields to the organization microdata
68 | * Added button label on the microdata tabs.
69 |
70 | 1. [](#fix)
71 | * Fixed the error Invalid Index Type on blueprints that did not use a "content" field
72 | * Fixed the music album microdata not being displayed
73 | * Removed duplicate attribute on the blueprint
74 |
75 | # v2.1.5
76 | ## 12/07/2017
77 | 1. [](#new)
78 | * Removed the empty script tags that appeared on page that did not use microdata
79 | * Added some required fields to the organization microdata
80 |
81 | # v2.1.4
82 | ## 11/22/2017
83 | 1. [](#fix)
84 | * Fixed the url of structured data testing tool for non-english language
85 |
86 | # v2.1.3
87 | ## 11/22/2017
88 | 1. [](#new)
89 | * Added a button to validate the page microdata with Google structured data testing tool
90 |
91 | # v2.1.2
92 | ## 10/12/2017
93 | 1. [](#bugfix)
94 | * Fixed site_name open graph
95 |
96 | # v2.1.1
97 | ## 10/12/2017
98 | 1. [](#bugfix)
99 | * Fixed duplicate toggle
100 |
101 | # v2.1.0
102 | ## 10/12/2017
103 | 1. [](#bugfix)
104 | * Added highlight to Toggle fields
105 | * Few languages fixes
106 | * Added url for Organization microdata
107 | * Few css fixes
108 | * Added more placeholder
109 |
110 | # v2.0.9
111 | ## 10/04/2017
112 | 1. [](#bugfix)
113 | * Fixed string manipulation causing error on some install
114 |
115 | # v2.0.8
116 | ## 10/04/2017
117 | 1. [](#new)
118 | * Added Logo url to Organization Microdata
119 |
120 | # v2.0.7
121 | ## 10/03/2017
122 | 1. [](#new)
123 | * Added Organization Microdata
124 |
125 | # v2.0.6
126 | ## 09/10/2017
127 | 1. [](#bugfix)
128 | * Changed Description
129 |
130 | # v2.0.5
131 | ## 09/10/2017
132 | 1. [](#bugfix)
133 | * First Stable Release - Reads the docs before updating from a 1.0.x Version!
134 | * Added Person Microdata
135 |
136 | # v2.0.4
137 | ## 09/10/2017
138 | 1. [](#bugfix)
139 | * Microdata is now automatically added to pages
140 | * Page date and last modified is modified automatically in article microdata
141 |
142 |
143 |
144 | # v2.0.3
145 | ## 09/08/2017
146 | 1. [](#bugfix)
147 | * Fixed error on empty fields
148 | * Added function for getting image width and height
149 |
150 |
151 | # v2.0.2
152 | ## 09/08/2017
153 | 1. [](#bugfix)
154 | * Fixed missing language.yaml entry
155 | * Added style vertical to microdata for better readability
156 | * Fixed many bugs
157 | * Fixed bug when image on a modular folder
158 |
159 | # v2.0.0
160 | ## 09/05/2017
161 |
162 | 1. [](#new)
163 | * Complete Refactor of the plugin with proper metadata integration
164 | * Users now just have to add {{json}} in the head of their base.html.twig
165 | * Added configuration for enabling or disabling microdata fields
166 | * Use of the fieldset and conditional fields
167 | * Changed filepicker for the new mediapicker field
168 |
169 | # v1.0.6
170 | ## 06/07/2017
171 |
172 | 1. [](#bugfix)
173 | * Added Twitter URL Meta
174 |
175 | # v1.0.5
176 | ## 06/06/2017
177 |
178 | 1. [](#bugfix)
179 | * Fix Twitter title not displayed correctly
180 |
181 | # v1.0.4
182 | ## 06/02/2017
183 |
184 | 1. [](#new)
185 | * New Microdata type: Music Event, MusicAlbum
186 | * Toggle will now display or hide the related fields
187 |
188 | # v1.0.3
189 | ## 06/01/2017
190 |
191 | 1. [](#new)
192 | * New feature: Microdata generation
193 | 2. [](#bugfix)
194 | * Fix Page title not rendered correctly
195 |
196 | # v0.9.1
197 | ## 06/01/2017
198 |
199 | 1. [](#new)
200 | * Removed the site-wide configuration.
201 | * Multiples layout fix
202 | 2. [](#bugfix)
203 | * Fix blueprint causing toggle fields to duplicate.
204 | * Fix fallback value when fields are not filled.
205 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 
2 |
3 | [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MX77VZWPUKLTU)
4 |
5 | ##### Table of Contents:
6 |
7 |
8 | * [About](#about)
9 | * [Features](#features)
10 | * [Installation and Updates](#installation-and-updates)
11 | * [Requirements](#requirements)
12 | * [Usage](#usage)
13 | * [Contributing](#contributing)
14 | * [License](#license)
15 |
16 |
17 | ## About
18 |
19 | `Seo` is an user-friendly plugin for [GetGrav.org](http://getgrav.org) used to manage all your metatags in order to customize your pages appearance in Search Engine Results or social networks. The plugin also allows the generation of JSON-LD Microdata.
20 |
21 | ## Features
22 |
23 | ### Google
24 | You can see and customize how your page will look on Google Search Results.
25 |
26 | 
27 |
28 | ### Twitter
29 | You can also preview how your page will look when shared on twitter
30 |
31 | 
32 |
33 |
34 | ### Facebook
35 | And on Facebook
36 |
37 | 
38 |
39 |
40 | ### JSON-LD
41 |
42 | You can also generate Schema.org JSON Microdata from the admin.
43 | 
44 | This will generate the following Json-ld between script tags
45 | ```JSON
46 | {
47 | "@context": "http://schema.org",
48 | "@type": "Article",
49 | "headline": "Article Title",
50 | "mainEntityOfPage": {
51 | "@type": "WebPage",
52 | "url": "http://yourwebsite.com"
53 | },
54 | "articleBody": "Lorem Ipsum dolor sit amet",
55 | "datePublished": "2017-12-01T00:00:00+00:00",
56 | "dateModified": "2019-01-01T00:00:00+00:00",
57 | "description": "Description of the article",
58 | "author": "Steve Jobs",
59 | "publisher": {
60 | "@type": "Organization",
61 | "name": "Apple",
62 | "logo": {
63 | "@type": "ImageObject",
64 | "url": "http://yourwebsite.com/home/logo.png",
65 | "width": "200",
66 | "height": "100"
67 | }
68 | },
69 | "image": {
70 | "@type": "ImageObject",
71 | "url": "http://yourwebsite.com/home/myimage.jpg",
72 | "width": "800",
73 | "height": "600"
74 | }
75 | }
76 | ```
77 |
78 | ## Requirements
79 |
80 | In order to use the plugin with a custom template, there is two requirements, you must:
81 | - Include in your base template the metadata template that comes shipped with antimatter, such as: `{% include 'partials/metadata.html.twig' %}`
82 | - For Microdatas, you must use Grav's asset manager. If your template has a line with `{{ assets.js() }}`, it will works.
83 | - The SEO tab extends the default blueprint, if it does not appear, make sure your blueprint extends the default blueprint with `extends@: default`
84 | #### Feedback needed
85 |
86 | As this plugin is in its early stage, please do not hesitate to leave a feedback, to suggest modification or features.
87 |
88 | ### TO-DO
89 |
90 | - [ ] Add more Microdata type
91 | - [ ] Add Translations (Contribution welcomed!)
92 | - [x] Add the possibility to add multiple microdata of the same type
93 | - [ ] YoastSEO text analysis integration (WIP)
94 | - [ ] Add some microdata on every page
95 |
96 |
97 |
98 |
99 | ## Installation and Updates
100 |
101 | ### Updating from Previous releases
102 |
103 | As there is a lot of changes from previous releases, be careful when updating, as your previously set values might be lost.
104 | The previous version required to modify your base template, whereas the 2.0+ version of the plugin now adds metadata and microdata automatically to your existing Installation.
105 |
106 | Installing or updating the `SEO` plugin can be done in one of three ways. Using the GPM (Grav Package Manager) installation update method (i.e. `bin/gpm install seo`) or manual install by downloading [this plugin](https://github.com/paulmassen/grav-plugin-seo) and extracting all plugin files to
107 |
108 | /your/site/grav/user/plugins/seo
109 |
110 | Once installed, the plugin will automatically set the metadata and append the json-ld microdatas to your document.
111 | If you plan on using the Twitter feature, make sure to fill your user ID in tab Plugins > SEO > Twitter ID
112 |
113 | ## Configuration
114 |
115 | Configuration is done through the plugin configuration page, accessible by clicking on Plugins > Seo. On this page, you can choose to enable the microdata fields you will use.
116 | Make sure to fill the Facebook ID field as well as the Twitter ID field, in order for your meta tags to be validated.
117 |
118 | ## Usage
119 |
120 | The `SEO` plugin appends a SEO tab on every pages where you can manage and define how your website will look on search engine results and on social networks.
121 |
122 |
123 | ## Contributing
124 |
125 | You can contribute at any time! Before opening any issue, please search for existing issues!
126 |
127 | After that please note:
128 |
129 | * If you find a bug, would like to make a feature request or suggest an improvement, [please open a new issue][issues]. If you have any interesting ideas for additions to the syntax please do suggest them as well!
130 | * Feature requests are more likely to get attention if you include a clearly described use case.
131 |
132 |
133 |
134 | ## License
135 |
136 |
--------------------------------------------------------------------------------
/templates/forms/fields/facebook/facebook.html.twig:
--------------------------------------------------------------------------------
1 |
2 | {% if admin.route %}
3 | {% set context = admin.page(true) %}
4 | {% endif %}
5 | {% if field.title or field.underline %}
6 | {% if grav.twig.twig.filters['tu'] is defined %}{{ field.title|tu }}{% else %}{{ field.title|t }}{% endif %}
7 | {% endif %}
8 |
9 | {% set context = admin.page(true) %}
10 |
11 |
17 |
18 |
Here is how this page will look when shared on facebook.
19 |
20 |
21 |
22 |
23 |
24 |
{{ context.header.facebooktitle|default(context.header.title ~ " | " ~ site.title )}}
25 |
{{ context.header.facebookdesc|default(context.summary|striptags) }}
26 |
{{uri.host|replace({"http://": "","/":" › " }) }}
27 |
28 |
29 |
30 |
31 |
32 | Like
33 | Comment
34 | Share
35 |
36 |
37 |
38 |
197 |
214 |
227 | {% if field.text %}
228 | {% endif %}
229 |
230 | {% if field.fields %}
231 |
232 | {% for field in field.fields %}
233 | {% if field.type %}
234 | {% set value = data.value(field.name) %}
235 | {% include ["forms/fields/#{field.type}/#{field.type}.html.twig", 'forms/fields/text/text.html.twig'] %}
236 | {% endif %}
237 | {% endfor %}
238 |
239 | {% endif %}
240 |
--------------------------------------------------------------------------------
/css/yoast-seo.min.css:
--------------------------------------------------------------------------------
1 | .yoast-section{width:auto;max-width:640px}.snippet_container:before,.snippet_container:after{content:' ';display:table}.snippet_container:after{clear:both}.snippet-editor__view{clear:both;background:#fff}.snippet-editor__view-toggle{display:inline-block;background-color:#f7f7f7;border:1px solid #dbdbdb;border-radius:4px;margin-top:10px;margin-left:20px;vertical-align:top}.snippet-editor__view-icon{width:31px;height:31px;float:left;cursor:pointer;background-color:transparent;background-repeat:no-repeat;background-position:center, center;border:none;border-bottom:4px solid transparent;outline:none}.snippet-editor__view-icon:hover,.snippet-editor__view-icon:focus{background-color:#ffffff;border-color:#1074a8;transition:.15s color ease-in-out,.15s background-color ease-in-out,.15s border-color ease-in-out}.snippet-editor__view-icon--active{border-color:#555;transition:.15s color ease-in-out,.15s background-color ease-in-out,.15s border-color ease-in-out}.snippet-editor__view-icon.yoast-tooltip:before{bottom:-10px}.snippet-editor__view-icon.yoast-tooltip:after{margin-top:10px}.snippet-editor__view-icon-desktop{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555%22%20d%3D%22M1728%20992v%2D832q0%2D13%2D9%2E5%2D22%2E5t%2D22%2E5%2D9%2E5h%2D1600q%2D13%200%2D22%2E5%209%2E5t%2D9%2E5%2022%2E5v832q0%2013%209%2E5%2022%2E5t22%2E5%209%2E5h1600q13%200%2022%2E5%2D9%2E5t9%2E5%2D22%2E5zm128%2D832v1088q0%2066%2D47%20113t%2D113%2047h%2D544q0%2037%2016%2077%2E5t32%2071%2016%2043%2E5q0%2026%2D19%2045t%2D45%2019h%2D512q%2D26%200%2D45%2D19t%2D19%2D45q0%2D14%2016%2D44t32%2D70%2016%2D78h%2D544q%2D66%200%2D113%2D47t%2D47%2D113v%2D1088q0%2D66%2047%2D113t113%2D47h1600q66%200%20113%2047t47%20113z%22%2F%3E%3C%2Fsvg%3E");background-size:18px}.snippet-editor__view-icon-desktop:hover,.snippet-editor__view-icon-desktop:focus{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%231074a8%22%20d%3D%22M1728%20992v%2D832q0%2D13%2D9%2E5%2D22%2E5t%2D22%2E5%2D9%2E5h%2D1600q%2D13%200%2D22%2E5%209%2E5t%2D9%2E5%2022%2E5v832q0%2013%209%2E5%2022%2E5t22%2E5%209%2E5h1600q13%200%2022%2E5%2D9%2E5t9%2E5%2D22%2E5zm128%2D832v1088q0%2066%2D47%20113t%2D113%2047h%2D544q0%2037%2016%2077%2E5t32%2071%2016%2043%2E5q0%2026%2D19%2045t%2D45%2019h%2D512q%2D26%200%2D45%2D19t%2D19%2D45q0%2D14%2016%2D44t32%2D70%2016%2D78h%2D544q%2D66%200%2D113%2D47t%2D47%2D113v%2D1088q0%2D66%2047%2D113t113%2D47h1600q66%200%20113%2047t47%20113z%22%2F%3E%3C%2Fsvg%3E")}.snippet-editor__view-icon-mobile{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555%22%20d%3D%22M976%201408q0%2D33%2D23%2E5%2D56%2E5t%2D56%2E5%2D23%2E5%2D56%2E5%2023%2E5%2D23%2E5%2056%2E5%2023%2E5%2056%2E5%2056%2E5%2023%2E5%2056%2E5%2D23%2E5%2023%2E5%2D56%2E5zm208%2D160v%2D704q0%2D13%2D9%2E5%2D22%2E5t%2D22%2E5%2D9%2E5h%2D512q%2D13%200%2D22%2E5%209%2E5t%2D9%2E5%2022%2E5v704q0%2013%209%2E5%2022%2E5t22%2E5%209%2E5h512q13%200%2022%2E5%2D9%2E5t9%2E5%2D22%2E5zm%2D192%2D848q0%2D16%2D16%2D16h%2D160q%2D16%200%2D16%2016t16%2016h160q16%200%2016%2D16zm288%2D16v1024q0%2052%2D38%2090t%2D90%2038h%2D512q%2D52%200%2D90%2D38t%2D38%2D90v%2D1024q0%2D52%2038%2D90t90%2D38h512q52%200%2090%2038t38%2090z%22%2F%3E%3C%2Fsvg%3E");background-size:22px}.snippet-editor__view-icon-mobile:hover,.snippet-editor__view-icon-mobile:focus{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%231074a8%22%20d%3D%22M976%201408q0%2D33%2D23%2E5%2D56%2E5t%2D56%2E5%2D23%2E5%2D56%2E5%2023%2E5%2D23%2E5%2056%2E5%2023%2E5%2056%2E5%2056%2E5%2023%2E5%2056%2E5%2D23%2E5%2023%2E5%2D56%2E5zm208%2D160v%2D704q0%2D13%2D9%2E5%2D22%2E5t%2D22%2E5%2D9%2E5h%2D512q%2D13%200%2D22%2E5%209%2E5t%2D9%2E5%2022%2E5v704q0%2013%209%2E5%2022%2E5t22%2E5%209%2E5h512q13%200%2022%2E5%2D9%2E5t9%2E5%2D22%2E5zm%2D192%2D848q0%2D16%2D16%2D16h%2D160q%2D16%200%2D16%2016t16%2016h160q16%200%2016%2D16zm288%2D16v1024q0%2052%2D38%2090t%2D90%2038h%2D512q%2D52%200%2D90%2D38t%2D38%2D90v%2D1024q0%2D52%2038%2D90t90%2D38h512q52%200%2090%2038t38%2090z%22%2F%3E%3C%2Fsvg%3E")}.snippet-editor__view--desktop{width:640px;max-width:100%;padding:0 20px;overflow:auto}.snippet-editor__view .snippet_container__title{width:600px;white-space:nowrap}.snippet-editor__view .snippet_container__title .title{display:inline-block;max-width:600px;overflow:hidden;text-overflow:ellipsis;vertical-align:top}.snippet-editor__view .snippet_container__title .title#snippet_sitename{display:inline}.snippet-editor__view .snippet_container__url{width:600px;white-space:nowrap;line-height:1}.snippet-editor__view .snippet_container__url .urlFull{display:inline-block;max-width:586px;overflow:hidden;text-overflow:ellipsis;vertical-align:top;font-size:14px;line-height:16px}.snippet-editor__view .snippet_container .down_arrow{display:inline-block;border-left:4px solid transparent;border-right:4px solid transparent;border-top:5px solid #006621;margin-top:6px;margin-left:6px;vertical-align:top}.snippet-editor__view .snippet_container__meta{width:600px}.snippet-editor__view--mobile{box-shadow:0 1px 2px rgba(0,0,0,0.2);border-radius:2px;border-bottom:1px hidden #fff;margin:0 20px 10px;padding:11px 0}.snippet-editor__view--mobile .snippet_container{display:block;line-height:20px}.snippet-editor__view--mobile .snippet_container__title,.snippet-editor__view--mobile .snippet_container__url,.snippet-editor__view--mobile .snippet_container__meta{width:100%;box-sizing:border-box}.snippet-editor__view--mobile .snippet_container__title{padding:0 16px;white-space:normal;overflow:visible;word-wrap:break-word}.snippet-editor__view--mobile .snippet_container__title .title{font-size:16px;line-height:20px}.snippet-editor__view--mobile .snippet_container__url{border-bottom:1px solid #ebebeb;padding:0 16px 9px;margin-bottom:9px}.snippet-editor__view--mobile .snippet_container__url .urlFull{max-width:100%;font-size:14px;line-height:20px}.snippet-editor__view--mobile .snippet_container .down_arrow{display:none}.snippet-editor__view--mobile .snippet_container__meta{font-size:14px;line-height:20px;padding:0 16px}.snippet-editor__view--mobile .snippet_container .desc{font-size:14px;line-height:20px}.snippet-editor__is-scrollable-hintwrapper{display:none;margin:1em 0 5px;text-align:center}.snippet-editor__view--desktop.snippet-editor__view--desktop-has-scroll+.snippet-editor__is-scrollable-hintwrapper{display:block}.snippet-editor__is-scrollable-hint{display:inline-block}.snippet-editor__is-scrollable-hint:before{content:"\21c4";display:inline-block;margin-right:10px;font-size:20px;line-height:inherit;vertical-align:text-top}.snippet-editor__container{position:relative;cursor:pointer}.snippet-editor__container.editable-preview__container--no-caret{cursor:auto}.snippet-editor__heading{padding:8px 20px;font-size:0.9rem;margin:0 0 15px;font-family:"Open Sans", sans-serif;font-weight:300;color:#555}.snippet-editor__heading-editor{border-top:1px solid #f7f7f7}.snippet-editor__heading-icon{background-repeat:no-repeat;background-position:left 20px top 0.6em;background-size:16px;padding-left:45px}.snippet-editor__heading-icon-eye{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555%22%20d%3D%22M1664%20960q%2D152%2D236%2D381%2D353%2061%20104%2061%20225%200%20185%2D131%2E5%20316%2E5t%2D316%2E5%20131%2E5%2D316%2E5%2D131%2E5%2D131%2E5%2D316%2E5q0%2D121%2061%2D225%2D229%20117%2D381%20353%20133%20205%20333%2E5%20326%2E5t434%2E5%20121%2E5%20434%2E5%2D121%2E5%20333%2E5%2D326%2E5zm%2D720%2D384q0%2D20%2D14%2D34t%2D34%2D14q%2D125%200%2D214%2E5%2089%2E5t%2D89%2E5%20214%2E5q0%2020%2014%2034t34%2014%2034%2D14%2014%2D34q0%2D86%2061%2D147t147%2D61q20%200%2034%2D14t14%2D34zm848%20384q0%2034%2D20%2069%2D140%20230%2D376%2E5%20368%2E5t%2D499%2E5%20138%2E5%2D499%2E5%2D139%2D376%2E5%2D368q%2D20%2D35%2D20%2D69t20%2D69q140%2D229%20376%2E5%2D368t499%2E5%2D139%20499%2E5%20139%20376%2E5%20368q20%2035%2020%2069z%22%20%2F%3E%3C%2Fsvg%3E")}.snippet-editor__container:hover:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23bfbfbf%22%20d%3D%22M1152%20896q0%2026%2D19%2045l%2D448%20448q%2D19%2019%2D45%2019t%2D45%2D19%2D19%2D45v%2D896q0%2D26%2019%2D45t45%2D19%2045%2019l448%20448q19%2019%2019%2045z%22%20%2F%3E%3C%2Fsvg%3E");position:absolute;content:'';top:-3px;left:-22px;display:block;width:24px;height:24px;background-size:25px}.snippet-editor__container--focus:hover:before,.snippet-editor__container--focus:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555%22%20d%3D%22M1152%20896q0%2026%2D19%2045l%2D448%20448q%2D19%2019%2D45%2019t%2D45%2D19%2D19%2D45v%2D896q0%2D26%2019%2D45t45%2D19%2045%2019l448%20448q19%2019%2019%2045z%22%20%2F%3E%3C%2Fsvg%3E");position:absolute;content:'';top:-3px;left:-22px;display:block;width:24px;height:24px;background-size:25px}.snippet-editor__preview{padding:0 0 15px;max-width:640px}.snippet-editor__preview #help-yoast-snippetpreview{padding:0 20px}.snippet-editor__button{background:#f7f7f7;border:1px solid #dbdbdb;border-radius:4px;color:#555;padding:8px 10px;cursor:pointer;font-size:0.8rem;line-height:15px}.snippet-editor__edit-button{background:#f7f7f7 url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555%22%20d%3D%22M491%201536l91%2D91%2D235%2D235%2D91%2091v107h128v128h107zm523%2D928q0%2D22%2D22%2D22%2D10%200%2D17%207l%2D542%20542q%2D7%207%2D7%2017%200%2022%2022%2022%2010%200%2017%2D7l542%2D542q7%2D7%207%2D17zm%2D54%2D192l416%20416%2D832%20832h%2D416v%2D416zm683%2096q0%2053%2D37%2090l%2D166%20166%2D416%2D416%20166%2D165q36%2D38%2090%2D38%2053%200%2091%2038l235%20234q37%2039%2037%2091z%22%20%2F%3E%3C%2Fsvg%3E") no-repeat;background-position:left 8px top 50%;background-size:16px;padding-left:32px;display:inline-block;box-sizing:border-box;margin-top:10px}.snippet-editor__form{padding:20px}.snippet-editor__label{display:block;width:100%;margin-top:1em;position:relative}.snippet-editor__label:first-child{margin-top:0}.snippet-editor__label--hover:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23bfbfbf%22%20d%3D%22M1152%20896q0%2026%2D19%2045l%2D448%20448q%2D19%2019%2D45%2019t%2D45%2D19%2D19%2D45v%2D896q0%2D26%2019%2D45t45%2D19%2045%2019l448%20448q19%2019%2019%2045z%22%20%2F%3E%3C%2Fsvg%3E");position:absolute;content:'';top:-3px;left:-22px;display:block;width:24px;height:24px;background-size:25px;top:20px}.snippet-editor__label--focus:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%231074a8%22%20d%3D%22M1152%20896q0%2026%2D19%2045l%2D448%20448q%2D19%2019%2D45%2019t%2D45%2D19%2D19%2D45v%2D896q0%2D26%2019%2D45t45%2D19%2045%2019l448%20448q19%2019%2019%2045z%22%20%2F%3E%3C%2Fsvg%3E");position:absolute;content:'';top:-3px;left:-22px;display:block;width:24px;height:24px;background-size:25px;top:20px}.snippet-editor__input{display:block;width:100%;margin-top:5px;border:1px solid #bfbfbf;max-width:100%;box-sizing:border-box}.snippet-editor__input:focus{border:1px solid #1074a8;outline:none}.rtl .snippet-editor__container:hover:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23bfbfbf%22%20d%3D%22M1216%20448v896q0%2026%2D19%2045t%2D45%2019%2D45%2D19l%2D448%2D448q%2D19%2D19%2D19%2D45t19%2D45l448%2D448q19%2D19%2045%2D19t45%2019%2019%2045z%22%2F%3E%3C%2Fsvg%3E")}.rtl .snippet-editor__container--focus:hover:before,.rtl .snippet-editor__container--focus:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555%22%20d%3D%22M1216%20448v896q0%2026%2D19%2045t%2D45%2019%2D45%2D19l%2D448%2D448q%2D19%2D19%2D19%2D45t19%2D45l448%2D448q19%2D19%2045%2D19t45%2019%2019%2045z%22%2F%3E%3C%2Fsvg%3E")}.rtl .snippet-editor__label--hover:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23bfbfbf%22%20d%3D%22M1216%20448v896q0%2026%2D19%2045t%2D45%2019%2D45%2D19l%2D448%2D448q%2D19%2D19%2D19%2D45t19%2D45l448%2D448q19%2D19%2045%2D19t45%2019%2019%2045z%22%2F%3E%3C%2Fsvg%3E")}.rtl .snippet-editor__label--focus:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%231074a8%22%20d%3D%22M1216%20448v896q0%2026%2D19%2045t%2D45%2019%2D45%2D19l%2D448%2D448q%2D19%2D19%2D19%2D45t19%2D45l448%2D448q19%2D19%2045%2D19t45%2019%2019%2045z%22%2F%3E%3C%2Fsvg%3E")}.snippet-editor__meta-description{height:70px}.snippet-editor__submit{margin-top:1em}#snippet_cite{min-width:20px}#meta_container{clear:both;min-height:20px}.snippet_container .title{color:#1e0fbe;text-decoration:none;font-size:18px;line-height:1.2;font-weight:normal;margin:0}.snippet_container .desc{font-size:13px;line-height:1.4}.snippet_container .url{color:#006621;font-style:normal}.snippet_container .url strong{font-weight:700}.snippet_container .desc-default{color:#545454}.snippet_container .desc-default strong{color:#6a6a6a;font-weight:700}.snippet_container .desc-render{color:#777}.snippet_container .tooLong{color:#f00 !important}.snippet-editor__field--invalid{color:#f00}.snippet-editor__progress{-webkit-appearance:none;-moz-appearance:none;appearance:none;border:none;box-sizing:border-box;display:block;margin-top:5px;height:8px;width:100%}.snippet-editor__progress::-webkit-progress-bar{background-color:#f7f7f7;height:8px;border:1px solid #bfbfbf}.snippet-editor__progress--fallback{background-color:#f7f7f7;height:8px;border:1px solid #bfbfbf}.snippet-editor__progress-bar{width:0;height:100%;max-width:100%}.snippet-editor__date{color:#808080;font-size:13px;line-height:1.4}.snippet-editor--hidden{display:none}.yoast-measurement-elements-holder{position:absolute;left:-9999em}.snippet-editor__progress--bad[value]{color:#dc3232}.snippet-editor__progress--bad[value]::-webkit-progress-value{background-color:#dc3232;transition:width 250ms}.snippet-editor__progress--bad[value]::-moz-progress-bar{background-color:#dc3232}.snippet-editor__progress--bad[value] .snippet-editor__progress-bar{background-color:#dc3232}.snippet-editor__progress--ok[value]{color:#ee7c1b}.snippet-editor__progress--ok[value]::-webkit-progress-value{background-color:#ee7c1b;transition:width 250ms}.snippet-editor__progress--ok[value]::-moz-progress-bar{background-color:#ee7c1b}.snippet-editor__progress--ok[value] .snippet-editor__progress-bar{background-color:#ee7c1b}.snippet-editor__progress--good[value]{color:#7ad03a}.snippet-editor__progress--good[value]::-webkit-progress-value{background-color:#7ad03a;transition:width 250ms}.snippet-editor__progress--good[value]::-moz-progress-bar{background-color:#7ad03a}.snippet-editor__progress--good[value] .snippet-editor__progress-bar{background-color:#7ad03a}.wpseoanalysis{padding-right:0px}.wpseo-score-text{float:left;width:86%;width:calc( 100% - 56px)}.assessment-results .wpseo-score-icon{float:left;width:12px;height:12px;margin:3px 10px 0 0;border-radius:50%;background:#888}.wpseo-score-icon.good{background-color:#7ad03a}.wpseo-score-icon.ok{background-color:#ee7c1b}.wpseo-score-icon.bad{background-color:#dc3232}.wpseo-score-icon.na{background-color:#999}.wpseo-score-icon.noindex{background-color:#1e8cbe}li.score{list-style-type:none !important;margin-bottom:6px}li.score:after{content:"";display:table;clear:both}.screen-reader-text{clip:rect(1px, 1px, 1px, 1px);position:absolute !important;height:1px;width:1px;overflow:hidden}.assessment-results{clear:both}.assessment-results__mark.icon-eye-inactive,.assessment-results__mark.icon-eye-active,.assessment-results__mark.icon-eye-disabled{float:left;border:0;width:28px;height:28px;margin:-5px 3px 0 3px;padding:4px;border-radius:100%;outline:none;background:no-repeat center;background-size:16px;cursor:pointer}.assessment-results__mark.icon-eye-inactive{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555%22%20d%3D%22M1664%20960q%2D152%2D236%2D381%2D353%2061%20104%2061%20225%200%20185%2D131%2E5%20316%2E5t%2D316%2E5%20131%2E5%2D316%2E5%2D131%2E5%2D131%2E5%2D316%2E5q0%2D121%2061%2D225%2D229%20117%2D381%20353%20133%20205%20333%2E5%20326%2E5t434%2E5%20121%2E5%20434%2E5%2D121%2E5%20333%2E5%2D326%2E5zm%2D720%2D384q0%2D20%2D14%2D34t%2D34%2D14q%2D125%200%2D214%2E5%2089%2E5t%2D89%2E5%20214%2E5q0%2020%2014%2034t34%2014%2034%2D14%2014%2D34q0%2D86%2061%2D147t147%2D61q20%200%2034%2D14t14%2D34zm848%20384q0%2034%2D20%2069%2D140%20230%2D376%2E5%20368%2E5t%2D499%2E5%20138%2E5%2D499%2E5%2D139%2D376%2E5%2D368q%2D20%2D35%2D20%2D69t20%2D69q140%2D229%20376%2E5%2D368t499%2E5%2D139%20499%2E5%20139%20376%2E5%20368q20%2035%2020%2069z%22%20%2F%3E%3C%2Fsvg%3E")}.assessment-results__mark.icon-eye-active{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23fff%22%20d%3D%22M1664%20960q%2D152%2D236%2D381%2D353%2061%20104%2061%20225%200%20185%2D131%2E5%20316%2E5t%2D316%2E5%20131%2E5%2D316%2E5%2D131%2E5%2D131%2E5%2D316%2E5q0%2D121%2061%2D225%2D229%20117%2D381%20353%20133%20205%20333%2E5%20326%2E5t434%2E5%20121%2E5%20434%2E5%2D121%2E5%20333%2E5%2D326%2E5zm%2D720%2D384q0%2D20%2D14%2D34t%2D34%2D14q%2D125%200%2D214%2E5%2089%2E5t%2D89%2E5%20214%2E5q0%2020%2014%2034t34%2014%2034%2D14%2014%2D34q0%2D86%2061%2D147t147%2D61q20%200%2034%2D14t14%2D34zm848%20384q0%2034%2D20%2069%2D140%20230%2D376%2E5%20368%2E5t%2D499%2E5%20138%2E5%2D499%2E5%2D139%2D376%2E5%2D368q%2D20%2D35%2D20%2D69t20%2D69q140%2D229%20376%2E5%2D368t499%2E5%2D139%20499%2E5%20139%20376%2E5%20368q20%2035%2020%2069z%22%20%2F%3E%3C%2Fsvg%3E");background-color:#a4286a}.assessment-results__mark.icon-eye-disabled{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23e6e6e6%22%20d%3D%22M1664%20960q%2D152%2D236%2D381%2D353%2061%20104%2061%20225%200%20185%2D131%2E5%20316%2E5t%2D316%2E5%20131%2E5%2D316%2E5%2D131%2E5%2D131%2E5%2D316%2E5q0%2D121%2061%2D225%2D229%20117%2D381%20353%20133%20205%20333%2E5%20326%2E5t434%2E5%20121%2E5%20434%2E5%2D121%2E5%20333%2E5%2D326%2E5zm%2D720%2D384q0%2D20%2D14%2D34t%2D34%2D14q%2D125%200%2D214%2E5%2089%2E5t%2D89%2E5%20214%2E5q0%2020%2014%2034t34%2014%2034%2D14%2014%2D34q0%2D86%2061%2D147t147%2D61q20%200%2034%2D14t14%2D34zm848%20384q0%2034%2D20%2069%2D140%20230%2D376%2E5%20368%2E5t%2D499%2E5%20138%2E5%2D499%2E5%2D139%2D376%2E5%2D368q%2D20%2D35%2D20%2D69t20%2D69q140%2D229%20376%2E5%2D368t499%2E5%2D139%20499%2E5%20139%20376%2E5%20368q20%2035%2020%2069z%22%20%2F%3E%3C%2Fsvg%3E")}.assessment-results__mark:focus{border-radius:100%;box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,0.8)}.assessment-results__mark-container{display:inline-block;float:right;width:33px;min-height:1px}.YoastSEO_msg .right,.YoastSEO_msg .left{display:none}@keyframes animatedBackground{from{background-position:0 0}to{background-position:100% 0}}.YoastSEO_msg .bufferbar{display:block;width:100%;height:12px;background-image:linear-gradient(to left, #fff, #0063ff, #fff, #0063ff);background-size:300% 100%;background-position:0px 0px;margin:10px 0 10px 0;border:1px solid #dfdfdf;animation:animatedBackground 5s linear infinite}.yoast-tooltip{position:relative}button.yoast-tooltip{overflow:visible}.yoast-tooltip::after{display:none;position:absolute;z-index:1000000;padding:6px 8px 5px;border-radius:3px;opacity:0;color:#fff;background:rgba(0,0,0,0.8);text-shadow:none;font:normal normal 11px/1.45454545 Helvetica, arial, nimbussansl, liberationsans, freesans, clean, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";text-align:center;white-space:pre;text-decoration:none;letter-spacing:normal;text-transform:none;word-wrap:break-word;content:attr(aria-label);pointer-events:none;-webkit-font-smoothing:subpixel-antialiased}.yoast-tooltip-alt::after{content:attr(data-label)}.yoast-tooltip::before{display:none;position:absolute;z-index:1000001;width:0;height:0;border:5px solid transparent;opacity:0;color:rgba(0,0,0,0.8);content:"\00a0";pointer-events:none}@keyframes yoast-tooltip-appear{from{opacity:0}to{opacity:1}}.yoast-tooltip:hover::before,.yoast-tooltip:hover::after,.yoast-tooltip:active::before,.yoast-tooltip:active::after,.yoast-tooltip:focus::before,.yoast-tooltip:focus::after{display:inline-block;text-decoration:none;animation-name:yoast-tooltip-appear;animation-duration:0.1s;animation-timing-function:ease-in;animation-delay:0.4s;animation-fill-mode:forwards}.yoast-tooltip-no-delay:hover::before,.yoast-tooltip-no-delay:hover::after,.yoast-tooltip-no-delay:active::before,.yoast-tooltip-no-delay:active::after,.yoast-tooltip-no-delay:focus::before,.yoast-tooltip-no-delay:focus::after{opacity:1;animation:none}.yoast-tooltip-multiline:hover::after,.yoast-tooltip-multiline:active::after,.yoast-tooltip-multiline:focus::after{display:table-cell}.yoast-tooltip-s::after,.yoast-tooltip-se::after,.yoast-tooltip-sw::after{top:100%;right:50%;margin-top:5px}.yoast-tooltip-s::before,.yoast-tooltip-se::before,.yoast-tooltip-sw::before{top:auto;right:50%;bottom:-5px;margin-right:-5px;border-bottom-color:rgba(0,0,0,0.8)}.yoast-tooltip-se::after{right:auto;left:50%;margin-left:-15px}.yoast-tooltip-sw::after{margin-right:-15px}.yoast-tooltip-n::after,.yoast-tooltip-ne::after,.yoast-tooltip-nw::after{right:50%;bottom:100%;margin-bottom:5px}.yoast-tooltip-n::before,.yoast-tooltip-ne::before,.yoast-tooltip-nw::before{top:-5px;right:50%;bottom:auto;margin-right:-5px;border-top-color:rgba(0,0,0,0.8)}.yoast-tooltip-ne::after{right:auto;left:50%;margin-left:-15px}.yoast-tooltip-nw::after{margin-right:-15px}.yoast-tooltip-s::after,.yoast-tooltip-n::after{-ms-transform:translateX(50%);transform:translateX(50%)}.yoast-tooltip-w::after{right:100%;bottom:50%;margin-right:5px;-ms-transform:translateY(50%);transform:translateY(50%)}.yoast-tooltip-w::before{top:50%;bottom:50%;left:-5px;margin-top:-5px;border-left-color:rgba(0,0,0,0.8)}.yoast-tooltip-e::after{bottom:50%;left:100%;margin-left:5px;-ms-transform:translateY(50%);transform:translateY(50%)}.yoast-tooltip-e::before{top:50%;right:-5px;bottom:50%;margin-top:-5px;border-right-color:rgba(0,0,0,0.8)}.yoast-tooltip-multiline::after{width:250px;width:-webkit-max-content;width:-moz-max-content;width:max-content;max-width:250px;border-collapse:separate;white-space:pre-line;word-wrap:normal;word-break:break-word}.yoast-tooltip-multiline.yoast-tooltip-s::after,.yoast-tooltip-multiline.yoast-tooltip-n::after{right:auto;left:50%;-ms-transform:translateX(-50%);transform:translateX(-50%)}.yoast-tooltip-multiline.yoast-tooltip-w::after,.yoast-tooltip-multiline.yoast-tooltip-e::after{right:100%}@media screen and (min-width: 0\0){.yoast-tooltip-multiline::after{width:250px}}.yoast-tooltip-sticky::before,.yoast-tooltip-sticky::after{display:inline-block}.yoast-tooltip-sticky.yoast-tooltip-multiline::after{display:table-cell}@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-moz-min-device-pixel-ratio: 2), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx){.yoast-tooltip-w::after{margin-right:4.5px}}.yoast-tooltip.yoast-tooltip-hidden::before,.yoast-tooltip.yoast-tooltip-hidden::after{display:none}
2 |
--------------------------------------------------------------------------------
/seo.php:
--------------------------------------------------------------------------------
1 |
12 | * @author Paul Massendari
13 | * @copyright 2020, Paul Massendari
14 | * @license MIT
15 | */
16 |
17 | namespace Grav\Plugin;
18 |
19 | use Grav\Common\Plugin;
20 | use Grav\Common\Page\Page;
21 | use Grav\Common\Data\Blueprints;
22 | use Grav\Common\Page\Pages;
23 | use RocketTheme\Toolbox\Event\Event;
24 | use Grav\Common\Grav;
25 | use Grav\Common\Page\Media;
26 | use Grav\Common\Helpers\Exif;
27 | use Grav\Common\Page\Medium\AbstractMedia;
28 | use Grav\Common\Iterator;
29 |
30 |
31 | /**
32 | * SEO Plugin
33 | *
34 | * This plugin adds an user-friendly SEO tab for your user to manage metadata tags
35 | * and appearance on Search Engine Results and Social Networks.
36 | */
37 |
38 | class SeoPlugin extends Plugin
39 | {
40 |
41 | /** -------------
42 | * Public methods
43 | * --------------
44 | */
45 |
46 | /**
47 | * Return a list of subscribed events.
48 | *
49 | * @return array The list of events of the plugin of the form
50 | * 'name' => ['method_name', priority].
51 | */
52 | public static function getSubscribedEvents()
53 | {
54 | return [
55 | 'onPluginsInitialized' => ['onPluginsInitialized', 0],
56 | 'onPageInitialized' => ['onPageInitialized', 0],
57 | // 'onPageContentRaw' => ['onPageContentRaw', 0],
58 | // 'onBlueprintCreated' => ['onBlueprintCreated', 0]
59 | ];
60 | }
61 |
62 | private function cleanArray(array $array): array
63 | {
64 | foreach ($array as $key => &$value) {
65 | if (is_array($value)) {
66 | $value = $this->cleanArray($value);
67 | }
68 |
69 | if (empty($value) && $value !== 0 && $value !== '0') {
70 | unset($array[$key]);
71 | }
72 | }
73 |
74 | return $array;
75 | }
76 |
77 | /**
78 | * Récupère les métadonnées d'une image (dimensions et URL)
79 | *
80 | * @param string|null $imageUrl URL de l'image à analyser
81 | * @return array{width: string, height: string, url: string}
82 | */
83 | private function seoGetImage(?string $imageUrl): array
84 | {
85 | // Si l'URL est vide, retourner directement les valeurs par défaut
86 | if (empty($imageUrl)) {
87 | return [
88 | 'width' => '0',
89 | 'height' => '0',
90 | 'url' => '',
91 | ];
92 | }
93 |
94 | try {
95 | // Extraction du chemin et du nom de fichier
96 | if (!preg_match('~((\/[^\/]+)+)\/([^\/]+)~', $imageUrl, $matches)) {
97 | throw new \RuntimeException('Format d\'URL invalide');
98 | }
99 |
100 | $imagePath = $matches[1];
101 | $imageName = $matches[3];
102 |
103 | // Récupération de la page
104 | $page = $this->grav['page']->find($imagePath);
105 | if (!$page) {
106 | throw new \RuntimeException("Page non trouvée: $imagePath");
107 | }
108 |
109 | // Vérification de la présence d'images
110 | $images = $page->media()->images();
111 | if (empty($images)) {
112 | throw new \RuntimeException("Aucune image trouvée");
113 | }
114 |
115 | // Recherche de l'image spécifique
116 | $availableImages = array_keys($images);
117 | $imageIndex = array_search($imageName, $availableImages);
118 | if ($imageIndex === false) {
119 | throw new \RuntimeException("Image spécifique non trouvée");
120 | }
121 |
122 | $imageKey = $availableImages[$imageIndex];
123 | $image = $images[$imageKey];
124 |
125 | // Vérification du chemin de l'image
126 | if (!$image || !$image->path() || !file_exists($image->path())) {
127 | throw new \RuntimeException("Fichier image invalide ou inaccessible");
128 | }
129 |
130 | $dimensions = @getimagesize($image->path());
131 | if ($dimensions === false) {
132 | throw new \RuntimeException("Impossible de lire les dimensions de l'image");
133 | }
134 |
135 | return [
136 | 'width' => (string)$dimensions[0],
137 | 'height' => (string)$dimensions[1],
138 | 'url' => $image->url(),
139 | ];
140 |
141 | } catch (\Exception $e) {
142 | // Log l'erreur mais ne casse pas le site
143 | $this->grav['log']->debug('SEO Plugin - Image Warning: ' . $e->getMessage());
144 |
145 | return [
146 | 'width' => '0',
147 | 'height' => '0',
148 | 'url' => '',
149 | ];
150 | }
151 | }
152 | /**
153 | * Nettoie et convertit le texte Markdown en texte brut
154 | *
155 | * @param string $text Le texte Markdown à nettoyer
156 | * @param int $maxLength Longueur maximale du texte retourné (défaut: 320)
157 | * @return string Le texte nettoyé
158 | */
159 | private const MARKDOWN_RULES = [
160 | // Suppression des inclusions Twig
161 | '/{%[\s\S]*?%}[\s\S]*?/' => '',
162 |
163 | // Suppression des balises HTML spécifiques
164 | '/