javascripthtmlcsspre

How to set numbers to PRE with JS/CSS


Well, I want to create an HTML template to create this: enter image description here

But this are my results:

enter image description here

or this:

enter image description here

In some way a need to combine this to results. Here is my code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Pre Test</title>
    <link rel="stylesheet" href="css/style.css">

    <link rel="stylesheet" href="js/styles/monokai-sublime.min.css" />
    <script src="js/highlight.min.js"></script>
    <script>
        hljs.highlightAll();
    </script>
</head>
<body>

<div>
    <div class="circleR"></div>
    <div class="circleY"></div>
    <div class="circleG"></div>
</div>

<pre><code class="language-python">def solve():
    global grid
    for y in range(9):
        for x in range(9):
            if grid[y][x] == 0:
                for n in range(1,10):
                    if possible(y,x,n):
                        grid[y][x] = n
                        solve()
                        grid[y][x] = 0
                return
    print(np.matrix(grid))
    input("More?")
</code></pre>

<script type="text/javascript">
    function addLineClass (pre) {
        var lines = pre.innerText.split("\n"); // can use innerHTML also
        while(pre.childNodes.length > 0) {
            pre.removeChild(pre.childNodes[0]);
        }
        for(var i = 0; i < lines.length; i++) {
            var span = document.createElement("span");
            span.className = "line";
            span.innerText = lines[i]; // can use innerHTML also
            pre.appendChild(span);
            pre.appendChild(document.createTextNode("\n"));
        }
    }
    window.addEventListener("load", function () {
        var pres = document.getElementsByTagName("pre");
        for (var i = 0; i < pres.length; i++) {
            addLineClass(pres[i]);
        }
    }, false);
</script>
</body>
</html>

