【问题标题】:How to use webworkers to highlight source code blocks using highlightjs?如何使用 webworkers 使用 highlightjs 突出显示源代码块?
【发布时间】:2022-01-14 15:41:17
【问题描述】:

我如何使用一个或多个网络工作者来突出显示我网站上的多个小源代码块?

【问题讨论】:

    标签: syntax-highlighting web-worker highlightjs


    【解决方案1】:

    使用一名网络工作者的示例

    要仅使用一个 webworker 来突出显示多个代码块,您可以使用以下代码,其中 highlight_code_worker_function 是 worker 函数。

    <script>
    
        function highlight_code() {
            if (typeof (Worker) === undefined) return false;
            var workerFunction = new Blob(['(' + highlight_code_worker_function.toString() + ')()'], {type: "text/javascript"});
            var worker = new Worker(URL.createObjectURL(workerFunction));
            var codeBlocks = $('div.readme pre, div.readme code');
            worker.onmessage = function(event) {
                var data = JSON.parse(event.data);
                codeBlocks.eq(data.index).html(data.result).addClass('hljs');
            };
            worker.onerror = function() {
                // do nothing
            };
            codeBlocks.each(function(index) {
                worker.postMessage(JSON.stringify({index: index, code: $(this).text()}));
            });
            worker.postMessage(JSON.stringify({index: -1}));
        }
    
        function highlight_code_worker_function() {
            onmessage = function(event) {
                var data = JSON.parse(event.data);
                if (data.index === -1) {
                    close(); // close worker
                }
                importScripts(''https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.6.0/highlight.min.js'');
                self.hljs.configure({tabReplace:4});
                var result = self.hljs.highlightAuto(data.code);
                postMessage(JSON.stringify({result: result.value, index: data.index}));
            }
        }
    
        highlight_code();
    
        </script>
    

    使用多个网络工作者的示例

        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.6.0/styles/monokai_sublime.min.css">
    
        <script type="text/javascript">
    
          function highlight_code()
          {
            if (typeof (Worker) === undefined) return false;
            var workerFunction = new Blob(['(' + highlight_code_worker_function.toString() + ')()'], {type: "text/javascript"});
            var localWorkerURL = URL.createObjectURL(workerFunction);
            $('div.readme pre, div.readme code').each(function() {
              var code = $(this);
              var worker = new Worker(localWorkerURL);
              worker.onmessage = function(event) { code.html(event.data).addClass('hljs'); }
              worker.postMessage(code.text()); // start worker
            });
          }
    
          function highlight_code_worker_function()
          {
            onmessage = function(event) {
              importScripts('https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.6.0/highlight.min.js');
              self.hljs.configure({tabReplace:4});
              var result = self.hljs.highlightAuto(event.data);
              postMessage(result.value);
              close(); // close worker
            }
          }
    
          $(window).on('load', highlight_code);
    
        </script>
    

    【讨论】:

      【解决方案2】:

      我知道这是一个老问题,但我提出的答案可以帮助任何未来的访客。

      您可以在突出显示代码 sn-ps 之间提供一些延迟,这将提高性能,因为所有工作人员不会同时工作。我个人在我的一个网站中使用了这种方法,并且我得到了巨大的性能差异。

      script.js

      const allPres = [...document.querySelectorAll('pre')];
      for (let i = 0; i < allPres.length; i++) {
        setTimeout(() => {
          const block = allPres[i];
          var code = block.innerText,
          worker = new Worker('/worker.js');
       
          worker.onmessage = function (event) {
            var result = event.data;
            block.innerHTML = result;
            worker.terminate();
          };
       
          worker.postMessage(code);
        }, i * 500)  // putting just a delay of 500ms will make your website's performance nice than running all them together
      }
      

      worker.js

      importScripts('https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.3.1/highlight.min.js');
       
      self.onmessage = function (event) {
          var result = hljs.highlightAuto(event.data);
          postMessage(result.value);
      };
      

      分步实施here

      【讨论】:

        【解决方案3】:

        受到official documentation 的启发,我找到了一个可靠的解决方案(我猜)。

        事实上,我创建了 3 个脚本:

        1. worker_functions.js
        2. worker.js
        3. HTML 中的脚本

        仅仅是因为我需要动态突出显示代码。这是我的过程:

        1. 使用所需脚本加载页面,等待 DOM 加载后运行脚本。
        2. 从数据库中获取一些数据,在带有eye 图标的按钮内的data-my_attribute 中插入XML 内容。
        3. 点击这些按钮将瞄准模式打开(bootstrap 4)
        4. 在模态显示(表示之前它是显示),从按钮获取xml数据将其放入我的代码块中。
        5. 在模态显示时(表示它是显示),通过向工作人员发送消息来触发突出显示。

        编辑:步骤 5 不是必需的,因为在开始突出显示过程之前,jQuery(this).find('#codeblock').html(xml); 已正确完成。


        worker_functions.js

        let highlight_worker;
        
        /**
         * Start the worker in order to highlighting code block when triggering
         * @param worker_url - The javascript path of the worker
         */
        function start_worker(worker_url) {
            highlight_worker = new Worker(worker_url);
        }
        
        /**
         * Start an highlighting process through the worker previously started
         * @param querySelector - The DOM element on which the highlighted content should be returned
         */
        function start_highlighting(querySelector) {
            // Callback to insert the highlighted content to the expected element in DOM
            highlight_worker.onmessage = (event) => {
                querySelector.innerHTML = event.data;
            }
            
            // Post the content to be highlighted by the worker
            highlight_worker.postMessage(querySelector.textContent);
        }
        

        Worker.js

        我使用了 highlight.js 的 custom package,只包含我想要突出显示的语言。

        /**
         * When worker receives a message, import highlight.js then post back the resulting highlight
         * @param event - The content to be highlighted
         */
        onmessage = function (event) {
            importScripts('highlight.pack.js');
            var result = self.hljs.highlightAuto(event.data);
            postMessage(result.value);
        }
        

        HTML 中的脚本 - Django 模板

        我导入worker_functions 脚本,然后添加一个事件侦听器来触发窗口加载、启动工作程序并触发模态事件的突出显示。

        {% block scripts %}
            <script src="{% static 'device/js/highlight/worker_functions.js' %}"></script>
            <script type="text/javascript">
                window.addEventListener("load", function (event) {
                    start_worker("{% static 'device/js/highlight/worker.js' %}");
                    $('#mifContentModal').on('show.bs.modal', function (e) {
                        // let xml = '<p class="text-break">' + e.relatedTarget.dataset.mif_content + '</p>'; // Before decompress
                        let xml = '<xmp>' + e.relatedTarget.dataset.mif_content + '</xmp>';
                        console.log(jQuery(this).find('#codeblock'));
                        jQuery(this).find('#codeblock').html(xml);
                        start_highlighting(codeblock); // It can be done right after adding the code in DOM
                    })
                    //$('#mifContentModal').on('shown.bs.modal', function (e) {
                    //    let codeblock = document.getElementById("codeblock");
                    //    start_highlighting(codeblock);
                    //    // Then remove the xmp tag
                    //    codeblock.innerHTML = jQuery(this).find('xmp').html();
                    //})
                });
            </script>
        {% endblock %}
        

        然后我可以使用单个工作人员随时随地突出显示。

        【讨论】:

          猜你喜欢
          • 2022-12-10
          • 1970-01-01
          • 2011-11-24
          • 2015-09-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多