最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Merging JSCSSHTML into single HTML - Stack Overflow

programmeradmin5浏览0评论

I have a small local web-application of 2 HTML files, 6 CSS files and 11 JS files.

  1. Would the web-application still work if all of these files were (properly) copy-pasted in a single HTML file, e.g. putting the JS in <script> tags in the header, and putting the CSS in <style> tags?

  2. Does anyone know of a tool that could automatically and safely merge a collection of JS, CSS and HTML files into a single HTML?

Searching online, I only found tools that can bine or minify files of one type at a time, but not create the merged HTML file (e.g. AIOM+, HTMLpressor. I did find this application called Inliner, but it seems it runs on Node.js, with which I'm not familiar and don't currently use.

In short, I'm looking for either a simple standalone tool that could read all the linked files in the HTML, and rewrite the HTML by appending those files' content. If that's asking too much, then just a confirmation that manually doing the job would result in a working file, or any tips to think about when doing so. Thanks!

I have a small local web-application of 2 HTML files, 6 CSS files and 11 JS files.

  1. Would the web-application still work if all of these files were (properly) copy-pasted in a single HTML file, e.g. putting the JS in <script> tags in the header, and putting the CSS in <style> tags?

  2. Does anyone know of a tool that could automatically and safely merge a collection of JS, CSS and HTML files into a single HTML?

Searching online, I only found tools that can bine or minify files of one type at a time, but not create the merged HTML file (e.g. AIOM+, HTMLpressor. I did find this application called Inliner, but it seems it runs on Node.js, with which I'm not familiar and don't currently use.

In short, I'm looking for either a simple standalone tool that could read all the linked files in the HTML, and rewrite the HTML by appending those files' content. If that's asking too much, then just a confirmation that manually doing the job would result in a working file, or any tips to think about when doing so. Thanks!

Share Improve this question asked Jun 20, 2017 at 7:25 sc28sc28 1,2136 gold badges28 silver badges52 bronze badges 5
  • 2 It is possible, you put the <style> in the <head> and the <script> at the end (but still inside the <body>) – marcellothearcane Commented Jun 20, 2017 at 7:30
  • 1 Possibly of interest: stackoverflow./questions/3135929/…, stackoverflow./questions/28195447/…, stackoverflow./questions/7454050/… – marcellothearcane Commented Jun 20, 2017 at 7:31
  • 1 The answer to your first question is YES. As for your second question, asking for tools is against SO policy. – Racil Hilan Commented Jun 20, 2017 at 7:35
  • Thanks for these ments, some interesting stuff in the linked questions, but not quite what I need either. I'll attempt the manual copy paste following these remendations and see if it works out. – sc28 Commented Jun 20, 2017 at 8:08
  • @sc28 did you find a solution? – mzuba Commented Nov 25, 2021 at 11:24
Add a ment  | 

3 Answers 3

Reset to default 7

I wrote a simple python script for it.

This is my tree:

root-folder
├── index.html
├── build_dist.py
├── js
│   └── somescript.js
├── css
│   ├── styles1.css
│   └── styles2.css
├── images
│   └── img1.png
└── dist

I run the script:

cd root-folder
python build_dist.py

And a standalone oneindex.html file is created in the dist folder.
This file contains all the js and css from the files specified with link and script tags in index.html.
It also contains all images specified with img tags (converted to base64 text).

You can use this file anywhere.

Note:

  1. The HTML file must be "index.html" in the root folder.
  2. It only works for a single HTML file. I don't know what you want to do with multiple HTML files.

build_dist.py code:

# build_dist.py

from bs4 import BeautifulSoup
from pathlib import Path
import base64

original_html_text = Path('index.html').read_text(encoding="utf-8")
soup = BeautifulSoup(original_html_text)

# Find link tags. example: <link rel="stylesheet" href="css/somestyle.css">
for tag in soup.find_all('link', href=True):
    if tag.has_attr('href'):
        file_text = Path(tag['href']).read_text(encoding="utf-8")

        # remove the tag from soup
        tag.extract()

        # insert style element
        new_style = soup.new_tag('style')
        new_style.string = file_text
        soup.html.head.append(new_style)


# Find script tags. example: <script src="js/somescript.js"></script>
for tag in soup.find_all('script', src=True):
    if tag.has_attr('src'):
        file_text = Path(tag['src']).read_text()

        # remove the tag from soup
        tag.extract()

        # insert script element
        new_script = soup.new_tag('script')
        new_script.string = file_text
        soup.html.body.append(new_script)

# Find image tags. example: <img src="images/img1.png">
for tag in soup.find_all('img', src=True):
    if tag.has_attr('src'):
        file_content = Path(tag['src']).read_bytes()

        # replace filename with base64 of the content of the file
        base64_file_content = base64.b64encode(file_content)
        tag['src'] = "data:image/png;base64, {}".format(base64_file_content.decode('ascii'))

# Save onefile
with open("dist/oneindex.html", "w", encoding="utf-8") as outfile:
    outfile.write(str(soup))

You could consider using webpack. It is not easy to understand at first but this is a good tutorial to start with.

1.

Generally, yes

2.

I don't know of merging multiple html files, but
Here is a Python script (Github) for merging css/js/images into one single html file. In addition to Noam Nol's answer..

  • ... it does not have external dependencies
  • ... it will also handle non-png images properly.

Usage: python3 htmlmerger yourfile.html

Code from github: htmlmerger.py

Below is the content from the file on Github.

from html.parser import HTMLParser
import os
import sys
import base64


gHelp = """
Merge JS/CSS/images/HTML into one single file
Version: 1.0

Usage:
  htmlmerger inputfile [optional: outputfile]

"""


def getFileContent (strFilepath):
  content = ""
  with open (strFilepath, "r") as file:
    content = file.read ()
  return content



def getFileContentBytes (strFilepath):
  content = b""
  with open (strFilepath, "rb") as file:
    content = file.read ()
  return content


class HtmlMerger(HTMLParser):
  """
    Call "run(htmlContent, basedir)"  to merge
    script/css/images referenced withing htmlContent
    into one single html file.
  """
  def __init__(self):
    super().__init__()
    self._result = ""
    self._additionalData = ""
    self._baseDir = ""
    self.messages = []



  def _addMessage_fileNotFound(self, file_asInHtmlFile, file_searchpath):
    self.messages.append ("Error: Line " + str (self.getpos ()[0]) +
                        ": Could not find file `" + str (file_asInHtmlFile) +
                        "`; searched in `" + str (file_searchpath) + "`." )



  def _getAttribute (self, attributes, attributeName):
    """Return attribute value or `None`, if not existend"""
    for attr in attributes:
      key = attr[0]
      if (key == attributeName):
        return attr[1]
    return None


  def _getFullFilepath (self, relPath):
    return os.path.join (self._baseDir, relPath)


  def handle_starttag(self, tag, attrs):

    # Style references are within `link` tags. So we have to
    #  convert the whole tag
    if (tag == "link"):
      href = self._getAttribute (attrs, "href")
      if (href):
        hrefFullPath = self._getFullFilepath (href)
        if (not os.path.isfile (hrefFullPath)):
          self._addMessage_fileNotFound (href, hrefFullPath)
          return
        styleContent = getFileContent (hrefFullPath)
        self._result += "<style>" + styleContent + "</style>"
        return

    self._result += "<" + tag + " "

    for attr in attrs:
      key = attr[0]
      value = attr[1]

      # main work: read source content and add it to the file
      if (tag == "script" and key == "src"):
        #self._result += "type='text/javascript'"
        strReferencedFile = self._getFullFilepath (value)
        if (not os.path.isfile (strReferencedFile)):
          self._addMessage_fileNotFound (value, strReferencedFile)
          continue
        referencedContent = getFileContent (strReferencedFile)
        self._additionalData += referencedContent

        # do not process this key
        continue

      if (tag == "img" and key == "src"):
        imgPathRel = value
        imgPathFull = self._getFullFilepath (imgPathRel)
        if (not os.path.isfile (imgPathFull)):
          self._addMessage_fileNotFound (imgPathRel, imgPathFull)
          continue

        imageExtension = os.path.splitext (imgPathRel)[1][1:]
        imageFormat = imageExtension

        # convert image data into browser-undertandable src value
        image_bytes = getFileContentBytes (imgPathFull)
        image_base64 = base64.b64encode (image_bytes)
        src_content = "data:image/{};base64, {}".format(imageFormat,image_base64.decode('ascii'))
        self._result += "src='" + src_content + "'"

        continue



      # choose the right quotes
      if ('"' in value):
        self._result += key + "='" + value + "' "
      else:
        self._result += key + '="' + value + '" '

    self._result +=  ">"

  def _writeAndResetAdditionalData(self):
    self._result += self._additionalData
    self._additionalData = ""

  def handle_endtag(self, tag):
    self._writeAndResetAdditionalData ()
    self._result += "</" + tag + ">"


  def handle_data(self, data):
    self._result += data

  def run(self, content, basedir):
    self._baseDir = basedir
    self.feed (content)
    return self._result



def merge(strInfile, strOutfile):

  if (not os.path.isfile (strInfile)):
    print ("FATAL ERROR: file `" + strInfile + "` could not be accessed.")
    return

  baseDir = os.path.split (os.path.abspath (strInfile))[0]

  #read file
  content = getFileContent (strInfile)

  parser = HtmlMerger()
  content_changed = parser.run (content, baseDir)

  # log errors
  if (len (parser.messages) > 0):
    print ("Problems occured")
    for msg in parser.messages:
      print ("  " + msg)
    print ("")

  # debug:
  if (False):
    print (content_changed)
    exit ()


  # write result
  with open (strOutfile, "w") as file:
    file.write (content_changed)



def main():
  args = sys.argv[1:] # cut away pythonfile
  if (len (args) < 1):
    print (gHelp)
    exit()

  inputFile = args[0]

  # get output file name
  outputFile = ""
  if (True):
    outputFile = os.path.splitext (inputFile)[0] + "_merged.html"

    if (len (args) > 1):
      outputFile = args[1]

    if (os.path.isfile (outputFile)):
      print ("FATAL ERROR: Output file " + outputFile + " does already exist")
      exit ()

  # run the actual merge
  merge (inputFile, outputFile)


main()
发布评论

评论列表(0)

  1. 暂无评论