The style.css file (so messy, sorry, I'm getting crazy)

  pre {
    border-radius: 5px;
    width: 550px;
    border: 2px solid black;
    padding: 20px 0px 0px 10px;
    background-color: #23241f;
    color: aliceblue;
    font-size: large;  
    counter-reset: linecounter;
    /*
    an-old-hope.min.css
    #1c1d21;

    monokai-sublime.min.css
    #23241f
    */
  }
  
  pre :before {
    /*counter-increment: line;*/
    /*content: counter(line);*/
    /*border-right: 1px solid #ddd;*/
    margin-right: .2em;
    color: #888 /*number color*/
  }

  pre span.line {
    counter-increment: linecounter;
    /*line-height: 16px;*/
}

pre span.line::before {
    padding: 0 .5em;
    display: inline-block;
    content: counter(linecounter);
    width: 30px;
    border-right: none;
    text-align: right;
    /*font-size: 16px;*/
    /*line-height: 16px;*/
    /*padding-right: 3px;*/
    /*display: inline-block;*/
    /*color: red;*/
}

  .circleR {
    background: #ff534a;
    border-radius: 100%;
    height: 10px;
    width: 10px;
    position: absolute;
    top: 20px;
    left: 20px;
  }
  
  .circleY {
    background: #ffea14;
    border-radius: 100%;
    height: 10px;
    width: 10px;
    position: absolute;
    top: 20px;
    left: 35px;
  }
  
  .circleG {
    background: #4bd13d;
    border-radius: 100%;
    height: 10px;
    width: 10px;
    position: absolute;
    top: 20px;
    left: 50px;
  }

Questions and Explanations:

I use the code from highlight.js, simply awesome. Here

<link rel="stylesheet" href="js/styles/monokai-sublime.min.css" />
<script src="js/highlight.min.js"></script>
<script>
    hljs.highlightAll();
</script>

With this lines into <head></head> everything in the tags <pre><code class="language-python">...</code></pre> will get the highlight style in your page, as a IDE, no extra tags need it. And if you want to check it just remove the last script at the end of body.

So I want to put numbers into my style, but when "run" the code in the script at the end of body removes the IDE style, because functions like this:

js/highlight.min.js comes throw every line and word inside <pre><code class="language-python">...</code></pre> and check what kind of style need and set something like this <span class="hljs-keyword">def</span> to take the style from js/styles/monokai-sublime.min.css, and the class for every word will change. (This is the second image)

But when <script type="text/javascript"> comes, remove everything and set this <span class="line">def solve():</span> because is in the same line inside pre. It is great because, set the numbers for every line (as you can see in the third image), but loosing the highlighting.

There is a way that I can get something like the first image, the IDE style and the numbers?


Solution

  • Method 1: Using after:highlight callback

    pre {
      width: 550px;
      font-size: large;
      border-radius: 5px;
      background-color: #23241f;
      counter-reset: linecounter;
    }
    
    pre .line-num {
      min-width: 3ch;
      display: inline-block;
    }
    
    pre .line-num::before {
      counter-increment: linecounter;
      content: counter(linecounter);
    }
    
    .circleR {
      background: #ff534a;
      border-radius: 100%;
      height: 10px;
      width: 10px;
      position: absolute;
      top: 20px;
      left: 20px;
    }
    
    .circleY {
      background: #ffea14;
      border-radius: 100%;
      height: 10px;
      width: 10px;
      position: absolute;
      top: 20px;
      left: 35px;
    }
    
    .circleG {
      background: #4bd13d;
      border-radius: 100%;
      height: 10px;
      width: 10px;
      position: absolute;
      top: 20px;
      left: 50px;
    }
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Pre Test</title>
      <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.0.1/styles/monokai-sublime.min.css">
      <script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.0.1/highlight.min.js"></script>
    
      <script>
        hljs.addPlugin({
          'after:highlight': (result) => {
            result.value = result.value.replace(/^/gm, '<span class="line-num"></span>')
          }
        });
    
        hljs.highlightAll();
      </script>
    </head>
    
    <body>
    
      <div>
        <div class="circleR"></div>
        <div class="circleY"></div>
        <div class="circleG"></div>
      </div>
    
      <pre>
      <code class="language-python">def solve():
        global grid
        for y in range(9):
            for x in range(9):
                if grid[y][x] == 0:
                    for n in range(1,10):
                        if possible(y,x,n):
                            grid[y][x] = n
                            solve()
                            grid[y][x] = 0
                    return
        print(np.matrix(grid))
        input("More?")</code>
    </pre>
    
    </body>
    
    </html>

    Method 2: Using highlightjs-line-numbers.min.js plugin

    pre {
      border-radius: 5px;
      width: 550px;
      background-color: #23241f;
      color: aliceblue;
      font-size: large;
    }
    
    .circleR {
      background: #ff534a;
      border-radius: 100%;
      height: 10px;
      width: 10px;
      position: absolute;
      top: 20px;
      left: 20px;
    }
    
    .circleY {
      background: #ffea14;
      border-radius: 100%;
      height: 10px;
      width: 10px;
      position: absolute;
      top: 20px;
      left: 35px;
    }
    
    .circleG {
      background: #4bd13d;
      border-radius: 100%;
      height: 10px;
      width: 10px;
      position: absolute;
      top: 20px;
      left: 50px;
    }
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Pre Test</title>
      <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.0.1/styles/monokai-sublime.min.css">
      <script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.0.1/highlight.min.js"></script>
      <script src="https://cdn.jsdelivr.net/npm/highlightjs-line-numbers.js@2.6.0/dist/highlightjs-line-numbers.min.js"></script>
    
      <script>
        hljs.highlightAll();
        hljs.initLineNumbersOnLoad();
      </script>
    </head>
    
    <body>
    
      <div>
        <div class="circleR"></div>
        <div class="circleY"></div>
        <div class="circleG"></div>
      </div>
    
      <pre>
      <code class="language-python">def solve():
        global grid
        for y in range(9):
            for x in range(9):
                if grid[y][x] == 0:
                    for n in range(1,10):
                        if possible(y,x,n):
                            grid[y][x] = n
                            solve()
                            grid[y][x] = 0
                    return
        print(np.matrix(grid))
        input("More?")</code>
    </pre>
    
    </body>
    
    </html>

    References

    https://highlightjs.readthedocs.io/en/latest/line-numbers.html

    https://highlightjs.readthedocs.io/en/latest/plugin-api.html#after-highlight-result

    https://github.com/wcoder/highlightjs-line-numbers.js