[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/media/plg_editors_tinymce/js/plugins/highlighter/ -> source.js (source)

   1  /**
   2   * source.js
   3   *
   4   * Original code by Arjan Haverkamp
   5   * Copyright 2013-2015 Arjan Haverkamp ([email protected])
   6   */
   7  if (!window.parent.Joomla || typeof window.parent.Joomla.getOptions !== 'function') {
   8    throw new Error('Joomla API not found');
   9  } // Get the base path for CodeMirror
  10  
  11  
  12  const rootPath = window.parent.Joomla.getOptions('system.paths').rootFull;
  13  const cmPath = `$rootPath}/media/vendor/codemirror`; // CodeMirror settings
  14  
  15  let CMsettings = {
  16    indentOnInit: true,
  17    config: {
  18      mode: 'htmlmixed',
  19      theme: 'default',
  20      lineNumbers: true,
  21      lineWrapping: true,
  22      indentUnit: 2,
  23      tabSize: 2,
  24      indentWithTabs: true,
  25      matchBrackets: true,
  26      saveCursorPosition: true,
  27      styleActiveLine: true
  28    },
  29    jsFiles: [// Default JS files
  30    `$cmPath}/lib/codemirror.min.js`, `$cmPath}/addon/edit/matchbrackets.min.js`, `$cmPath}/mode/xml/xml.min.js`, `$cmPath}/mode/javascript/javascript.min.js`, `$cmPath}/mode/css/css.min.js`, `$cmPath}/mode/htmlmixed/htmlmixed.min.js`, `$cmPath}/addon/dialog/dialog.min.js`, `$cmPath}/addon/search/searchcursor.min.js`, `$cmPath}/addon/search/search.min.js`, `$cmPath}/addon/selection/active-line.min.js`],
  31    cssFiles: [// Default CSS files
  32    `$cmPath}/lib/codemirror.css`, `$cmPath}/addon/dialog/dialog.css`]
  33  }; // Declare some variables:
  34  
  35  let tinymce; // Reference to TinyMCE
  36  
  37  let editor; // Reference to TinyMCE editor
  38  
  39  let codemirror; // CodeMirror instance
  40  
  41  const chr = 0; // Unused utf-8 character, placeholder for cursor
  42  
  43  const isMac = /macintosh|mac os/i.test(navigator.userAgent); // Utility function to load CodeMirror script files
  44  
  45  const loadScript = url => new Promise((resolve, reject) => {
  46    const script = document.createElement('script');
  47    script.src = url;
  48  
  49    script.onload = () => resolve();
  50  
  51    script.onerror = () => reject(new Error(`Failed to load the script $url}`));
  52  
  53    document.head.appendChild(script);
  54  });
  55  /**
  56   * Find the depth level
  57   */
  58  
  59  
  60  const findDepth = (haystack, needle) => {
  61    const idx = haystack.indexOf(needle);
  62    let depth = 0;
  63  
  64    for (let x = idx - 1; x >= 0; x -= 1) {
  65      switch (haystack.charAt(x)) {
  66        case '<':
  67          depth -= 1;
  68          break;
  69  
  70        case '>':
  71          depth += 1;
  72          break;
  73  
  74        case '&':
  75          depth += 1;
  76          break;
  77      }
  78    }
  79  
  80    return depth;
  81  };
  82  /**
  83   * This function is called by plugin.js, when user clicks 'Ok' button
  84   */
  85  
  86  
  87  window.tinymceHighlighterSubmit = () => {
  88    const cc = '&#x0;';
  89    const {
  90      isDirty
  91    } = codemirror;
  92    const {
  93      doc
  94    } = codemirror;
  95  
  96    if (doc.somethingSelected()) {
  97      // Clear selection:
  98      doc.setCursor(doc.getCursor());
  99    } // Insert cursor placeholder (&#x0;)
 100  
 101  
 102    doc.replaceSelection(cc);
 103    const pos = codemirror.getCursor();
 104    let curLineHTML = doc.getLine(pos.line);
 105  
 106    if (findDepth(curLineHTML, cc) !== 0) {
 107      // Cursor is inside a <tag>, don't set cursor:
 108      curLineHTML = curLineHTML.replace(cc, '');
 109      doc.replaceRange(curLineHTML, window.CodeMirror.Pos(pos.line, 0), window.CodeMirror.Pos(pos.line));
 110    } // Submit HTML to TinyMCE:
 111    // [FIX] Cursor position inside JS, style or &nbps;
 112    // Workaround to fix cursor position if inside script tag
 113  
 114  
 115    const code = codemirror.getValue();
 116    /* Regex to check if inside script or style tags */
 117  
 118    const ccScript = new RegExp(`<script(.*?)>(.*?)$cc}(.*?)</script>`, 'ms');
 119    const ccStyle = new RegExp(`<style(.*?)>(.*?)$cc}(.*?)</style>`, 'ms');
 120    /* Regex to check if in beginning or end or if between < & > */
 121  
 122    const ccLocationCheck = new RegExp(`<[^>]*($cc}).*>|^($cc})|($cc})$`);
 123  
 124    if (code.search(ccScript) !== -1 || code.search(ccStyle) !== -1 || code.search(ccLocationCheck) !== -1) {
 125      editor.setContent(code.replace(cc, ''));
 126    } else {
 127      editor.setContent(code.replace(cc, '<span id="CmCaReT"></span>'));
 128    }
 129  
 130    editor.isNotDirty = !isDirty;
 131  
 132    if (isDirty) {
 133      editor.nodeChanged();
 134    } // Set cursor:
 135  
 136  
 137    const el = editor.dom.select('span#CmCaReT')[0];
 138  
 139    if (el) {
 140      editor.selection.scrollIntoView(el);
 141      editor.selection.setCursorLocation(el, 0);
 142      editor.dom.remove(el);
 143    }
 144  };
 145  /**
 146   * Listen for the escape key and close the modal
 147   *
 148   * @param {Event} evt
 149   */
 150  
 151  
 152  document.addEventListener('keydown', evt => {
 153    const event = evt || window.event;
 154    let isEscape = false;
 155    if ('key' in event) isEscape = event.key === 'Escape' || event.key === 'Esc';else isEscape = event.keyCode === 27;
 156    if (isEscape) tinymce.activeEditor.windowManager.close();
 157  });
 158  /**
 159   * Append some help text in the modal footer
 160   */
 161  
 162  const start = () => {
 163    // Initialise (on load)
 164    if (typeof window.CodeMirror !== 'function') {
 165      throw new Error(`CodeMirror not found in "$CMsettings.path}", aborting...`);
 166    } // Create legend for keyboard shortcuts for find & replace:
 167  
 168  
 169    const head = window.parent.document.querySelectorAll('.tox-dialog__footer')[0];
 170    const div = window.parent.document.createElement('div');
 171    const td1 = '<td style="font-size:11px;background:#777;color:#fff;padding:0 4px">';
 172    const td2 = '<td style="font-size:11px;padding-right:5px">';
 173    div.innerHTML = `
 174  <table cellspacing="0" cellpadding="0" style="border-spacing:4px">
 175    <tr>
 176      $td1}$isMac ? '&#8984;-F' : 'Ctrl-F</td>'}$td2}$tinymce.translate('Start search')}</td>
 177      $td1}$isMac ? '&#8984;-G' : 'Ctrl-G'}</td>
 178      $td2}$tinymce.translate('Find next')}</td>
 179      $td1}$isMac ? '&#8984;-Alt-F' : 'Shift-Ctrl-F'}</td>
 180      $td2}$tinymce.translate('Find previous')}</td>
 181    </tr>
 182    <tr>
 183      $td1}$isMac ? '&#8984;-Alt-F' : 'Shift-Ctrl-F'}</td>
 184      $td2}$tinymce.translate('Replace')}</td>
 185      $td1}$isMac ? 'Shift-&#8984;-Alt-F' : 'Shift-Ctrl-R'}</td>
 186      $td2}$tinymce.translate('Replace all')}</td>
 187    </tr>
 188  </table>`;
 189    div.style.position = 'absolute';
 190    div.style.left = '5px';
 191    div.style.bottom = '5px';
 192    head.appendChild(div); // Set CodeMirror cursor and bookmark to same position as cursor was in TinyMCE:
 193  
 194    let html = editor.getContent({
 195      source_view: true
 196    }); // [FIX] #6 z-index issue with table panel and source code dialog
 197    //  editor.selection.getBookmark();
 198  
 199    html = html.replace(/<span\s+style="display: none;"\s+class="CmCaReT"([^>]*)>([^<]*)<\/span>/gm, String.fromCharCode(chr));
 200    editor.dom.remove(editor.dom.select('.CmCaReT')); // Hide TinyMCE toolbar panels, [FIX] #6 z-index issue with table panel and source code dialog
 201    // https://github.com/christiaan/tinymce-codemirror/issues/6
 202  
 203    tinymce.each(editor.contextToolbars, toolbar => {
 204      if (toolbar.panel) {
 205        toolbar.panel.hide();
 206      }
 207    });
 208    window.CodeMirror.defineInitHook(inst => {
 209      // Move cursor to correct position:
 210      inst.focus();
 211      const cursor = inst.getSearchCursor(String.fromCharCode(chr), false);
 212  
 213      if (cursor.findNext()) {
 214        inst.setCursor(cursor.to());
 215        cursor.replace('');
 216      } // Indent all code, if so requested:
 217  
 218  
 219      if (editor.settings.codemirror.indentOnInit) {
 220        const last = inst.lineCount();
 221        inst.operation(() => {
 222          // eslint-disable-next-line no-plusplus
 223          for (let i = 0; i < last; ++i) {
 224            inst.indentLine(i);
 225          }
 226        });
 227      }
 228    });
 229    CMsettings.config.value = html; // Instantiate CodeMirror:
 230  
 231    codemirror = window.CodeMirror(document.body, CMsettings.config);
 232    codemirror.isDirty = false;
 233    codemirror.on('change', inst => {
 234      inst.isDirty = true;
 235    });
 236    codemirror.setSize('100%', '100%');
 237    codemirror.refresh();
 238  }; // Initialise
 239  
 240  
 241  tinymce = window.parent.tinymce;
 242  
 243  if (!tinymce) {
 244    throw new Error('tinyMCE not found');
 245  }
 246  
 247  editor = tinymce.activeEditor;
 248  const userSettings = editor.settings.codemirror;
 249  
 250  if (userSettings.fullscreen) {
 251    CMsettings.jsFiles.push(`$cmPath}/addon/display/fullscreen.min.js`);
 252    CMsettings.cssFiles.push(`$cmPath}/addon/display/fullscreen.css`);
 253  } // Merge config
 254  
 255  
 256  CMsettings = { ...CMsettings,
 257    ...userSettings
 258  }; // Append the stylesheets
 259  
 260  CMsettings.cssFiles.forEach(css => {
 261    const link = document.createElement('link');
 262    link.rel = 'stylesheet';
 263    link.href = css;
 264    document.head.appendChild(link);
 265  });
 266  /**
 267   * Append javascript files ensuring the order of execution.
 268   * Then execute the start function.
 269   */
 270  
 271  CMsettings.jsFiles.reduce((p, item) => p.then(() => loadScript(item)), Promise.resolve(true)).then(() => {
 272    // Borrowed from codemirror.js themeChanged function. Sets the theme's class names to the html element.
 273    // Without this, the background color outside of the codemirror wrapper element remains white.
 274    // [TMP] commented temporary, cause JS error: Uncaught TypeError: Cannot read property 'replace' of undefined
 275    if (CMsettings.config.theme) {
 276      document.documentElement.className += CMsettings.config.theme.replace(/(^|\s)\s*/g, ' cm-s-');
 277    }
 278  
 279    start();
 280  });


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer