' . __( 'Settings', '16deza-table-cell-extras' ) . ''; array_unshift( $links, $settings_link ); return $links; } /* ============================================================ エディター Assets の登録・エンキュー ============================================================ */ add_action( 'enqueue_block_editor_assets', 'tcex_enqueue_editor_assets' ); function tcex_enqueue_editor_assets() { $js_file = TCEX_PLUGIN_DIR . 'build/index.js'; $css_file = TCEX_PLUGIN_DIR . 'build/index.css'; if ( file_exists( $js_file ) ) { $asset_file = TCEX_PLUGIN_DIR . 'build/index.asset.php'; $asset = file_exists( $asset_file ) ? require $asset_file : [ 'dependencies' => [], 'version' => TCEX_VERSION ]; wp_enqueue_script( 'rich-table-cells-editor', TCEX_PLUGIN_URL . 'build/index.js', array_merge( $asset['dependencies'], [ 'wp-blocks', 'wp-element', 'wp-editor', 'wp-components', 'wp-rich-text', 'wp-hooks', 'wp-i18n', 'wp-data', 'wp-compose', ] ), $asset['version'], true ); /* プラグイン設定を JS に渡す */ wp_localize_script( 'rich-table-cells-editor', 'tcexSettings', [ 'allowOutsideTable' => (bool) get_option( 'tcex_allow_outside_table', false ), ] ); } if ( file_exists( $css_file ) ) { wp_enqueue_style( 'rich-table-cells-editor', TCEX_PLUGIN_URL . 'build/index.css', [ 'wp-edit-blocks' ], TCEX_VERSION ); } /* フロントエンド共通スタイルもエディターに読み込む */ wp_enqueue_style( 'rich-table-cells-frontend', TCEX_PLUGIN_URL . 'assets/css/frontend.css', [], TCEX_VERSION ); /* JS の翻訳ファイルを登録 */ wp_set_script_translations( 'rich-table-cells-editor', '16deza-table-cell-extras', TCEX_PLUGIN_DIR . 'languages' ); } /* ============================================================ フロントエンド用スタイルの読み込み ============================================================ */ add_action( 'wp_enqueue_scripts', 'tcex_enqueue_frontend_assets' ); function tcex_enqueue_frontend_assets() { wp_enqueue_style( 'rich-table-cells-frontend', TCEX_PLUGIN_URL . 'assets/css/frontend.css', [], TCEX_VERSION ); } /* ============================================================ render_block フィルター:セル背景色をフロントエンド HTML に適用 ============================================================ */ add_filter( 'render_block', 'tcex_render_table_block', 10, 2 ); function tcex_render_table_block( $block_content, $block ) { if ( 'core/table' !== $block['blockName'] ) { return $block_content; } $colors = isset( $block['attrs']['tcxCellBgColors'] ) ? $block['attrs']['tcxCellBgColors'] : []; if ( empty( $colors ) || ! is_array( $colors ) ) { return $block_content; } $dom = new DOMDocument( '1.0', 'UTF-8' ); libxml_use_internal_errors( true ); $dom->loadHTML( '
' . $block_content . '' ); libxml_clear_errors(); $table = $dom->getElementsByTagName( 'table' )->item( 0 ); if ( ! $table ) { return $block_content; } $section_map = [ 'head' => 'thead', 'body' => 'tbody', 'foot' => 'tfoot', ]; foreach ( $colors as $key => $color ) { /* カラーをサニタイズ(#rgb, #rrggbb のみ許可) */ if ( ! preg_match( '/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/', $color ) ) { continue; } $parts = explode( '_', $key, 3 ); if ( count( $parts ) < 3 ) { continue; } $sec = $parts[0]; $ri = (int) $parts[1]; $ci = (int) $parts[2]; if ( ! isset( $section_map[ $sec ] ) ) { continue; } $sections = $table->getElementsByTagName( $section_map[ $sec ] ); if ( 0 === $sections->length ) { continue; } $section_el = $sections->item( 0 ); $rows = $section_el->getElementsByTagName( 'tr' ); if ( $ri >= $rows->length ) { continue; } $row = $rows->item( $ri ); $cell_index = 0; foreach ( $row->childNodes as $cell ) { if ( XML_ELEMENT_NODE !== $cell->nodeType ) { continue; } if ( $cell_index === $ci ) { /* 既存の background-color を除去してから再設定 */ $existing = $cell->getAttribute( 'style' ); $existing = preg_replace( '/background-color\s*:[^;]*;?\s*/', '', $existing ); $new_style = trim( $existing ); $new_style = ( $new_style ? rtrim( $new_style, ';' ) . '; ' : '' ) . 'background-color:' . esc_attr( $color ) . ';'; $cell->setAttribute( 'style', trim( $new_style ) ); break; } $cell_index++; } } /* body 直下の子ノードを文字列化して返す */ $body = $dom->getElementsByTagName( 'body' )->item( 0 ); if ( ! $body ) { return $block_content; } $output = ''; foreach ( $body->childNodes as $child ) { $output .= $dom->saveHTML( $child ); } return $output; } /* ============================================================ 設定ページ ============================================================ */ add_action( 'admin_menu', 'tcex_add_settings_page' ); function tcex_add_settings_page() { add_options_page( __( '16Deza Table Cell Extras – Settings', '16deza-table-cell-extras' ), __( 'Table Cell Extras', '16deza-table-cell-extras' ), 'manage_options', 'table-cell-extras', 'tcex_render_settings_page' ); } add_action( 'admin_init', 'tcex_register_settings' ); function tcex_register_settings() { register_setting( 'tcex_options_group', 'tcex_allow_outside_table', [ 'type' => 'boolean', 'default' => false, 'sanitize_callback' => 'rest_sanitize_boolean', ] ); } function tcex_render_settings_page() { if ( ! current_user_can( 'manage_options' ) ) { return; } ?>