This repository has been archived by the owner on Dec 24, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 41
/
more.rb
142 lines (122 loc) · 4.51 KB
/
more.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# Less::More provides methods for parsing LESS files in a rails application to CSS target files.
#
# When Less::More.parse is called, all files in Less::More.source_path will be parsed using LESS
# and saved as CSS files in Less::More.destination_path. If Less::More.compression is set to true,
# extra line breaks will be removed to compress the CSS files.
#
# By default, Less::More.parse will be called for each request in `development` environment and on
# application initialization in `production` environment.
begin
require 'less'
rescue LoadError => e
e.message << " (You may need to install the less gem)"
raise e
end
class Less::More
HEADER = %{/*\n\n\n\n\n\tThis file was auto generated by Less (http://lesscss.org). To change the contents of this file, edit %s instead.\n\n\n\n\n*/}
class << self
# Less::More.compression = true/false --- compress generated css ? (default: false)
# Less::More.header = true/false --- insert editing warning into css ? (default: true)
# Less::More.destination_path = 'css' --- put css into public/??? (default: stylesheets)
# Less::More.source_path = 'public/stylesheets/less' --- where do less files live? (default: app/stylesheets)
attr_writer :compression, :header, :destination_path, :source_path
def header
@header.nil? ? true : @header
end
def destination_path
@destination_path || 'stylesheets'
end
def source_path
@source_path || 'app/stylesheets'
end
def compression
@compression
end
# Generates the .css from a .less or .lss file in Less::More.source_path matching
# the given parameters.
#
# Less::More.generate("screen.less")
# Less::More.generate("subdirectories/here/homepage.less")
def generate(source)
generated = to_dot_css(path_to_destination(source))
path_to_source = File.join(Rails.root, source_path, source)
# check if the destination file exists, and compare the modified times to see if it needs to be written
if mtime(generated) >= mtime_including_imports(path_to_source)
# up to date, nothing to do!
else
# css file does not exist or is out of date
css = if File.extname(path_to_source) == ".css"
# vanilla css nothing to do!
File.read(path_to_source)
else
# less or lss file, compile it
css = compile(path_to_source)
css.delete!("\n") if compression # TODO: use real compression !
css = (HEADER % [File.join(source_path, source)]) << css if header
css
end
# write the css
FileUtils.mkdir_p File.dirname(generated)
File.open(generated, "w"){|f| f.write css }
end
end
# Generates all the .css files
def generate_all
all_less_files.each do |path|
generate(relative_to_source_path(path))
end
end
# Removes all generated css files.
def remove_all_generated
all_less_files.each do |path|
css_path = to_dot_css(relative_to_source_path(path))
css_file = path_to_destination(css_path)
File.delete(css_file) if File.file?(css_file)
end
end
# Array of paths of less source files.
def all_less_files
all = Dir[File.join(Rails.root, source_path, "**", "*.{css,less,lss}")]
all.reject{|path| File.basename(path) =~ /^_/ }
end
private
def mtime(file)
return 0 unless File.file?(file)
File.mtime(file).to_i
end
# consider imports for mtime
# just 1 level deep so we do not get any looping/nesting errors
def mtime_including_imports(file)
mtimes = [mtime(file)]
File.readlines(file).each do |line|
if line =~ /^\s*@import ['"]([^'"]+)/
imported = File.join(File.dirname(file), $1)
mtimes << if imported =~ /\.le?ss$/ # complete path given ?
mtime(imported)
else # we need to add .less or .lss
[mtime("#{imported}.less"), mtime("#{imported}.lss")].max
end
end
end
mtimes.max
end
def compile(file)
begin
engine = File.open(file){|f| Less::Engine.new(f) }
engine.to_css
rescue Exception => e
e.message << "\nFrom #{file}"
raise e
end
end
def to_dot_css(path)
path.to_s.sub(/(le?|c)ss$/, "css")
end
def path_to_destination(path)
File.join(Rails.root, "public", destination_path, path)
end
def relative_to_source_path(path)
path.to_s.sub(File.join(Rails.root, source_path), '')[1..-1]
end
end
end