MediaWiki:Gadget-code-prettify.js:修订间差异

H萌娘,万物皆可H的百科全书!
跳到导航 跳到搜索
imported>=海豚=
无编辑摘要
imported>=海豚=
无编辑摘要
第1行: 第1行:
//<nowiki>
// 由ResourceLoader直接调用,不可使用ES6语法
/**
/**
  * @Function: 高亮JavaScript、CSS、HTML和Lua,按行号跳转,并添加行号和指示色块
  * @name highlight.js
  * @Dependencies: ext.gadget.site-lib
  * @description 为页面内 代码块提供语法高亮
  * @Source: [[moegirl:mediawiki:gadget-code-prettify.js]]和[[moegirl:user:机智 小鱼君/gadget/Highlight.js]]
* @EditedBy: [[User:Bhsd]]
  */
  */
"use strict";
!(async () => {
/*global hljs */
  // 为代码页面添加 class
const acceptLangs = {js: "javascript", javascript: "javascript", json: "json", css: "css", html: "xml",
  const pageName = mw.config.get('wgPageName')
    scribunto: "lua", lua: "lua"},
  if (pageName.substr(pageName.length - 3, 3) === '.js') {
    contentModel = mw.config.get( "wgPageContentModel" ).toLowerCase();
   $('#mw-content-text pre.mw-code').addClass('lang-js highlight linenums')
  } else if (pageName.substr(pageName.length - 4, 4) === '.css') {
   $('#mw-content-text pre.mw-code').addClass('lang-css highlight linenums')
  } else if (
    // Lua
    mw.config.get('wgNamespaceNumber') === 828 &&
   pageName.substr(pageName.length - 4, 4) !== '/doc'
  ) {
   $('#mw-content-text pre.mw-code').addClass('lang-lua highlight linenums')
  }


mw.hook( 'wikipage.content' ).add(function($content) {
  // 兼容站内现有写法
    if (contentModel in acceptLangs) {
  $('pre.prettyprint')
      $content.find( '.mw-code' ).addClass('hljs linenums ' + acceptLangs[contentModel]);
   .addClass('highlight')
   .removeClass('prettyprint')
 
  // 定死表格内pre的宽度,防止table的宽度异常导致抑郁
  $('#mw-content-text table:not(.mw-collapsible) pre.highlight').css('width', function() {
   return $(this).width() > 0 ? $(this).width() : undefined
  })
 
  // 加载脚本
  try {
   await $.ajax({
    url:
     'https://cdn.jsdelivr.net/gh/highlightjs/[email protected]/build/highlight.min.js',
    dataType: 'script',
    cache: true
   })
  } catch (err) {
   return console.warn('Highlight.js load error', err)
  }
 
  // 初始化高亮
  $('#mw-content-text pre.highlight').each(function(_, block) {
   const $block = $(block)
 
   // 高亮当前块
   if ($block.data('hljs') !== 'done') {
    hljs.highlightBlock(block)
    $block.data('hljs', 'done')
    }
 
   // 行号显示
   if (
    $block.data('line-from') !== undefined ||
    $block.data('line-ping') !== undefined
   ) {
    $block.addClass('linenums')
   }
   if ($block.hasClass('linenums')) {
    // 起始行号
    let lineNumFrom = parseInt($block.data('line-from'))
    if (isNaN(lineNumFrom) || lineNumFrom < 1) lineNumFrom = 1
 
    // 高亮行号
    let pingLine = $block.data('line-emphatic') || $block.data('line-ping')
    if (typeof pingLine === 'number') pingLine = [pingLine]
    if (typeof pingLine === 'string')
     pingLine = pingLine.replace(/\s/g, '').split(',')
    if (typeof pingLine !== 'object') pingLine = []
 
    $block.html(function() {
      const $thisBlock = $(this)
 
     // 创建 jQuery 对象
     const $html = $('<div>', { class: 'line-container' }).append(
      $('<div>', { class: 'line-content' }),
      $('<div>', { class: 'line-numbers' })
     )
 
     // 处理内部有换行的span标签
     $thisBlock.find('span').html(function() {
      const $span = $(this)
      let html = $span.html()
      let openTag = $span.prop('outerHTML').split('>')[0] + '>'
      html = html.replace(/\n/g, `</span>\n${openTag}`)
      return html
     })
 
     // 拆开每一行
     let splitHtml = $thisBlock.html().split('\n')
     $.each(splitHtml, (lineNum, lineContent) => {
      // 防止最后一行后被添加一行空行
      if (lineNum + 1 === splitHtml.length) return
 
      // 显示行号为起始行号加当前行号
      displayLineNum = lineNum + lineNumFrom
 
      // 是否高亮显示
      let isPing = ''
      if (pingLine.includes(lineNum + 1)) {
       isPing = 'line-ping'
      }
 
      // 添加行号
      $html.find('.line-numbers').append(
       $('<div>', {
        class: `line-number-block ${isPing}`,
        text: displayLineNum
       })
      )
 
      // 添加内容
      $html
       .find('.line-content')
       .append(
        $('<div>', { class: `line-row ${isPing}`, html: lineContent })
       )
     })
 
     return $html
    })
    }
    }
   $content.find('pre[lang], code[lang]').addClass(function() {
  })
     const $self = $(this),
})()
       lang = $self.attr( "lang" ).toLowerCase();
     if (lang in acceptLangs) { return "hljs " + acceptLangs[lang] + ($self.is('pre') ? " linenums" : ""); }
   });
   const $block = $content.find( '.hljs:not(.highlighted)' ); // 不重复高亮
   if ($block.length === 0) { return; }
   console.log('Hook: wikipage.content, 开始执行语法高亮');
   const path = '//cdn.jsdelivr.net/gh/highlightjs/[email protected]/build/highlight.min.js';
   (window.hljs ? Promise.resolve() : mw.loader.getScript( path )).then(function() { // 不重复下载脚本
     $block.each(function() { hljs.highlightBlock( this ); }).addClass( 'highlighted' ).filter( '.linenums' )
       .html(function() { // 添加行号。这里不使用<table>排版,而是使用<ol>
       const $this = $(this);
       $this.children( ':contains(\n)' ).replaceWith(function() { // 先处理跨行元素
         const $self = $(this);
         return $self.html().split( '\n' ).map(function(ele) {
           return $self.clone().html( ele ).prop( 'outerHTML' );
         }).join('\n');
       });
       var lines = $this.html().replace(/\n$/, '').split('\n');
       if (mw.config.get( 'wgNamespaceNumber' ) == 274) { lines = lines.slice(1, -1); } // 扔掉首尾的Wikitext注释
       return $('<ol>', {html: lines.map(function(ele, i) { return $('<li>', {html: ele, id: 'L' + (i + 1)}); })})
         .css('padding-left', lines.length.toString().length + 2.5 + 'ch');
     });
     mw.hook( 'code.prettify' ).fire( $block );
     const $cssblock = $block.filter( '.css' ); // 对CSS代码添加指示色块
     if ($cssblock.length === 0) { return; }
     const $color = $('<span>', {class: 'hljs-color'});
     $cssblock.find( '.hljs-number:contains(#)' ).before(function() { // 16进制颜色
       const color = this.textContent,
         n = color.length,
         alpha = n == 5 ? color[4].repeat(2) : color.slice(7);
       return $color.clone().css({ color: color.slice(0, n > 5 ? 7 : 4),
         opacity: alpha ? parseInt(alpha, 16) / 255 : undefined });
     });
     $cssblock.find( '.hljs-built_in:contains(rgb), .hljs-built_in:contains(hsl)' ).before(function() { // RGB颜色
       const $siblings = $(this).parent().contents(), // 标点符号都是text节点,所以需要使用contents
         index = $siblings.index( this ),
         n = this.textContent.length == 4 ? 9 : 7, // rgba/hsla或rgb/hsl
         // 右半括号那一项可能有分号
         color = $siblings.slice(index, index + n).map(function() { return this.textContent; }).toArray();
       return $color.clone().css({ color: color[0].slice(0, 3) + color.slice(1, 7).join('') + ')',
         opacity: color[8] });
     });
     // 手动跳转
     const fragment = decodeURIComponent( location.hash.slice(1) ),
       target = document.getElementById( fragment ); // 用户输入内容,禁止使用$()
     if (/^L\d+$/.test( fragment ) && target) { target.scrollIntoView({ behavior: 'smooth' }); }
   }, function(reason) { mw.apiFailure(reason, 'highlight.js'); });
});
//</nowiki>

