web-dev-qa-db-ja.com

カスタムの[ソースコード]ショートコードを作成する、正しい方法は?

私がやりたいこと

WordPressの投稿でコードを共有することは、すべてのHTMLが世話をするのを避けるために非常に面倒です。そこで、以下に示すように、[sourcecode]と呼ばれる カスタムショートコード でポストにコードを囲み、自動的に特殊文字をエスケープするようにします。

[sourcecode]
<?php

    // Some code here.

?>
[/sourcecode]

コード

そしてこれが(私のテーマのfunctions.phpの中の)関連する関数のようなものです。

/**
 * 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
 */

質問

説明が邪魔にならないようになりました...

  1. 私は他に何かが足りないのですか?

    例えば、 SyntaxHighlighter Evolved pluginのソースを読むまで、\0&#92;&#48;で置き換える必要があることを知りませんでした(これは私にとっては十分に明確ではありませんでした)。

  2. そして、特殊文字をエスケープする以外に、私が見逃している可能性がある何か他のものはありますか?私は正しいやり方ですか?

    (誰かが このファイル (SyntaxHighlighter EvolvedプラグインのPHPソースコード)を見て、私が実装する必要があるものを見つけることができるかどうかを確認できれば素晴らしいと思います。


PS:プラグイン自体を使用しないのはなぜですか? 1つには、構文の強調表示がしたくないためです。そしてそれが何をするのが簡単に実装できるかどうか知りたいのです。

5
its_me

あなたはXについて質問していますが、私は Y と答えます。私見、他の解決策を認めるために扱うには多すぎる例外があります。

SyntaxHighlighter Evolvedは以下のものを持っています Pro Tip (オリジナルでは強い、大文字):

ヒント:コードを壊したくない場合は、ビジュアルエディタを使用しないでください。 TinyMCEはあなたのHTMLを「片付ける」でしょう。

それだけでなく、プラグインやテーマをthe_contentでめちゃくちゃにするのはごく普通のことです。大まかな(そしてまったく科学的でない)対策:50のプラグイン内で10の発生。 50テーマ中に15回発生。

もう一つ プロのヒント

enter image description here

提案された解決策

1)コードを処理するには、[投稿編集]画面の[カスタムフィールド/ボックス]か、投稿と "プライベート"の間のブリッジのいずれかと考えますコードを保存するカスタム投稿タイプ。私は後者が好きです。ステップ:

  • <textarea>でレンダリングされたedit_form_after_titleに埋め込みコードを貼り付けます
  • バックエンドに表示するにはesc_htmlを使用してください
  • フロントエンドの'<pre class="pretty">'.htmlentities($code).</pre>

2)構文のハイライトを処理するために、望ましい方法を選ぶのは読者次第です。 Google Prettifyは文字通り2行のコードで、<pre>タグにクラスを追加しています。スクリプトのみをエンキューする ショートコードが存在する場合

サンプルプラグイン

カスタム投稿タイプ enter image description here

投稿の投稿タイプ
enter image description here

以下はスケルトンであり、ロジックの概要のみを説明しています。そして、ここにいくつかのグッズへのリンクがあります。
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

念のために Rodolfo's answer が明確ではない場合、彼が提案しているのはこれだ。

  1. スニペットと呼ばれる private カスタム投稿タイプを作成し、その投稿にコードスニペットを保存します。

    私達は私達の利点のためにregister_post_typesupports引数を使います。コンテンツをカスタムメタボックスに保存するので、カスタム投稿タイプの編集画面にコンテンツエディタを表示したくありません。[1] (基本的にはカスタムフィールドです)ので、非表示にします。その他の不要なフィールドも private カスタム投稿タイプになります。

    これがどのように行われるかについてのアイデアをあなたに与えるための例です:

    /*
     * 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' ),
                )
            )
        );
    
    }
    

    関連リンク:(コード内で説明をしていないため)

  2. カスタム投稿タイプのスニペットの編集画面にのみ表示される 'textarea'タイプのメタボックス(基本的にはカスタムフィールド)を作成します。

    コーディング方法 がわからない場合は、 Advanced Custom Fields のようなプラグインを使用して簡単に作成できます。これはあなたにアイデアを与えるためのスクリーンショットです。

    Create a custom meta box using Advanced Custom Fields plugin

  3. スニペット投稿のIDを取り込み、<pre>タグの間にコンテンツ(コードスニペットなど)を表示するカスタムショートコードを作成します。もちろん、すべてのHTML特殊文字は正しくエスケープされています。

    ここにあなたに良い考えを与えるための例があります:

    /*
     * 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>';
    }
    

    関連リンク:

  4. 作業を少し簡単にするために、カスタム投稿タイプ(スニペット)の編集画面に、使用するショートコード(例:[snippet id="120"])を表示するカスタムメタボックスを作成します。スニペットを公開したら、投稿にコードを埋め込むためのショートコードをコピーできます。

    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>';
    
    }
    

これで、必要なことはほとんどすべてです。構文の強調表示や内容は余分なので、これ以上詳しく説明しません。

脚注:

  1. Rodolfoが言ったように、プラグインとテーマはthe_contentで簡単にめちゃくちゃになります。 (WEにしたくないのであれば)コードスニペットはそのまま残しておきたいので、カスタムフィールドを使ってデータを保存しています。つまり、コードスニペットです。

    また、WordPressはデフォルトでthe_contentにたくさんのフィルタを持っているので、私たちが望むことをするのは非常に複雑です。代わりにカスタムフィールドを使用すると、はるかに簡単でわかりやすくなります。

アイデア:

  1. languageなどのカスタム分類法を使用してカスタム投稿タイプの投稿を整理したり、構文ハイライトコードに使用することもできます。
1
its_me