├── tests
├── project
│ ├── content
│ │ ├── contents.lr
│ │ └── filter.html
│ │ │ └── contents.lr
│ ├── packages
│ │ └── lektor-minify
│ ├── models
│ │ └── page.ini
│ ├── assets
│ │ └── static
│ │ │ ├── style.css
│ │ │ └── script.js
│ ├── test_project.lektorproject
│ └── templates
│ │ ├── page.html
│ │ └── filter.html
└── test.sh
├── setup.cfg
├── .gitignore
├── .pypirc
├── CHANGELOG.md
├── .travis.yml
├── LICENSE
├── Makefile
├── setup.py
├── README.md
└── lektor_minify
└── __init__.py
/tests/project/content/contents.lr:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [bdist_wheel]
2 | universal=1
3 |
--------------------------------------------------------------------------------
/tests/project/packages/lektor-minify:
--------------------------------------------------------------------------------
1 | ../../..
--------------------------------------------------------------------------------
/tests/project/models/page.ini:
--------------------------------------------------------------------------------
1 | [model]
2 | name = Page
3 |
--------------------------------------------------------------------------------
/tests/project/assets/static/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | color: #fff;
3 | }
4 |
--------------------------------------------------------------------------------
/tests/project/test_project.lektorproject:
--------------------------------------------------------------------------------
1 | [project]
2 | name = test_project
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /dist
2 | /build
3 | /tests/tmp
4 |
5 | *.py[co]
6 | *.egg-info
7 |
--------------------------------------------------------------------------------
/tests/project/templates/page.html:
--------------------------------------------------------------------------------
1 |
2 | This is a test ✅
3 |
4 |
--------------------------------------------------------------------------------
/tests/project/assets/static/script.js:
--------------------------------------------------------------------------------
1 | function test() {
2 | console.log("test");
3 | }
4 |
--------------------------------------------------------------------------------
/tests/project/content/filter.html/contents.lr:
--------------------------------------------------------------------------------
1 | _model: none
2 | ---
3 | _template: filter.html
4 |
--------------------------------------------------------------------------------
/.pypirc:
--------------------------------------------------------------------------------
1 | [distutils]
2 | index-servers =
3 | upload
4 |
5 | [upload]
6 | repository = https://upload.pypi.org/legacy/
7 |
--------------------------------------------------------------------------------
/tests/project/templates/filter.html:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # lektor-minify changelog
2 |
3 | ## lektor-minify 1.2
4 |
5 | _Released on February 27th, 2017_
6 |
7 | * Add the `minify()` filter to Jinja2 templates
8 | * Fix plugin crashing sometimes on the development server
9 |
10 | ## lektor-minify 1.1
11 |
12 | _Released on February 21th, 2017_
13 |
14 | * Fix wheel for Python 2 not being built
15 | * Fix unicode files not properly handled
16 |
17 | ## lektor-minify 1.0
18 |
19 | _Released on February 21th, 2017_
20 |
21 | * Initial release
22 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: python
2 | cache: pip
3 |
4 | python:
5 | - 2.7
6 | - 3.6
7 | env:
8 | - LEKTOR=2.3
9 | - LEKTOR=3.0
10 | - LEKTOR=3.1
11 | - LEKTOR=master
12 |
13 | matrix:
14 | exclude:
15 | - python: 3.6
16 | env: LEKTOR=2.3
17 |
18 | install:
19 | - pip install -U virtualenv setuptools
20 | - if [[ "${LEKTOR}" = "master" ]]; then pip install "git+https://github.com/lektor/lektor.git"; else pip install "lektor==${LEKTOR}"; fi
21 |
22 | script:
23 | - tests/test.sh
24 |
25 | notifications:
26 | email: false
27 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2017 Pietro Albini
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2016-2017 Pietro Albini
2 | #
3 | # Permission is hereby granted, free of charge, to any person obtaining a copy
4 | # of this software and associated documentation files (the "Software"), to deal
5 | # in the Software without restriction, including without limitation the rights
6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | # copies of the Software, and to permit persons to whom the Software is
8 | # furnished to do so, subject to the following conditions:
9 | #
10 | # The above copyright notice and this permission notice shall be included in
11 | # all copies or substantial portions of the Software.
12 | #
13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | # SOFTWARE.
20 |
21 | # Configuration
22 | SOURCE = lektor_minify
23 | PACKAGES_OUT = build/packages
24 |
25 | # Uploading configuration
26 | RELEASES_SERVER = files@winter.net.pietroalbini.org
27 | RELEASES_DIR = public/releases/lektor-minify/$(shell $(PYTHON) setup.py --version)
28 |
29 | # Executables
30 | PYTHON = python3
31 | GPG = gpg
32 | TWINE = twine
33 |
34 | .PHONY: build sign _pre-sign upload test clean
35 |
36 |
37 | # Basic packages building
38 |
39 | build: $(PACKAGES_OUT)/*.tar.gz $(PACKAGES_OUT)/*.whl
40 |
41 | $(PACKAGES_OUT):
42 | @mkdir -p $(PACKAGES_OUT)
43 |
44 | $(PACKAGES_OUT)/*.tar.gz: $(PACKAGES_OUT) setup.py $(wildcard $(SOURCE)/*)
45 | @$(PYTHON) setup.py sdist -d $(PACKAGES_OUT)
46 |
47 | build/packages/*.whl: $(PACKAGES_OUT) setup.py $(wildcard $(SOURCE)/*)
48 | @$(PYTHON) setup.py bdist_wheel -d $(PACKAGES_OUT)
49 |
50 |
51 | # Packages signing
52 |
53 | sign: _pre-sign $(addsuffix .asc,$(filter-out $(wildcard $(PACKAGES_OUT)/*.asc),$(wildcard $(PACKAGES_OUT)/*)))
54 |
55 | _pre-sign:
56 | @rm -f $(PACKAGES_OUT)/*.asc
57 |
58 | $(PACKAGES_OUT)/%.asc:
59 | @$(GPG) --detach --armor --sign $(PACKAGES_OUT)/$*
60 |
61 |
62 | # Packages uploading
63 |
64 | upload: build sign
65 | @ssh $(RELEASES_SERVER) -- mkdir -p $(RELEASES_DIR)
66 | @scp $(PACKAGES_OUT)/* $(RELEASES_SERVER):$(RELEASES_DIR)
67 | @$(TWINE) upload --config-file .pypirc -r upload --skip-existing $(PACKAGES_OUT)/*
68 |
69 |
70 | # Testing
71 |
72 | test:
73 | @tests/test.sh
74 |
75 |
76 | # Cleanup
77 |
78 | clean:
79 | @rm -rf build
80 | @rm -rf tests/tmp
81 | @find -name "*.pyc" -delete
82 | @rm -rf $(SOURCE).egg-info
83 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2017 Pietro Albini
2 | #
3 | # Permission is hereby granted, free of charge, to any person obtaining a copy
4 | # of this software and associated documentation files (the "Software"), to deal
5 | # in the Software without restriction, including without limitation the rights
6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | # copies of the Software, and to permit persons to whom the Software is
8 | # furnished to do so, subject to the following conditions:
9 | #
10 | # The above copyright notice and this permission notice shall be included in
11 | # all copies or substantial portions of the Software.
12 | #
13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | # SOFTWARE.
20 |
21 | '''
22 | =============
23 | lektor-minify
24 | =============
25 |
26 | This plugin allows you to minify the build artifacts of your `Lektor`_ project
27 | during the build process, without any additional tool. It currently supports
28 | minifying HTML, CSS and JS files.
29 |
30 | The plugin only minifies the files changed during the last build, avoiding
31 | slowing down the build if your project consists of a lot of files. Internally
32 | it uses the rcssmin and rjsmin libraries, and it's released under the MIT
33 | license.
34 |
35 | `Learn more about the plugin`_
36 |
37 | .. _Lektor: https://www.getlektor.com
38 | .. _Learn more about the plugin: https://github.com/pietroalbini/lektor-minify
39 | '''
40 |
41 | # -*- coding: utf-8 -*-
42 |
43 | import setuptools
44 |
45 |
46 | setuptools.setup(
47 | name = "lektor-minify",
48 | version = "1.3.dev0",
49 | license = "MIT",
50 |
51 | author = "Pietro Albini",
52 | author_email = "pietro@pietroalbini.org",
53 |
54 | description = "Minify build artifacts during the Lektor build process",
55 | long_description = __doc__,
56 |
57 | packages = [
58 | "lektor_minify",
59 | ],
60 |
61 | install_requires = [
62 | "rcssmin",
63 | "rjsmin",
64 | "django_htmlmin",
65 | ],
66 |
67 | entry_points = {
68 | "lektor.plugins": [
69 | "minify = lektor_minify:MinifyPlugin",
70 | ]
71 | },
72 |
73 | classifiers = [
74 | "Development Status :: 5 - Production/Stable",
75 | "Environment :: Plugins",
76 | "Intended Audience :: Developers",
77 | "License :: OSI Approved :: MIT License",
78 | "Programming Language :: Python :: 2",
79 | "Programming Language :: Python :: 3",
80 | ],
81 | )
82 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # lektor-minify
2 |
3 | [](https://travis-ci.org/pietroalbini/lektor-minify)
4 |
5 | This plugin allows you to minify the build artifacts of your [Lektor][lektor]
6 | project during the build process, without any additional tool. It currently
7 | supports minifying HTML, CSS and JS files.
8 |
9 | The plugin only minifies the files changed during the last build, avoiding
10 | slowing down the build if your project consists of a lot of files. Internally
11 | it uses the [django_htmlmin][htmlmin], [rcssmin][rcssmin] and [rjsmin][rjsmin]
12 | libraries, and it's released under the MIT license.
13 |
14 | **Supported Lektor releases:** 2.3, 3.0
15 |
16 | ## Installation
17 |
18 | If you want to use lektor-minify in your project, you can to execute the
19 | following command in your Lektor project folder:
20 |
21 | ```
22 | $ lektor plugins add lektor-minify
23 | ```
24 |
25 | After you did that, it's good to clear the build cache: the plugin only
26 | minifies changed files, so clearing the cache ensures all the assets are
27 | minified:
28 |
29 | ```
30 | $ lektor clean --yes
31 | ```
32 |
33 | ## Usage
34 |
35 | This plugin isn't enabled by default: you need to provide the `minify` flag to
36 | the `build` (or `server`) command if you want to minify the build artifacts:
37 |
38 | ```
39 | $ lektor build -f minify
40 | $ lektor server -f minify
41 | ```
42 |
43 | If you need to minify only some kind of artifacts, you can tell which ones you
44 | want to minify by providing their kinds as a comma-separated list in the flag:
45 |
46 | ```
47 | $ lektor build -f minify:html
48 | $ lektor build -f minify:html,css,js
49 | ```
50 |
51 | Keep in mind only artifacts built with the flag will be minified: if you
52 | execute other builds without the flag there might be some unminified files!
53 |
54 | ## Jinja2 filter
55 |
56 | The plugin also provides the `minify` filter, ready to be used in your
57 | templates. The filter is useful, for example, if you need to include in the
58 | page external assets, and you want them to be minified as well.
59 |
60 | You can use the filter by piping the content into it, and providing the type of
61 | the content as argument:
62 |
63 | ```
64 | {{ this.extra_style | minify("css") }}
65 | ```
66 |
67 | If you need to apply the filter to a block of code, you can also use the filter
68 | block Jinja2 provides:
69 |
70 | ```
71 |
78 | ```
79 |
80 | The filter will work even if the `minify` flag is not provided during the
81 | build.
82 |
83 | ## Testing
84 |
85 | Some basic tests are available for the project. If you want to run them clone
86 | the repository, install Lektor and run:
87 |
88 | ```
89 | make test
90 | ```
91 |
92 | [lektor]: https://www.getlektor.com/
93 | [rcssmin]: http://opensource.perlig.de/rcssmin/
94 | [rjsmin]: http://opensource.perlig.de/rjsmin/
95 | [htmlmin]: https://github.com/cobrateam/django-htmlmin
96 |
--------------------------------------------------------------------------------
/tests/test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # Copyright (c) 2017 Pietro Albini
3 | #
4 | # Permission is hereby granted, free of charge, to any person obtaining a copy
5 | # of this software and associated documentation files (the "Software"), to deal
6 | # in the Software without restriction, including without limitation the rights
7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | # copies of the Software, and to permit persons to whom the Software is
9 | # furnished to do so, subject to the following conditions:
10 | #
11 | # The above copyright notice and this permission notice shall be included in
12 | # all copies or substantial portions of the Software.
13 | #
14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | # SOFTWARE.
21 |
22 | set -euo pipefail
23 |
24 | EXPECTED_CSS='body{color:#fff}'
25 | EXPECTED_JS='function test(){console.log("test");}'
26 | EXPECTED_HTML='This is a test ✅
'
27 | EXPECTED_FILTER_MIN=''
28 | EXPECTED_FILTER_NO_MIN=''
31 |
32 | # Detect source directory
33 | # Thanks to http://stackoverflow.com/a/246128/2204144
34 | source="$0"
35 | while [ -h "${source}" ]; do
36 | dir="$( cd -P "$( dirname "${source}" )" && pwd )"
37 | source="$(readlink "${source}")"
38 | done
39 | BASE="$( cd "$( dirname "${source}" )" && pwd )"
40 |
41 | TEST_PROJECT="${BASE}/project"
42 | TMP_DIRECTORY="${BASE}/tmp"
43 |
44 |
45 | build() {
46 | cd "${TEST_PROJECT}"
47 | rm -rf "${TMP_DIRECTORY}"
48 | lektor build -O "${TMP_DIRECTORY}" $@
49 | }
50 |
51 | assert() {
52 | name="$1"
53 | file="$2"
54 | expected="$3"
55 | outcome="$4"
56 |
57 | content="`cat "${TMP_DIRECTORY}/${file}"`"
58 | if [[ "${content}" == "${expected}" ]]; then
59 | [[ "${outcome}" = "true" ]] || fail "${name}"
60 | else
61 | [[ "${outcome}" = "false" ]] || fail "${name}"
62 | fi
63 | }
64 |
65 | assert_html() { assert html index.html "${EXPECTED_HTML}" "$1"; }
66 | assert_style() { assert css static/style.css "${EXPECTED_CSS}" "$1"; }
67 | assert_script() { assert js static/script.js "${EXPECTED_JS}" "$1"; }
68 | assert_filter_min() { assert filter filter.html "${EXPECTED_FILTER_MIN}" "$1"; }
69 | assert_filter_no_min() { assert filter filter.html "${EXPECTED_FILTER_NO_MIN}" "$1"; }
70 |
71 | fail() {
72 | echo "Failed $@"
73 | exit 1
74 | }
75 |
76 |
77 | echo "Testing with no flags..."
78 | build
79 | assert_html false
80 | assert_style false
81 | assert_script false
82 | assert_filter_no_min true
83 |
84 | echo "Testing with the minify flag..."
85 | build -f minify
86 | assert_html true
87 | assert_style true
88 | assert_script true
89 | assert_filter_min true
90 |
91 | echo "Testing with the minify:css flag..."
92 | build -f minify:css
93 | assert_html false
94 | assert_style true
95 | assert_script false
96 | assert_filter_no_min true
97 |
98 | echo "Testing with the minify:js flag..."
99 | build -f minify:js
100 | assert_html false
101 | assert_style false
102 | assert_script true
103 | assert_filter_no_min true
104 |
105 | echo "Testing with the minify:html flag..."
106 | build -f minify:html
107 | assert_html true
108 | assert_style false
109 | assert_script false
110 | assert_filter_min true
111 |
112 | echo "Testing with the minify:css,js,html flag..."
113 | build -f minify:css,js,html
114 | assert_html true
115 | assert_style true
116 | assert_script true
117 | assert_filter_min true
118 |
119 | echo "Test successful!"
120 | rm -rf "${TMP_DIRECTORY}"
121 |
--------------------------------------------------------------------------------
/lektor_minify/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2017 Pietro Albini
2 | #
3 | # Permission is hereby granted, free of charge, to any person obtaining a copy
4 | # of this software and associated documentation files (the "Software"), to deal
5 | # in the Software without restriction, including without limitation the rights
6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | # copies of the Software, and to permit persons to whom the Software is
8 | # furnished to do so, subject to the following conditions:
9 | #
10 | # The above copyright notice and this permission notice shall be included in
11 | # all copies or substantial portions of the Software.
12 | #
13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | # SOFTWARE.
20 |
21 | # -*- coding: utf-8 -*-
22 |
23 | from __future__ import unicode_literals
24 |
25 | import codecs
26 |
27 | import rcssmin
28 | import rjsmin
29 | import htmlmin.minify as htmlmin
30 |
31 | from lektor.pluginsystem import Plugin
32 | from lektor.reporter import reporter
33 |
34 |
35 | MINIFY_FLAG = "minify"
36 | FILTER_NAME = "minify"
37 |
38 | # To add new minifiers, you need to add a new matcher and the corresponding
39 | # minifier -- no other code change is needed
40 | MATCHERS = {
41 | "html": lambda name: name.endswith(".html"),
42 | "css": lambda name: name.endswith(".css"),
43 | "js": lambda name: name.endswith(".js"),
44 | }
45 | MINIFIERS = {
46 | "html": htmlmin.html_minify,
47 | "css": rcssmin.cssmin,
48 | "js": rjsmin.jsmin,
49 | }
50 |
51 |
52 | class MinifyPlugin(Plugin):
53 | name = u"minify"
54 | description = u"Minify your build artifacts during the build process"
55 |
56 | def __init__(self, *args, **kwargs):
57 | Plugin.__init__(self, *args, **kwargs)
58 |
59 | def can_minify(self, builder, type):
60 | """Check if a file type can be minified"""
61 | try:
62 | types = builder.__can_minify
63 | except AttributeError:
64 | types = self.parse_flags(builder)
65 |
66 | return type in types
67 |
68 | def parse_flags(self, builder):
69 | """Parse the flags of the provided builder"""
70 | try: # Lektor 3+
71 | flags = builder.extra_flags
72 | except AttributeError: # Lektor 2
73 | flags = builder.build_flags
74 |
75 | types = set()
76 |
77 | allowed_kinds = set(MATCHERS.keys())
78 | if MINIFY_FLAG in flags:
79 | if flags[MINIFY_FLAG] == MINIFY_FLAG:
80 | types = allowed_kinds
81 | else:
82 | kinds = set(flags[MINIFY_FLAG].split(","))
83 |
84 | diff = kinds - allowed_kinds
85 | for kind in diff:
86 | reporter.report_generic(
87 | "\033[33mUnknown param for flag %s:\033[37m %s"
88 | % (MINIFY_FLAG, kind)
89 | )
90 |
91 | types = kinds & allowed_kinds
92 |
93 | builder.__can_minify = types
94 | return types
95 |
96 | def jinja_filter(self, content, type):
97 | """Minify a part of a template"""
98 | if type not in MINIFIERS:
99 | raise NameError("Unknown minifier: %s" % type)
100 | return MINIFIERS[type](content)
101 |
102 | def on_setup_env(self, **extra):
103 | self.env.jinja_env.filters[FILTER_NAME] = self.jinja_filter
104 |
105 | def on_after_build(self, builder, build_state, **extra):
106 | # Get the new artifacts built in this state
107 | try:
108 | seen = build_state.__seen_artifacts
109 | except AttributeError:
110 | build_state.__seen_artifacts = set()
111 | artifacts = set(build_state.updated_artifacts)
112 | else:
113 | updated = set(build_state.updated_artifacts)
114 | artifacts = updated - seen
115 |
116 | # This keeps track of the artifacts already built in this build_state,
117 | # so those files aren't minified multiple times
118 | build_state.__seen_artifacts |= artifacts
119 |
120 | for artifact in artifacts:
121 | name = artifact.dst_filename
122 |
123 | for type, matcher in MATCHERS.items():
124 | if matcher(name) and self.can_minify(builder, type):
125 | minifier = MINIFIERS[type]
126 | break
127 | else:
128 | continue
129 |
130 | with artifact.update():
131 | with artifact.open("rb+") as f:
132 | content = codecs.decode(f.read(), "utf-8")
133 |
134 | f.seek(0)
135 | f.write(codecs.encode(minifier(content), "utf-8"))
136 | f.truncate()
137 |
--------------------------------------------------------------------------------