diff --git a/.gitignore b/.gitignore index 57ac9b1..22875f1 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ mincss.egg-info/ simple.js *.pyc __pycache__/ +.cache/ +.eggs/ diff --git a/.travis.yml b/.travis.yml index 73f9e10..884c645 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ cache: pip python: - '2.7' +- '3.3' - '3.4' - '3.5' diff --git a/README.rst b/README.rst index 7f33bf0..24eaf8f 100644 --- a/README.rst +++ b/README.rst @@ -1,3 +1,9 @@ +**UPDATE April 2019** + +INSTEAD OF USING THIS, A MUCH BETTER ALTERNATIVE IS https://github.com/peterbe/minimalcss/ WHICH SUPPORTS JAVASCRIPT AND THE CSS PARSING AND TRANSFORMATIONS ARE DONE WITH A PARSED AST. + + + mincss ====== @@ -8,9 +14,9 @@ mincss Clears the junk out of your CSS by finding out which selectors are actually not used in your HTML. -By Peter Bengtsson, 2012-2015 +By Peter Bengtsson, 2012-2018 -Tested in Python 2.7, 3.3 and 3.4 +Tested in Python 2.7, 3.3, 3.4 and 3.5 Example ------- diff --git a/docs/api.rst b/docs/api.rst index 01d5a0c..b303e1b 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -51,6 +51,10 @@ API If you for some reason already have the HTML you can jump straight to this method. Note, you still need to provide the URL where you got the HTML from so it can use that to download any external CSS. + + * When calling ``process_url()`` or ``process_html()``, you have to call ``process()`` + at the end without arguments, in order to post process the pages that were + processed individually. The ``Processor`` instance will make two attributes available diff --git a/mincss/__init__.py b/mincss/__init__.py index 2b3823f..94f8ab8 100644 --- a/mincss/__init__.py +++ b/mincss/__init__.py @@ -1 +1 @@ -__version__ = '0.11.2' +__version__ = '0.11.6' diff --git a/mincss/main.py b/mincss/main.py index 5f2f6f0..0f79534 100644 --- a/mincss/main.py +++ b/mincss/main.py @@ -4,10 +4,14 @@ import os import time +from mincss import __version__ from .processor import Processor def run(args): + if args.version: + print(__version__) + return options = {'debug': args.verbose} if args.phantomjs_path: options['phantomjs'] = args.phantomjs_path @@ -64,6 +68,9 @@ def main(): add('--phantomjs-path', action='store', default='', help='Where is the phantomjs executable') + add('--version', action='store_true', + default=False, + help='Prints out the version of mincss') args = parser.parse_args() return run(args) or 0 diff --git a/mincss/processor.py b/mincss/processor.py index fc045a4..f8ef569 100644 --- a/mincss/processor.py +++ b/mincss/processor.py @@ -43,6 +43,12 @@ VENDOR_PREFIXED_PSEUDO_CLASSES = re.compile( ':-(webkit|moz)-' ) +# For matching things like "foo:bar" and '"foo:ing":bar' because it's +# not enough to just do a split on ':' since the ':' might be inside +# quotation marks. E.g. 'a[href^="javascript:"]' +PSEUDO_SELECTOR = re.compile( + r':(?=([^"\'\\]*(\\.|["\']([^"\'\\]*\\.)*[^"\'\\]*[\'"]))*[^"\']*$)' +) EXCEPTIONAL_SELECTORS = ( 'html', @@ -153,12 +159,14 @@ def process(self, *urls): for identifier in sorted(self.blocks.keys()): content = self.blocks[identifier] - processed = self._process_content(content, self._bodies) + no_mincss = identifier[-1] + if no_mincss: + processed = content + else: + processed = self._process_content(content, self._bodies) if identifier[1] == INLINE: - line, _, url, no_mincss = identifier - if no_mincss: - processed = content + line, _, url, _ = identifier self.inlines.append( InlineResult( line, @@ -168,9 +176,7 @@ def process(self, *urls): ) ) else: - _, _, url, href, no_mincss = identifier - if no_mincss: - processed = content + _, _, url, href, _ = identifier self.links.append( LinkResult( href, @@ -391,7 +397,7 @@ def commentmatcher(match): for temp_key, old, __ in inner_improvements: assert old in content, old - content = content.replace(old, temp_key) + content = content.replace(old, temp_key, 1) _regex = re.compile('((.*?){(.*?)})', re.DOTALL | re.M) @@ -504,8 +510,6 @@ def _found(self, bodies, selector): # If the last part of the selector is a tag like # ".foo blockquote" or "sometag" then we can look for it # in plain HTML as a form of optimization - last_part = selector.split()[-1] - # if self._all_tags and '"' not in selector: if not re.findall('[^\w \.]', selector): # It's a trivial selector. Like "tag.myclass", # or ".one.two". Let's look for some cheap wins @@ -525,7 +529,7 @@ def _found(self, bodies, selector): def _simplified_selector(selector): # If the select has something like :active or :hover, # then evaluate it as if it's without that pseudo class - return selector.split(':')[0].strip() + return PSEUDO_SELECTOR.split(selector)[0].strip() def _selector_query_found(self, bodies, selector): if '}' in selector: diff --git a/run.py b/run.py index 94c4083..bb4d10b 100755 --- a/run.py +++ b/run.py @@ -3,6 +3,7 @@ import os import sys import time +import codecs # make sure it's running the mincss here and not anything installed @@ -40,11 +41,13 @@ def run(args): #print("AFTER ".ljust(79, '-')) #print(link.after) orig_name = link.href.split('/')[-1] - with open(os.path.join(output_dir, orig_name), 'w') as f: + fn = os.path.join(output_dir, orig_name) + with codecs.open(fn, 'w', 'utf-8') as f: f.write(link.after) before_name = 'before_' + link.href.split('/')[-1] - with open(os.path.join(output_dir, before_name), 'w') as f: - f.write(link.before.encode('utf-8')) + fn = os.path.join(output_dir, before_name) + with codecs.open(fn, 'w', 'utf-8') as f: + f.write(link.before) print("Files written to", output_dir) print() print( diff --git a/setup.py b/setup.py index bd61d7d..f09a8a6 100755 --- a/setup.py +++ b/setup.py @@ -62,6 +62,7 @@ def find_install_requires(): 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', ], install_requires=find_install_requires(), entry_points={'console_scripts': ['mincss=mincss.main:main']}, diff --git a/tests/complex-selector.html b/tests/complex-selector.html index 14f057f..40916d3 100644 --- a/tests/complex-selector.html +++ b/tests/complex-selector.html @@ -6,11 +6,20 @@