編輯器 < ruby > 支援

//以下源碼實作 Froala Editor 的 <ruby> 支援。

// Froala Editor <ruby> support by Sheepy.  Tested on editor version 3.1.0.
// CC BY-SA 4.0 https://creativecommons.org/licenses/by-sa/4.0/
( () => { 'use strict';
const f = FroalaEditor;
if ( f.COMMANDS.rubyBtn ) return;
// Ruby button
f.DefineIconTemplate( 'rubySvg', '<svg class="fr-svg" viewBox="0 0 24 24" style="fill:#333"><text y="22" x="6" font-size="18px">R</text><text y="6" x="5" font-size="8px">abc</text></svg>' );
f.DefineIcon( 'rubyIco', { template:'rubySvg' } );
f.RegisterCommand( 'rubyBtn', { title:'Ruby', icon:'rubyIco', callback: function () { this.rubyPlugin.showPopup() } } );
f.RegisterShortcut( 192, 'rubyBtn', '', '`' );
// Ruby popup
f.POPUP_TEMPLATES.rubyPopup = '<div class="fr-link-insert-layer fr-layer" style="display:block"><div class="fr-input-line"><input id="fr-ruby-rt" type="text" class="fr-link-attr" tabindex="1"><label for="fr-ruby-rt">Annotation</label></div><div class="fr-input-line"><input id="fr-ruby" type="text" class="fr-link-attr"><label for="fr-ruby">Text</label></div><div class="fr-action-buttons"><button id="fr-ruby-add" class="fr-command fr-submit" type="button">Insert</button></div></div>';
f.PLUGINS.rubyPlugin = function ( editor ) {
   const { format, html, popups, selection } = editor;
   function qs ( e, query = '' ) { return ( query ? e : document ).querySelector( query || e ); }
   function getRubyInput () { return qs( '#fr-ruby-rt' ); }
   function getTextInput () { return qs( '#fr-ruby' ); }
   function getAddButton () { return qs( '#fr-ruby-add' ); }
   function showPopup () {
      if ( ! popups.get( 'rubyPopup' ) ) {
         popups.create( 'rubyPopup' );
         popups.onRefresh( 'rubyPopup', refreshPopup );
         getAddButton().addEventListener( 'click', () => {
            hidePopup();
            insert( getRubyInput().value, getTextInput().value );
         } );
      }
      popups.setContainer( 'rubyPopup', editor.$tb );
      popups.refresh( 'rubyPopup' );
      const btn = editor.$tb.find( '.fr-command[data-cmd="rubyBtn"]' );
      const top = btn.offset().top + ( editor.opts.toolbarBottom ? 10 : btn.outerHeight() - 10 );
      popups.show( 'rubyPopup', btn.offset().left, top, btn.outerHeight() );
      getRubyInput().select();
   }
   function hidePopup () { popups.hide('rubyPopup') };
   function refreshPopup () {
      function setValue ( sel, val ) {
         sel.value = val;
         sel.classList[ val ? 'add' : 'remove' ]( 'fr-not-empty' );
      }
      const r = selection.element().querySelector( 'rt' );
      setValue( getRubyInput(), r ? r.textContent : '' );
      setValue( getTextInput(), selection.text() );
   }
   function insert ( rt, txt = null ) {
      const rprt = '<rp>(</rp><rt></rt><rp>)</rp>';
      if ( txt === null ) txt = selection.text();
      if ( ! txt ) return;
      if ( txt !== selection.text() ) {
         // Insert new text with or without ruby.
         const ruby = document.createElement( 'ruby' );
         ruby.textContent = txt;
         if ( rt ) {
            ruby.insertAdjacentHTML( 'beforeend', rprt );
            ruby.querySelector( 'rt' ).textContent = rt;
         }
         html.insert( ruby[ rt ? 'outerHTML' : 'innerHTML' ], false );
      } else {
         // Remove old ruby.
         for ( let blk of selection.blocks() )
            for ( let e of blk.querySelectorAll( 'rp, rt' ) )
               e.remove();
         format.remove( 'ruby' );
         if ( rt === '' ) return;
         // Apply new ruby.
         format.apply( 'ruby' );
         selection.element().insertAdjacentHTML( 'beforeend', rprt );
         selection.element().querySelector( 'rt' ).textContent = rt;
      }
   }
   return { showPopup, hidePopup, insert, remove: () => insert( '' ) };
}
} )();

//以下源碼會重整本站的發帖編輯器,加入 Ruby 按鍵。

( () => {
   const e = window.editor, ae = e.artEditor, { opts } = ae;
   opts.toolbarButtons[0].push( 'rubyBtn' );
   opts.pluginsEnabled.push( 'rubyPlugin' );
   ae.destroy();
   e.artEditor = new FroalaEditor( "#artEditor", opts );
} )();

你的回應