htmldeps.py

Expand CSS and javascript dependency links in HTML

This module supports clean separation of markup, presentation, and behavior in HTML. It looks for special dependency comments atop CSS and javascript files and within <style> or <script> tags of the form:

/* :depends module1, module2 */

The comma separated list following the :depends string indicates CSS or javascript modules that need to be linked into the markup just before each <style> or <script> tag enclosing a dependency comment.

After processing, the HTML will contain all the required links to CSS or javascript modules listed in the markup, along with any of their dependencies.

When a CSS or javascript module file requires other modules to be loaded first, it should provide a dependency comment toward the beginning the source code. CSS modules may only depend upon other CSS modules, and javascript modules may depend only on other javascript modules. There may only be one dependency comment in any module file, and the comment should be somewhere in the first five lines of the source code.

Module names correspond to filenames without an extension, e.g. <style>/*:depends site*/</style> depends on a file named site.css. Module names must only consist of the ASCII characters matching the regular expression [a-zA-Z0-9_-].

Moudle files are located by looking in the current working directory and then via whatever paths have been optionally specified in the $HTMLDEPS environment variable (formatted just like the ubiquitous $PATH variable). In addition, the list of paths to search may also be adjusted via the config object.

Within the original HTML, the :depends string must only appear in comments inside of <script> or <style> tags. When a tag contains a dependency comment, is must not contain any other CSS or javascript expressions: the comment and its enclosing tag will be removed from the HTML output and replaced with links to external files. The same module will not be included more than once in the HTML output.

Attributes in the original <script> or <style> tags will be written into the transformed HTML. For example:

<style media="print">/* :depends print */</style>

Might render something like this:

<link rel="stylesheet" href="print.css" media="print">

(For XHTML, <link rel="stylesheet" href="print.css" media="print" />)

All HTML, CSS, and javascript files must be encoded in utf-8.

This module may also be invoked directly from the command line by passing it to the python interpreter. Run the script with --help to see the available command flags:

python htmldeps.py --help

requirements

Python 3 or later

usage

import htmldeps
htmldeps.write('test.html')

contents

config

This object holds configuration data to properly process HTML passed into link(). It has the following attributes:

config.search_path

A list of directories which will be searched to find 'css' and 'js' modules.

These lists are structured and used much like sys.path. By default, they are empty or set to the contents of the $HTMLDEPS environment variable split into separate items according to os.pathsep.

Pathnames may be added or removed from the list as needed. The value of os.getcwd() will be searched before the directories named in the list.

config.link_prefixes

A dict with two keys, 'css' and 'js', each indexing a str (default: '') indicating an optional URL value to prepend to any generated links of the given filetype. For example, if:

link_prefixes['js'] == '/js/'

Then HTML input containing:

<script>/* :depends site */</script>

Will be converted to something like:

<script src="/js/site.js"></script>

Be sure to include a trailing '/' in any directory prefixes.

config.flatten

Set to False by default, but if True, any chain of generated links should be flattened into one bearing the name of the last link in the sequence. For example:

<script>/* depends a, b */</script>

Would normally be transformed into:

<script src="a.js"></script><script src="b.js"></script>

But if flatten were True the output would just be:

<script src="b.js"></script>

The content of "b.js" would be that of module a concatenated with b. Use this option to reduce http requests and boost the performance of your page.

Inserts the appropriate CSS and javascript links into an HTML string. The html parameter may be a str or a file handle in 'rt' mode.

Returns a two-item tuple (html, links). The first item is a new HTML string containing links to all the CSS and javascript modules listed in dependency comments. The second item is a dict which maps the URL of each CSS or javascript link to its corresponding text content.

It's up to the caller to write the text content into the appropriate file locations on the web server. For example, if links were:

{ '/css/site.css' : 'body {color:red;}' }

Then the caller would typically write a file named site.css in the css directory (under the web server’s document root) containing the 'body {color:red;}' string.

write(*html_filenames, output_directory='build', verbose=False)

Convenience function. Iterates over html_filenames and applies link() to the HTML in each file. All HTML, CSS, and javascript output will be written into output_directory. Typically, it’s best to set the working directory to wherever the CSS or javascript files required by the HTML reside (or set the $HTMLDEPS environment variable appropriately).

If verbose, describe which files are written via standard error.

If this function doesn’t give you the file output you want, it’s better to just call link() directly.