0

Following command gives me the output I want:

$ sed '/^<template.*>/,/<\/template>/!d;//d' src/components/**/*.vue | html2jade

in that it processes each template containing html into it's pug equivalent.

Would it be possible now to somehow replace the originally found html in all those files, with this now processed output? There is also some other content outside template tags, which should stay as it is, namely some script and style tags.

  • i.e. pick the part between <template> and </template>, run it through a filter program, and then stick the result back in where the template was? – ilkkachu Dec 7 '17 at 21:44
  • @ilkkachu Yes, exactly. – branquito Dec 7 '17 at 21:47
1

I believe you can't do this with sed. It should be possible with awk but hard. python3 seems more appropriate.

import re
import subprocess
from io import StringIO
from traceback import format_exception_only

PROCESS_COMMAND = ("html2jade",)
TEMPLATE_OPEN_REGEX = re.compile(r"^<template.*>$")
TEMPLATE_CLOSE_REGEX = re.compile(r"^</template>$")

def replace_templates(file_path) :
    out_buffer = StringIO()
    template_buffer = StringIO()

    with open(file_path, "r") as file :
        lines_gen = enumerate(file, 1)
        for (lineno, line) in lines_gen :
            out_buffer.write(line)

            if (TEMPLATE_OPEN_REGEX.match(line)) :
                for (lineno, line) in lines_gen :
                    if (TEMPLATE_OPEN_REGEX.match(line)) :
                        raise ValueError("nested opening tag on line {:d}".format(lineno))
                    elif (TEMPLATE_CLOSE_REGEX.match(line)) :
                        break

                    template_buffer.write(line)
                else :
                    raise ValueError("tag never closed")

                proc = subprocess.run(
                    PROCESS_COMMAND,
                    input=template_buffer.getvalue(),
                    stdout=subprocess.PIPE,
                    stderr=subprocess.DEVNULL,
                    encoding="UTF-8",
                    check=True)

                out_buffer.write(proc.stdout)
                out_buffer.write(line)

                template_buffer.seek(0)
                template_buffer.truncate()
            elif (TEMPLATE_CLOSE_REGEX.match(line)) :
                raise ValueError("closing tag encountered on line {:d}, before opening tag".format(lineno))

    with open(file_path, "w") as file :
        file.write(out_buffer.getvalue())

def main(args) :
    for a in args :
        try :
            replace_templates(a)
        except Exception as ex :
            print("generation failed for file {!r} ({:s})".format(
                 a,
                 format_exception_only(type(ex), ex)[-1].rstrip()))
        else :
            print("file {!r} written".format(a))

if (__name__ == "__main__") :
    from sys import argv

    main(argv[1:])
  • You seems to ignore any template code on the line of the tag, so my code do not handle this and do a full-line match.
  • ValueError is raised if opening and closing template tag are not correctly ordered.
  • FileNotFoundError is raised if the .vue file or the sub-process command is not found.
  • subprocess.CalledProcessError is raised if the sub-process do not return 0.
  • UnicodeDecodeError is raised if the sub-process output non UTF-8 chars.
  • The file is not touched if an error occurs.
  • The full file output is buffered to RAM.
  • Thanks for this solution, but this goes way beyond the complexity I would like to have for this kind of task. I know how to write a shell script that would do this, but I was wondering if there might be a solution using a kind of one-liner – branquito Dec 8 '17 at 11:36
  • $ ./template.py src/components/**/*.vue is a oneliner :P . I do not know a tool doing this, this is not trivial. My rule is "if it is not easy with awk, write a script". – user285259 Dec 8 '17 at 12:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.