|
3 | 3 | import time |
4 | 4 |
|
5 | 5 | from django.core.management.base import BaseCommand |
6 | | -from django.contrib.staticfiles.finders import get_finders |
7 | 6 | import sass |
8 | 7 |
|
| 8 | +from django_sass import compile_sass, find_static_scss |
| 9 | + |
9 | 10 |
|
10 | 11 | class Command(BaseCommand): |
11 | 12 | help = "Runs libsass including all paths from STATICFILES_FINDERS." |
@@ -51,109 +52,66 @@ def add_arguments(self, parser): |
51 | 52 | help="Watch input path and re-generate css files when scss files are changed.", |
52 | 53 | ) |
53 | 54 |
|
54 | | - def compile_sass(self, outfile: str, **kwargs) -> None: |
55 | | - rval = sass.compile(**kwargs) |
56 | | - # sass.compile() will return None if used with dirname. |
57 | | - # If used with filename, it will return a string of file contents. |
58 | | - if rval and outfile: |
59 | | - # If we got a css and sourcemap tuple, write the sourcemap. |
60 | | - if isinstance(rval, tuple): |
61 | | - map_outfile = outfile + ".map" |
62 | | - outfile_dir = os.path.dirname(map_outfile) |
63 | | - if not os.path.exists(outfile_dir): |
64 | | - os.makedirs(outfile_dir, exist_ok=True) |
65 | | - file = open(map_outfile, "w", encoding="utf8") |
66 | | - file.write(rval[1]) |
67 | | - file.close() |
68 | | - rval = rval[0] |
69 | | - |
70 | | - # Write the outputted css to file. |
71 | | - outfile_dir = os.path.dirname(outfile) |
72 | | - if not os.path.exists(outfile_dir): |
73 | | - os.makedirs(outfile_dir, exist_ok=True) |
74 | | - file = open(outfile, "w", encoding="utf8") |
75 | | - file.write(rval) |
76 | | - file.close() |
77 | | - |
78 | 55 | def handle(self, *args, **options) -> None: |
79 | 56 | """ |
80 | 57 | Finds all static paths used by the project, and runs sass |
81 | 58 | including those paths. |
82 | 59 | """ |
83 | | - found_paths = [] |
84 | | - for finder in get_finders(): |
85 | | - if hasattr(finder, "storages"): |
86 | | - for appname in finder.storages: |
87 | | - if hasattr(finder.storages[appname], "location"): |
88 | | - abspath = finder.storages[appname].location |
89 | | - found_paths.append(abspath) |
90 | | - |
91 | | - sassargs = {"output_style": options["t"], "precision": options["p"]} |
92 | | - inpath = options["in"][0] |
93 | | - outpath = options["out"][0] |
94 | | - outfile = None |
95 | 60 |
|
96 | | - if found_paths: |
97 | | - sassargs.update({"include_paths": found_paths}) |
98 | | - |
99 | | - if os.path.isdir(inpath): |
100 | | - # Assume outpath is also a dir, or make it. |
101 | | - if not os.path.exists(outpath): |
102 | | - os.makedirs(outpath) |
103 | | - if os.path.isdir(outpath): |
104 | | - sassargs.update({"dirname": (inpath, outpath)}) |
105 | | - else: |
106 | | - raise NotADirectoryError( |
107 | | - "Output path must also be a directory when input path is a directory." |
108 | | - ) |
109 | | - |
110 | | - if os.path.isfile(inpath): |
111 | | - sassargs.update({"filename": inpath}) |
112 | | - if os.path.isdir(outpath): |
113 | | - outfile = os.path.join( |
114 | | - outpath, os.path.basename(inpath.replace(".scss", ".css")) |
115 | | - ) |
116 | | - else: |
117 | | - outfile = outpath |
118 | | - if options["g"]: |
119 | | - sassargs.update({"source_map_filename": outfile + ".map"}) |
| 61 | + # Parse options. |
| 62 | + o_inpath = options["in"][0] |
| 63 | + o_outpath = options["out"][0] |
| 64 | + o_srcmap = options["g"] |
| 65 | + o_precision = options["p"] |
| 66 | + o_style = options["t"] |
120 | 67 |
|
121 | 68 | # Watch files for changes if specified. |
122 | 69 | if options["watch"]: |
123 | 70 | try: |
124 | 71 | self.stdout.write("Watching...") |
| 72 | + |
| 73 | + # Track list of files to watch and their modified time. |
125 | 74 | watchfiles = {} |
126 | 75 | while True: |
127 | 76 | needs_updated = False |
128 | 77 |
|
129 | 78 | # Build/update list of ALL scss files in static paths. |
130 | | - for finder in get_finders(): |
131 | | - for path, storage in finder.list([]): |
132 | | - if path.endswith(".scss"): |
133 | | - fullpath = finder.find(path) |
134 | | - prev_mtime = watchfiles.get(fullpath, 0) |
135 | | - curr_mtime = os.stat(fullpath).st_mtime |
136 | | - if curr_mtime > prev_mtime: |
137 | | - needs_updated = True |
138 | | - watchfiles.update({fullpath: curr_mtime}) |
| 79 | + for fullpath in find_static_scss(): |
| 80 | + prev_mtime = watchfiles.get(fullpath, 0) |
| 81 | + curr_mtime = os.stat(fullpath).st_mtime |
| 82 | + if curr_mtime > prev_mtime: |
| 83 | + needs_updated = True |
| 84 | + watchfiles.update({fullpath: curr_mtime}) |
139 | 85 |
|
140 | 86 | # Recompile the sass if needed. |
141 | 87 | if needs_updated: |
142 | 88 | # Catch compile errors to keep the watcher running. |
143 | 89 | try: |
144 | | - self.compile_sass(outfile, **sassargs) |
| 90 | + compile_sass( |
| 91 | + inpath=o_inpath, |
| 92 | + outpath=o_outpath, |
| 93 | + output_style=o_style, |
| 94 | + precision=o_precision, |
| 95 | + source_map=o_srcmap, |
| 96 | + ) |
145 | 97 | self.stdout.write("Updated files at %s" % time.time()) |
146 | 98 | except sass.CompileError as exc: |
147 | 99 | self.stdout.write(str(exc)) |
148 | 100 |
|
149 | 101 | # Go back to sleep. |
150 | 102 | time.sleep(3) |
151 | 103 |
|
152 | | - except KeyboardInterrupt: |
| 104 | + except (KeyboardInterrupt, InterruptedError): |
153 | 105 | self.stdout.write("Bye.") |
154 | 106 | sys.exit(0) |
155 | 107 |
|
156 | 108 | # Write css. |
157 | 109 | self.stdout.write("Writing css...") |
158 | | - self.compile_sass(outfile, **sassargs) |
| 110 | + compile_sass( |
| 111 | + inpath=o_inpath, |
| 112 | + outpath=o_outpath, |
| 113 | + output_style=o_style, |
| 114 | + precision=o_precision, |
| 115 | + source_map=o_srcmap, |
| 116 | + ) |
159 | 117 | self.stdout.write("Done.") |
0 commit comments