web-dev-qa-db-fra.com

Créer un shortcode personnalisé [code source], dans le bon sens?

Ce que je veux faire

Le partage de code dans les publications sur WordPress est assez pénible avec tous les échappements HTML à prendre en charge. Donc, je prévois d’enfermer du code dans les articles dans un shortcode personnalisé appelé [sourcecode], comme indiqué ci-dessous, et le laisser échapper automatiquement des caractères spéciaux.

[sourcecode]
<?php

    // Some code here.

?>
[/sourcecode]

Le code

Et voici à quoi ressemble la fonction correspondante (dans functions.php de mon thème):

/**
 * Functionality to set up custom shortcode correctly.
 *
 * This function is attached to the 'the_content' filter hook.
 */
add_filter( 'the_content', 'run_bbcodes', 7 );
function run_bbcodes( $content ) {
    global $shortcode_tags;

    $orig_shortcode_tags = $shortcode_tags;
    $shortcode_tags = array();

    // New shortcodes below
    add_shortcode( 'sourcecode', 'bbcode_code' );

    $content = do_shortcode( $content );
    $shortcode_tags = $orig_shortcode_tags;

    return $content;
}

/**
 * Add Custom shortcode functions below
 *
 * This function is attached to the 'sourcecode' shortcode hook.
 */
function bbcode_code( $atts, $content = null ) {

    // Ensure contents of a <pre>...</pre> HTML block aren't converted into paragraphs or line-breaks
    $content = clean_pre( $content );

    $content = str_replace(

        // Replace these special characters...
        array( '&', '\0', '<', '>', '\'', '"', '/', '[', ']' ),

        // ...with the HTML entities below, respectively
        array( '&amp;', '&#92;&#48;', '&lt;', '&gt;', '&apos;', '&quot;', '&#47;', '&#91;', '&#93;' ),

        $content
    );

    return '<pre><code>' . trim( $content ) . '</code></pre>';
}

/**
 * Related sourcecode worth reading:
 *
 * https://bitbucket.org/cbavota/syntax-highlighter-plugin/src
 *
 * https://github.com/mdawaffe/Highlight.js-for-WordPress/blob/master/highlight-js.php
 *
 * https://github.com/fracek/highlight-wp/blob/master/highlight.php
 *
 * http://plugins.svn.wordpress.org/syntaxhighlighter/trunk/
 *
 * http://blog.webspace.jp/235
 *
 * http://core.trac.wordpress.org/browser/trunk/src/wp-includes/shortcodes.php
 */

Des questions)

Maintenant que l'explication est hors du chemin ...

  1. Est-ce que je manque quelque chose d'autre?

    Par exemple, jusqu'à ce que je lise la source du plugin SyntaxHighlighter Evolved , je ne savais pas que \0 devait également être remplacé par &#92;&#48; "pour contourner kses" (ce qui n'était pas assez clair pour moi).

  2. Et à part échapper aux caractères spéciaux, y a-t-il autre chose que je pourrais éventuellement manquer? Est-ce que je le fais correctement?

    (Ce serait formidable si quelqu'un pouvait jeter un œil à ce fichier } (code source PHP du plugin SyntaxHighlighter Evolved) et voir si vous pouviez trouver quelque chose que je devais mettre en œuvre. J'ai déjà essayé de faire de mon mieux. )


PS: Pourquoi ne pas utiliser le plugin lui-même? D'une part, je ne veux pas que la syntaxe mette en évidence ce qu'il fait; et je veux savoir si ce qu'il fait peut être mis en œuvre facilement.

5
its_me

Vous parlez de X, mais je vais répondre par Y . IMHO, il y a trop d'exceptions à gérer pour accorder une autre solution.

SyntaxHighlighter Evolved contient les éléments suivants Pro Tip (forts, en majuscules et dans l’original):

CONSEIL: N'utilisez pas l'éditeur visuel si vous ne voulez pas que votre code soit mutilé. TinyMCE "nettoie" votre code HTML.

De plus, il est assez courant que des plugins et des thèmes fouillent avec the_content. Mesure approximative (et totalement non scientifique): 10 occurrences dans 50 plugins; 15 occurrences sur 50 thèmes.

Un autre Pro Tip :

enter image description here

Solution proposée

1) Pour gérer le code, je pense que c'est soit un champ/une zone personnalisé dans l'écran Modifier la publication, soit un pont entre la publication et un type de publication personnalisé "privé" qui sera stocké. le code. Je préfère ce dernier. Pas:

  • coller le code incorporable dans un <textarea> rendu avec edit_form_after_title
  • utilisez esc_html pour afficher dans le backend
  • et '<pre class="pretty">'.htmlentities($code).</pre> dans l'interface

2) Pour gérer la surbrillance de la syntaxe, il appartient au lecteur de choisir sa méthode préférée. Google Prettify est littéralement 2 lignes de code et ajoute une classe à la balise <pre>. Ne mettre en file d'attente que le script lorsque le shortcode est présent .

