MagTun
MagTun

Reputation: 6185

html + js: retrieve the line number in the file where a div is created

I have a html file (the path is C:/Users/user/file.html) composed of several blocks. Next to each title of a block I would like to have a link that looks like this vscode://file/C:/Users/user/file.html:150:45

This link opens my file in VsCode to the line 150 and the column 45.

Because the script will change a lot, I do not want to hard code the link as it will require too much work. So I would like to create this vscode link dynamically with a js script. I got everything sorted out, except the part that should retrieve the correct line and column number of the "selected" title in the file.

You can see what I mean in the snippet below: for instance, if in my html file, the line/column where Title A is "hardcoded" is 80/20, then the js script should generate the link on "edit this block" as vscode://file/C:/Users/user/file.html:80:20.

Also, I will create some content dynamically with another piece of js script so the line/column number in the link should reflect the "hardcoded" and not the one in the browser.

(I really care about the line, but not so much about the column number, I will be satisfied if it's always set to 1).

<!DOCTYPE html>
<body>

    <div>
        <a-title>Title A</a-title>
       <p>Long text for A</p> 
    </div>

    <div>
        <a-title>Title B</a-title>
       <p>Long text for B</p> 
    </div>


    <div>
        <a-title>Title C</a-title>
       <p>Long text for C</p> 
    </div>

    <script>
        //  get all existing div in document
        var elements = document.getElementsByTagName("a-title");

        for (var i = 0; i < elements.length; i++) {
            var atitle = elements[i];
            var atitle_innerHtml = atitle.innerHTML;
            atitle.innerHTML = atitle_innerHtml +" <a href=\"vscode://file/C:/Users/user/file.html:150:45\">edit this block</a>";
        };
    </script>
   
</body>

Upvotes: 1

Views: 848

Answers (3)

Mark
Mark

Reputation: 180945

Here is an alternative approach which is fairly simple:

const jsdom = require("jsdom");
const { JSDOM } = jsdom;

const options = { includeNodeLocations: true };

// can use a string, url or file here
JSDOM.fromFile("./jsdomTest.html", options).then(dom => {

  const aTitles = dom.window.document.getElementsByTagName("a-title");

  for (let element of aTitles) {

    // console.log(dom.nodeLocation(element).line);
    // console.log(dom.nodeLocation(element).endTag.col);

    element.innerHTML += ` <a href=\"vscode://file/C:/Users/user/file.html:${dom.nodeLocation(element).line}:${dom.nodeLocation(element).endTag.col}\">edit this block</a>`;    
  };

  console.log(dom.window.document.documentElement.innerHTML);
  // write to a file
});

The jsdom package will allow you to easily query for elements. Its option includeNodeLocations will save the original locations (line numbers and columns and more) of any element.

The code above will produce this console.log:

<head></head><body>

    <div>
        <a-title>Title A <a href="vscode://file/C:/Users/user/file.html:5:25">edit this block</a></a-title> 
       <p>Long text for A</p> 
    </div>

    <div>
        <a-title>Title B <a href="vscode://file/C:/Users/user/file.html:10:25">edit this block</a></a-title>
       <p>Long text for B</p> 
    </div>

    <div>
        <a-title>Title C <a href="vscode://file/C:/Users/user/file.html:16:25">edit this block</a></a-title>
       <p>Long text for C</p> 
    </div>

Upvotes: 2

MagTun
MagTun

Reputation: 6185

I ended up going the way @arieljuod proposed but because I am not using my file on a server I didn't go with PHP.

I was using AHK anyway to start my html file with a shortcut so it didn't take much to start instead a Python script that create/replace a data-line attribute and start the html file.

import re  #regex to replace number line 
import webbrowser
matchtitle="<a-title"
data_line=" data-line="
all_lines_as_list=[]
filename=r"C:\Users\Me\memo python.html"

with open(filename, "r", encoding="utf8") as myFile_read:
    for num, line in enumerate(myFile_read, 0):
            # print (num, line)
            if matchtitle in line or matchpre in line:
                # print(line)
                if data_line in line:
                    line = re.sub(r"\d+", str(num+1), line)
                else:
                    line=line.replace(matchtitle, matchtitle+data_line+f"\"{num+1}\" ")
            all_lines_as_list.append(line)
    all_lines_joined="".join(all_lines_as_list)
    # print(all_lines_joined)
    with open(filename, "w", encoding="utf8") as myFile_write:
        myFile_write.write(all_lines_joined)


new=2 # open html file in a new browser file
webbrowser.open(filename,new=new)

Upvotes: 0

Kizer
Kizer

Reputation: 1666

You can get the document source code with document.documentElement.innerHTML; You can then use text search to find the element of interest, and the line number.

However, as there is no way I know to get the parts that are outside the tag, including the doctype. You will have make assumptions there.

Upvotes: -2

Related Questions