【问题标题】:Merging JS/CSS/HTML into single HTML将 JS/CSS/HTML 合并为单个 HTML
【发布时间】:2017-11-22 14:37:41
【问题描述】:

我有一个包含 2 个 HTML 文件、6 个 CSS 文件和 11 个 JS 文件的小型本地 Web 应用程序。

  1. 如果所有这些文件都是 (正确)复制粘贴到单个 HTML 文件中,例如将 JS 放入 <script> 标记在标题中,并将 CSS 放在 <style> 标记中?

  2. 有没有人知道一个工具可以 自动安全地合并 JS、CSS 和 HTML 的集合 文件转换成一个 HTML?

在网上搜索,我只发现可以一次合并或缩小一种类型的文件的工具,但不能创建合并的 HTML 文件(例如AIOM+HTMLcompressor. 我确实找到了这个名为 Inliner 的应用程序,但它似乎运行在 Node.js 上,我不熟悉并且目前不使用它。

简而言之,我正在寻找一种简单的独立工具,它可以读取 HTML 中的所有链接文件,并通过附加这些文件的内容来重写 HTML。如果这要求太多,那么只需确认手动完成工作会产生工作文件,或者在这样做时要考虑的任何提示。谢谢!

【问题讨论】:

标签: javascript html css


【解决方案1】:

1.

一般来说是的

2.

我不知道合并多个 html 文件,但
Here is a Python script (Github) 用于将 css/js/images 合并到一个 html 文件中。除了 Noam Nol 的回答..

  • ...它没有外部依赖项
  • ...它还可以正确处理非png图像。

用法: python3 htmlmerger yourfile.html

来自 github 的代码:htmlmerger.py

以下是 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()

【讨论】:

    【解决方案2】:

    我为它写了一个简单的python脚本。

    这是我的树:

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

    我运行脚本:

    cd root-folder
    python build_dist.py
    

    并且在 dist 文件夹中创建了一个 oneindex.html 文件。
    此文件包含 index.html 中使用 linkscript 标记指定的文件中的所有 js 和 css。
    您可以在任何地方使用此文件。

    注意:

    1. HTML 文件必须是根文件夹中的“index.html”。
    2. 它仅适用于单个 HTML 文件。我不知道你想对多个 HTML 文件做什么。

    build_dist.py 代码:

    # 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.
    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))
    

    【讨论】:

      【解决方案3】:

      您可以考虑使用webpack。一开始并不容易理解,但这是一个很好的 tutorial 开头。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-03-27
        • 2011-05-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-20
        相关资源
        最近更新 更多