Exemple de plugin

Type d'article personnalisé  enter image description here

type de publication ()
enter image description here

Ce qui suit est un squelette et ne décrit que la logique. Et voici les liens pour quelques goodies:
Working skeleton at GistFull plugin at GitHub

<?php
/**
 * Plugin Name: Skeleton for the plugin Snippets Shortcode
 * Plugin URI: https://Gist.github.com/brasofilo/6804951
 */

/**
 * Based on Plugin Class Demo
 * https://Gist.github.com/toscho/3804204
 */
add_action(
    'plugins_loaded',
    array ( B5F_Snippets_Shortcode::get_instance(), 'plugin_setup' )
);

/**
 * Main class
 *
 * Fires all classes
 * Handles save_post action for other classes
 */
class B5F_Snippets_Shortcode {
    protected static $instance = NULL;
    public $post_type = 'snippet';    
    public function plugin_setup() {
        new B5F_SS_Cpt();
        new B5F_SS_Posts_Pages_Metabox();
        new B5F_SS_Shortcode();
        add_action( 'save_post', array( $this, '_save_post' ), 10, 2 );
    }
} 

/**
 * Register Snippet post type and render Textarea Field after the Title
 *
 * CPT is hierarchical 
 * Custom Metabox for CPT is left empty, can be used as Language Selector
 * Uses save_post for CPT 
 */
class B5F_SS_Cpt {
    public function __construct() {
        add_action( 'init', array( $this, '_cpt' ) );
        add_action( 'edit_form_after_title', array( $this, 'input_text_area' ) );
    }
}

/**
 * Metabox to select the Snippet and to display the correspondent Shortcode
 *
 * Displayed in Posts and Pages post types
 * Add jQuery to listen to the Snippets Dropdown changes and update the sample Text Field
 * Uses save_post for other Post Types 
 */
class B5F_SS_Posts_Pages_Metabox {
    public function __construct() {
        add_action( 'add_meta_boxes', array( $this, '_meta_boxes' ) );
    }
}

/**
 * Snippets Shortcode
 *
 * First gets the Snippet Post ID, then its associated Meta Data, 
 * finally filters the string with http://php.net/manual/en/function.htmlentities.php 
 *
 * Uses Google Code Prettify
 * https://code.google.com/p/google-code-prettify/
 */
class B5F_SS_Shortcode {
    public function __construct() {
        add_shortcode( 'snippet', array( $this, '_shortcode' ) );
    }
}
4
brasofilo

