How to use Observable syntax highlight inside P5 sketch within Framework

Hi Everyone,

While converting my p5 sketch into Framework, the syntax highlight I used inside p5 sketch from prismjs is messing up with beautiful syntax highlighting of Observable Framework, as seen in the image below, and the link to the demo is here. What should I do if I want to use Observable code syntax highlighting for my P5 sketch when I scroll my p5 sketch (when scrolling, a sequence of code blocks will be displaying, this is a feature of my sketch)

Thank you so much!

The code which I think are responsible for the mess is the following:


    function addCodeDivP5(code, id) {
      // Create a new div element
      let newDiv = p.createDiv();
      newDiv.id(id);
      newDiv.style('opacity', '0.0');

      newDiv.html(`<pre><code class="language-javascript">${escapeHtml(code)}</code></pre>`);

      // Prism.highlightAll();
      let codeElement = newDiv.elt.getElementsByTagName('code')[0];

      // Highlight only the code within the new div
      Prism.highlightElement(codeElement);
    }

    function escapeHtml(unsafe) {
      return unsafe
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/"/g, "&quot;")
        .replace(/'/g, "&#039;");
    }
const loadPrismCSS = (id) => {
  const link = document.createElement('link');
  link.rel = 'stylesheet';
  link.href = 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.24.1/themes/prism.min.css';
  document.getElementById(id).appendChild(link);
};

loadPrismCSS('mySketch');

import Prism from 'https://cdn.skypack.dev/prismjs';

Can you publish the project? It looks like it’s currently private.

1 Like

Thanks, I didn’t know it was still in private mode. Now it is shared, here is the link
https://shendusuipian.observablehq.cloud/p5inframework/random00

It’s hard to tell since I don’t know prism, but mixes of different programs (here highlight.js and prism, and their stylesheets) targeting the same elements are never easy to fix. Maybe you need a way to disable highlight.js?

To avoid having two styles, can you try to create your own style.css?

Similarly I wonder if it’s really necessary to wrap the <pre class="language-javascript">generated by framework with a <code class="language-javascript">.

Thanks for your reply! However, I have no experience of working with css, and I only know a little p5.js.

My goal is to get rid of Prism and only use observable’s syntax highlighting for the code display in p5 sketch inside Framework. Could there be a easier solution?

Hi

I have solved the problem I posted above, but with one problem which prevent me from working with Framework offline.

I have made my original question (as described above) working by removing prism.js and only using highlight.js by simply importing like below

import hljs from 'https://cdn.skypack.dev/highlight.js';

As you can see, it won’t work if I go offline, unless I can use the highlight.js already inside Node_modules folder. However, when I try to import explicitly highlight.js. I tried the following but all returned the similar error of fetch failed.

import hljs from "npm: highlightjs";
import hljs from "npm: highlight.js";
import hljs from "npm: highlight";

All these three attempts failed with similar messages like below inside the terminal

GET /noise01
npm:highlightjs → GET /noise01
TypeError: fetch failed
    at node:internal/deps/undici/undici:12443:11
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async file:///Users/Natsume/Documents/Processing/my_projects/kennynoc/node_modules/@observablehq/framework/dist/npm.js:193:22 {
  cause: ConnectTimeoutError: Connect Timeout Error
      at onConnectTimeout (node:internal/deps/undici/undici:7595:28)
      at node:internal/deps/undici/undici:7551:50
      at Immediate._onImmediate (node:internal/deps/undici/undici:7583:13)
      at process.processImmediate (node:internal/timers:478:21) {
    code: 'UND_ERR_CONNECT_TIMEOUT'
  }
}
TypeError: fetch failed
    at node:internal/deps/undici/undici:12443:11
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async file:///Users/Natsume/Documents/Processing/my_projects/kennynoc/node_modules/@observablehq/framework/dist/npm.js:193:22 {
  cause: ConnectTimeoutError: Connect Timeout Error
      at onConnectTimeout (node:internal/deps/undici/undici:7595:28)
      at node:internal/deps/undici/undici:7551:50
      at Immediate._onImmediate (node:internal/deps/undici/undici:7583:13)
      at process.processImmediate (node:internal/timers:478:21) {
    code: 'UND_ERR_CONNECT_TIMEOUT'
  }
}

Why does Framework fetch highlight.js online? why it always fail? How can I import it explicitly and be able to use it when offline.

Ok, I got it. Finally one of the import worked, as the fetch was successful, and all problem is considered solved.
Thanks!

1 Like

Bravo! Would you mind sharing your solution?

1 Like

Of course, if you think it is worth your time, I would love to share with you.

Previously I was using prism.js and since Framework is already using highlight.js to create beautiful syntax highlight, why should I use prism.js. So, I decide to switch to highlight.js. At first, I was using the online hosted version of highlight.js and it just works, then since the network is not stable in China, so I think it would be better to use highlight.js offline directly from Framework itself, and that’s why I choose to do import hljs from "npm: highlightjs". Because of the unstable networks, often the fetch fails, but eventually it did fetch after a while. So, it just works now. Below are the codes I used involving highlight.js:

    function addCodeDivP5(code, id) {
      // Create a new div element
      let newDiv = p.createDiv();
      newDiv.id(id);
      newDiv.style('opacity', '0.0');

      newDiv.html(`<pre><code class="language-javascript">${escapeHtml(code)}</code></pre>`);

      // Prism.highlightAll();
      let codeElement = newDiv.elt.getElementsByTagName('code')[0];

      // Highlight only the code within the new div
      // Prism.highlightElement(codeElement);
      hljs.highlightBlock(codeElement);
    }

    function escapeHtml(unsafe) {
      return unsafe
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/"/g, "&quot;")
        .replace(/'/g, "&#039;");
    }
// Import the p5 library from npm
import P5 from "npm:p5";
// import Prism from 'https://cdn.skypack.dev/prismjs';
import hljs from 'npm:highlightjs';
// import hljs from 'https://cdn.skypack.dev/highlight.js';

You can go to Code in Steps and click open the source code details and scroll up and down on the p5 canvas area to see my added syntax highlight (I have to admit that it is not perfect as it is not highlighting the syntax for p5, but the style is consistent with observable), and then click the import and helper details button to see the original observable syntax highlighting.