2010-04-01 7 views
1

Ceci est l'expression régulière utilisée pour "shortcodes" dans WordPress (un pour l'ensemble de la balise, d'autres pour les attributs).WordPress: Problème avec le raccourci regex

return '(.?)\[('.$tagregexp.')\b(.*?)(?:(\/))?\](?:(.+?)\[\/\2\])?(.?)'; 
$pattern = '/(\w+)\s*=\s*"([^"]*)"(?:\s|$)|(\w+)\s*=\s*\'([^\']*)\'(?:\s|$)|(\w+)\s*=\s*([^\s\'"]+)(?:\s|$)|"([^"]*)"(?:\s|$)|(\S+)(?:\s|$)/'; 

Il parse des trucs comme

[foo bar="baz"]content[/foo] 

ou

[foo /] 

Dans le WordPress trac, ils disent qu'il est un peu imparfait, mais mon principal problème est qu'il ne prend pas en charge shortcodes l'intérieur les attributs, comme dans

[foo bar="[baz /]"]content[/foo] 

parce que la regex arrête la principale shortcode à la première apparition d'un support de fermeture, donc dans l'exemple, il rend

[foo bar="[baz /] 

et

"]content[/foo] 

montre tel qu'il est.

Y a-t-il un moyen de modifier l'expression rationnelle afin qu'elle contourne toute occurrence de [ avec ] et son contenu lorsqu'il se produit entre l'étiquette d'ouverture ou l'étiquette de fermeture automatique?

+0

Où trouverions-nous cette regex? Cela aiderait si nous pouvions voir exactement comment il est utilisé. –

+0

Peu importe, je l'ai trouvé: http://xref.yoast.com/2.8/wp-includes/shortcodes.php.source.html#l45 –

Répondre

0

J'ai trouvé un moyen de le réparer: Tout d'abord, changer le regex shortcode de:

(.?)\[('.$tagregexp.')\b(.*?)(?:(\/))?\](?:(.+?)\[\/\2\])?(.?) 

Pour:

(.?)\[('.$tagregexp.')\b((?:[^\[\]]|(?R)|.)*?)(?:(\/))?\](?:(.+?)\[\/\2\])?(.?) 

Et puis modifier la priorité de la fonction do_shortcode pour éviter les conflits avec wptexturize, la fonction qui stylise les guillemets et gâche ce correctif. Il n'y a pas de problèmes avec wpautop parce que c'est quelque peu corrigé avec une autre fonction récente je pense.

Avant:

add_filter('the_content', 'do_shortcode', 11); // AFTER wpautop() 

Après:

add_filter('the_content', 'do_shortcode', 9); 

J'ai présenté cela TRAC et est sur une sorte de hiatus permanent. En attendant, je me demande si je peux faire un plugin pour appliquer mon correctif sans changer les fichiers de base. Remplacer la priorité du filtre est facile, mais je n'ai aucune idée de la façon de contourner la regex.

0

Quel est votre objectif? Même si WordPress 'regex était meilleur, le shortcode ne serait pas exécuté.

0
return '(.?)\[('.$tagregexp.')\b((?:"[^"]*"|.)*?)(?:/)?\](?:(.+?)\[\/\2\])?(.?)'; 

est une variante de la première regex où le bit qui correspond aux attributs a été changé pour capturer des chaînes complètement sans tenir compte de ce qui est en eux:

(?:"[^"]*"|.)*? 

au lieu de

.*? 

Notez qu'il ne gère pas les chaînes avec des caractères de guillemets échappés en eux (encore - peut être fait, mais est-il nécessaire?). Je n'ai rien changé d'autre car je ne connais pas la syntaxe des shortcodes WordPress.

Mais il semble que cela aurait pu être nettoyé un peu en enlevant antislashs et des parenthèses inutiles:

return '(.?)\[(foo)\b((?:"[^"]*"|.)*?)/?\](?:(.+?)\[/\2\])?(.?)'; 

Peut-être que d'autres améliorations sont nécessaires. Je m'inquiète un peu du point peu précis dans l'extrait ci-dessus, et je préfère utiliser (?:"[^"]*"|[^/\]])* au lieu de (?:"[^"]*"|.)*?, mais je ne sais pas si cela casserait quelque chose d'autre. En outre, je ne sais pas ce que les (.?) sont bons pour. Ils ne correspondent à rien dans votre exemple, donc je ne connais pas leur but.

0

Voulez-vous remplacer ce regex directement?Celui-ci permet des valeurs d'attributs pour contenir des choses qui ressemblent à des balises, comme dans votre exemple:

'(.?)\[(\w+)\b((?:[^"\'\[\]]++|(?:"[^"]*+")|(?:\'[^\']*+\'))*+)\](?:(?<=(\/)\])|([^\[\]]*+)\[\/\2\])(.?)' 

Ou, sous une forme plus lisible:

/(.?)    # could be [ 
\[(\w+)\b   # tag name 
((?:[^"'\[\]]++ # attributes 
    |(?:"[^"]*+") 
    |(?:'[^']*+') 
)*+ 
)\] 
(?:(?<=(\/)\]) # '/' if self-closing 
    |([^\[\]]*+) # ...or content 
    \[\/\2\]  # ...and closing tag 
)(.?)   # could be ] 
/

Si je comprends bien, $tagregexp dans l'original est un l'alternance de tous les noms de marques qui ont été définis; J'ai remplacé \w+ pour la lisibilité. Tout ce que la regex originale capture, celle-ci aussi, et dans les mêmes groupes. La seule différence est que le / dans une étiquette à fermeture automatique est capturé dans le groupe 3 avec les attributs ainsi que dans son propre groupe (# 4).

Je ne pense pas que l'autre expression régulière doit être modifiée à moins que vous vouliez ajouter un support complet pour les balises incorporées dans les valeurs d'attribut. Cela signifierait aussi permettre des citations échappées dans celui-ci, et je ne sais pas comment vous voudriez faire cela. Les doubler serait ma conjecture; c'est comme ça que Textpattern le fait, et WordPress est censé s'appuyer là-dessus.

Cette question est un bon exemple de pourquoi des applications comme WordPress ne devraient pas être implémentées avec des regex. La seule façon d'ajouter ou de modifier des fonctionnalités est de rendre les regex plus grandes et plus laides et encore plus difficiles à maintenir.

+0

J'ai essayé de remplacer toute la regex et le shortcode montre comme texte. J'ai essayé avec le 3ème groupe seulement et les courses de shortcode normales, mais quand il y a un shortcode dans un shortcode, seulement le (s) un (s) à l'intérieur de run et le suivant l'affiche sous forme de texte. – peroyomas

0

Ce serait bien de corriger! Je n'ai pas représentant suffisant pour commenter, je repars le lien wordpress lié trac ci-dessous, peut-être est le même que celui que vous vouliez dire: http://core.trac.wordpress.org/ticket/14481

J'espère que toute solution permettrait la syntaxe shortcode comme

[shortcode att1 = "val] n"] contenu [/ shortcode]

puisque dans 3.0.1 le contenu de $ est mal analysés comme ue"]content au lieu de simplement content

Mise à jour: Après avoir passé ti moi apprendre des regices (regexes?) J'ai permis d'autoriser des citations échappées de style Pascal et Pascal (par exemple arg = 'that' [so] great ') dans ces arguments avec 2 changements: d'abord changer le groupe (.*?) dans la première regex (get_shortcode_regex) en

 
((?:[^'"\]]|'[^']*'|"[^"]*")*) 

(NB: assurez-vous tout échapper correctement dans votre code php) puis dans shortcode_parse_atts (la fonction contenant la seconde regex) modifier les éléments suivants (encore une fois, changer '-\' si vous guillemet simple $pattern comme dans le code original)

 
in $pattern change "([^"]*)" to "((?:[^"]|"")*)" 
in $pattern change '([^']*)' to '((?:[^']|'')*)' 
$atts[strtolower($m[1])] = preg_replace('_""_', '"', stripcslashes($m[2])); 
$atts[strtolower($m[3])] = preg_replace("_''_", "'", stripcslashes($m[4])); 

NB encore une fois: les changements de pat Tern peut s'appuyer sur la nature gourmande de l'appariement, donc si cette option a déjà changé, les bits modifiés de $pattern pourraient devoir être terminés avec quelque chose comme (?!"), etc

Questions connexes