Juste au cas où la réponse de Rodolfo n'est pas claire, voici ce qu'il suggère (je pense) - une excellente idée, en passant:

  1. Créez un type de message personnalisé privé appelé Snippets, dans lequel nous allons stocker nos extraits de code.

    Nous utiliserons l'argument supports dans register_post_type à notre avantage. Nous ne voulons pas que l'éditeur de contenu apparaisse sur l'écran d'édition pour le type d'article personnalisé, car nous stockons notre contenu dans une boîte méta personnalisée.[1] (essentiellement un champ personnalisé), nous allons donc le cacher; et d'autres champs inutiles aussi, car il s'agira d'un type de message personnalisé privé.

    Voici un exemple pour vous donner une idée de la procédure à suivre:

    /*
     * Register Custom Post Types
     * DON'T FORGET TO FLUSH PERMALINKS
     *
     * http://justintadlock.com/archives/2013/09/13/register-post-type-cheat-sheet
     * https://Gist.github.com/justintadlock/6552000
     * http://core.trac.wordpress.org/browser/trunk/src/wp-includes/post.php
     */
    add_action( 'init', 'itsme_register_post_types' );
    function itsme_register_post_types() {
    
        // Post Type: Snippets
        register_post_type(
    
            // Keeping it unique so that it never conflicts with a plugin or theme
            'itsme_snippet',
    
            array(
                'description'         => 'Code snippets for sharing in posts.',
                'public'              => false, // NOTE!
                'publicly_queryable'  => false, // NOTE!
                'exclude_from_search' => true, // NOTE!
                'show_in_nav_menus'   => false,
                'show_ui'             => true,
                'show_in_menu'        => true,
                'show_in_admin_bar'   => false,
                'menu_position'       => 5, // Your choice.
                'menu_icon'           => null,
                'can_export'          => false,
                'delete_with_user'    => false,
                'hierarchical'        => false,
                'taxonomies'          => array(),
                'has_archive'         => false, // NOTE!
                'query_var'           => false, // NOTE!
                'capability_type'     => 'post',
                'rewrite' => array(
                    'slug'            => 'snippets',
                    'with_front'      => false,
                    'pages'           => false,
                    'feeds'           => false, // NOTE!
                ),
    
                // IMPORTANT! At least make sure that the 'editor' (Content Editor) is hidden - i.e. remove it from the array.
                'supports'             => array( 'title', 'revisions', ),
    
                'labels' => array(
                    'name'               => __( 'Snippets' ),
                    'singular_name'      => __( 'Snippet' ),
                    'menu_name'          => __( 'Snippets' ),
                    'name_admin_bar'     => __( 'Snippets' ),
                    'add_new'            => __( 'Add New' ),
                    'add_new_item'       => __( 'Add New Snippet' ),
                    'edit_item'          => __( 'Edit Snippet' ),
                    'new_item'           => __( 'New Snippet' ),
                    'view_item'          => __( 'View Snippet' ),
                    'search_items'       => __( 'Search Snippets' ),
                    'not_found'          => __( 'No Snippets found' ),
                    'not_found_in_trash' => __( 'No Snippets found in trash' ),
                    'all_items'          => __( 'All Snippets' ),
                    'parent_item'        => __( 'Parent Snippet' ),
                    'parent_item_colon'  => __( 'Parent Snippet:' ),
                    'archive_title'      => __( 'Snippets' ),
                )
            )
        );
    
    }
    

    Liens connexes: (car je n'ai donné aucune explication dans le code.)

  2. Créez une méta-boîte de type 'textarea' (essentiellement un champ personnalisé) qui apparaît uniquement sur l'écran d'édition pour les extraits de type publication personnalisé.

    Si vous ne savez pas comment en coder un , vous pouvez facilement en créer un en utilisant un plugin tel que Champs personnalisés avancés . Voici une capture d'écran juste pour vous donner une idée:

    Create a custom meta box using Advanced Custom Fields plugin

  3. Créez un shortcode personnalisé qui prend l'identifiant de la publication d'extrait de code et affiche le contenu (c'est-à-dire un extrait de code) entre les balises <pre>; avec tous les caractères spéciaux HTML correctement échappés, bien sûr.

    Voici un exemple pour vous donner une bonne idée:

    /*
     * Custom Shortcode: Snippet
     * USAGE: [snippet id="188"], where id = Snippet (CPT) post's ID
     *
     * http://wpquestions.com/question/showChrono?id=8901
     */
    add_shortcode( 'snippet', 'bbcode_snippet' );
    function bbcode_snippet( $atts ) {
        extract( shortcode_atts( array(
            'id' => null,
        ), $atts ) );
    
        $post = get_post( $id );
        $content = $post->post_content;
        $content = trim( htmlspecialchars( clean_pre( $content ) ) );
    
        return '<pre><code>' . $content . '</code></pre>';
    }
    

    Liens associés:

  4. Pour simplifier un peu les choses, créez une boîte méta personnalisée affichant le shortcode à utiliser (par exemple [snippet id="120"]) sur l'écran d'édition du type de message personnalisé (Snippets). Ainsi, une fois que vous avez publié l'extrait de code, vous pouvez copier le shortcode pour l'incorporer dans vos messages.

    add_action( 'add_meta_boxes', 'itsme_custom_meta_boxes' );
    function itsme_custom_meta_boxes() {
        add_meta_box(
    
            // HTML 'id' attribute of the edit screen section (AKA meta box)
            'itsme-snippet-shortcode-box',
    
            // Title of the meta box, visible to user
            esc_html__( 'Snippet Shortcode' ),
    
            // Callback function
            'itsme_snippet_shortcode_box',
    
            // Custom post type on whose edit screen to show meta box
            'aahank_vault',
    
            // The part of edit screen where the meta box should be shown
            'side',
    
            // Priority within the context where the meta box should show
            'high'
    
        );
    }
    
    // Function to display the meta box
    function itsme_snippet_shortcode_box() {
    
        global $post;
        $snippet_id = $post->ID;
        echo '<textarea rows="1" readonly="readonly" placeholder="Publish post first!" onclick="this.focus();this.select();">[snippet id="' . $snippet_id . '"]</textarea>';
    
    }
    

C'est à peu près tout ce dont nous avons besoin. La coloration syntaxique et les choses sont extra, je ne vais donc pas entrer dans les détails.

Notes de bas de page:

  1. Comme le dit Rodolfo, les plugins et les thèmes peuvent facilement gâcher the_content. Puisque nous voulons laisser nos extraits de code intacts (sauf siNOUSvoulons), nous utilisons un champ personnalisé pour stocker nos données, c’est-à-dire des extraits de code.

    De plus, WordPress, par défaut, a beaucoup de filtres sur the_content, ce qui rend assez complexe la tâche de faire ce que nous voulons. Utiliser un champ personnalisé à la place rend cela beaucoup plus facile et simple.

Idées:

  1. Vous pouvez utiliser une taxonomie personnalisée appelée language ou quelque chose pour organiser les publications du type de publication personnalisée, et même l'utiliser pour mettre en surbrillance le code.
1
its_me