2021年5月7日 (五) 21:36的版本

/**
 * @name highlight.js
 * @description 为页面内的代码块提供语法高亮
 */
!(async () => {
  // 为代码页面添加 class
  const pageName = mw.config.get('wgPageName')
  if (pageName.substr(pageName.length - 3, 3) === '.js') {
    $('#mw-content-text pre.mw-code').addClass('lang-js highlight linenums')
  } else if (pageName.substr(pageName.length - 4, 4) === '.css') {
    $('#mw-content-text pre.mw-code').addClass('lang-css highlight linenums')
  } else if (
    // Lua
    mw.config.get('wgNamespaceNumber') === 828 &&
    pageName.substr(pageName.length - 4, 4) !== '/doc'
  ) {
    $('#mw-content-text pre.mw-code').addClass('lang-lua highlight linenums')
  }

  // 兼容站内现有写法
  $('pre.prettyprint')
    .addClass('highlight')
    .removeClass('prettyprint')

  // 定死表格内pre的宽度,防止table的宽度异常导致抑郁
  $('#mw-content-text table:not(.mw-collapsible) pre.highlight').css('width', function() {
    return $(this).width() > 0 ? $(this).width() : undefined
  })

  // 加载脚本
  try {
    await $.ajax({
      url:
        'https://cdn.jsdelivr.net/gh/highlightjs/[email protected]/build/highlight.min.js',
      dataType: 'script',
      cache: true
    })
  } catch (err) {
    return console.warn('Highlight.js load error', err)
  }

  // 初始化高亮
  $('#mw-content-text pre.highlight').each(function(_, block) {
    const $block = $(block)

    // 高亮当前块
    if ($block.data('hljs') !== 'done') {
      hljs.highlightBlock(block)
      $block.data('hljs', 'done')
    }

    // 行号显示
    if (
      $block.data('line-from') !== undefined ||
      $block.data('line-ping') !== undefined
    ) {
      $block.addClass('linenums')
    }
    if ($block.hasClass('linenums')) {
      // 起始行号
      let lineNumFrom = parseInt($block.data('line-from'))
      if (isNaN(lineNumFrom) || lineNumFrom < 1) lineNumFrom = 1

      // 高亮行号
      let pingLine = $block.data('line-emphatic') || $block.data('line-ping')
      if (typeof pingLine === 'number') pingLine = [pingLine]
      if (typeof pingLine === 'string')
        pingLine = pingLine.replace(/\s/g, '').split(',')
      if (typeof pingLine !== 'object') pingLine = []

      $block.html(function() {
        const $thisBlock = $(this)

        // 创建 jQuery 对象
        const $html = $('<div>', { class: 'line-container' }).append(
          $('<div>', { class: 'line-content' }),
          $('<div>', { class: 'line-numbers' })
        )

        // 处理内部有换行的span标签
        $thisBlock.find('span').html(function() {
          const $span = $(this)
          let html = $span.html()
          let openTag = $span.prop('outerHTML').split('>')[0] + '>'
          html = html.replace(/\n/g, `</span>\n${openTag}`)
          return html
        })

        // 拆开每一行
        let splitHtml = $thisBlock.html().split('\n')
        $.each(splitHtml, (lineNum, lineContent) => {
          // 防止最后一行后被添加一行空行
          if (lineNum + 1 === splitHtml.length) return

          // 显示行号为起始行号加当前行号
          displayLineNum = lineNum + lineNumFrom

          // 是否高亮显示
          let isPing = ''
          if (pingLine.includes(lineNum + 1)) {
            isPing = 'line-ping'
          }

          // 添加行号
          $html.find('.line-numbers').append(
            $('<div>', {
              class: `line-number-block ${isPing}`,
              text: displayLineNum
            })
          )

          // 添加内容
          $html
            .find('.line-content')
            .append(
              $('<div>', { class: `line-row ${isPing}`, html: lineContent })
            )
        })

        return $html
      })
    }
  })
})()