tesutodayo

(() => {
  const { registerBlockVariation } = wp.blocks || {};
  const domReady = (wp && wp.domReady) || null;
  const { addFilter } = wp.hooks || {};
  const { createHigherOrderComponent } = wp.compose || {};
  const { Fragment, createElement: el } = wp.element || {};
  const { PanelBody, SelectControl } = wp.components || {};
  const { InspectorControls } = wp.blockEditor || wp.editor || {};

  if (!registerBlockVariation || !domReady) {
    return;
  }

  domReady(() => {
    // Add a variation so "/" search suggests a Code block with copy/highlight.
    registerBlockVariation('core/code', {
      name: 'mchl-code-copy',
      title: 'Code (Copy Button)',
      description: 'Prismハイライト+コピー付きコードブロック',
      keywords: ['code', 'copy', 'コード', 'コピー', 'codeblock'],
      attributes: {},
      scope: ['inserter', 'transform'],
    });

    // Add Inspector control for language selection on core/code.
    if (addFilter && createHigherOrderComponent && InspectorControls && SelectControl) {
      const LANG_OPTIONS = [
        { label: 'Auto / 未指定', value: '' },
        { label: 'PHP', value: 'php' },
        { label: 'JavaScript', value: 'js' },
        { label: 'TypeScript', value: 'ts' },
        { label: 'HTML', value: 'markup' },
        { label: 'CSS', value: 'css' },
        { label: 'JSON', value: 'json' },
        { label: 'Python', value: 'python' },
        { label: 'Ruby', value: 'ruby' },
        { label: 'Go', value: 'go' },
        { label: 'C', value: 'c' },
        { label: 'C++', value: 'cpp' },
        { label: 'Java', value: 'java' },
        { label: 'Shell', value: 'bash' },
        { label: 'SQL', value: 'sql' },
        { label: 'YAML', value: 'yaml' },
        { label: 'Markdown', value: 'markdown' },
      ];

      const withLanguageSelector = createHigherOrderComponent((BlockEdit) => {
        return (props) => {
          if (props.name !== 'core/code') {
            return el(BlockEdit, props);
          }

          const currentClass = props.attributes.className || '';
          const match = currentClass.match(/\blanguage-([^\s]+)/);
          const currentLang = match ? match[1] : '';

          const onChangeLang = (value) => {
            const withoutLang = currentClass
              .split(/\s+/)
              .filter((cls) => cls && !cls.startsWith('language-'))
              .join(' ');
            const nextClass = value ? `${withoutLang} language-${value}`.trim() : withoutLang || undefined;
            props.setAttributes({ className: nextClass });
          };

          return el(
            Fragment,
            null,
            el(BlockEdit, props),
            el(
              InspectorControls,
              null,
              el(
                PanelBody,
                { title: 'Syntax Highlight', initialOpen: true },
                el(SelectControl, {
                  label: '言語',
                  value: currentLang,
                  options: LANG_OPTIONS,
                  onChange: onChangeLang,
                  help: 'Prismのlanguage-xxxを設定します。未指定なら自動判定に任せます。',
                })
              )
            )
          );
        };
      }, 'withLanguageSelector');

      addFilter(
        'editor.BlockEdit',
        'mchl/code-language-selector',
        withLanguageSelector
      );
    }
  });
})();

コメント

タイトルとURLをコピーしました