Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
mincss
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Taddeüs Kroes
mincss
Commits
34391515
Commit
34391515
authored
Jul 28, 2014
by
Taddeüs Kroes
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implemented shorthands and more color names
parent
515b05a9
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
244 additions
and
46 deletions
+244
-46
Makefile
Makefile
+2
-1
color.ml
color.ml
+4
-16
main.ml
main.ml
+14
-4
shorthand.ml
shorthand.ml
+177
-16
stringify.ml
stringify.ml
+41
-9
types.ml
types.ml
+2
-0
util.ml
util.ml
+4
-0
No files found.
Makefile
View file @
34391515
RESULT
:=
mincss
PRE_TGTS
:=
types
MODULES
:=
util stringify parser lexer parse color shorthand main
MODULES
:=
color_names
util stringify parser lexer parse color shorthand main
ALL_NAMES
:=
$(PRE_TGTS)
$(MODULES)
OCAMLCFLAGS
:=
-g
...
...
@@ -37,6 +37,7 @@ parser.mli: parser.ml
parse.cmx
:
lexer.cmi parser.cmx
main.cmx
:
parse.cmx util.cmx color.cmx shorthand.cmx
util.cmx
:
OCAMLCFLAGS += -pp cpp
util.cmx color.cmx
:
color_names.cmx
stringify.cmx parser.cmx color.cmx shorthand.cmx
:
util.cmi
$(addsuffix .cmx,$(MODULES))
:
$(addsuffix .cmi
,
$(PRE_TGTS))
...
...
color.ml
View file @
34391515
...
...
@@ -13,21 +13,6 @@ let clip = function
|
value
->
value
let
rec
short
=
function
|
Ident
"black"
->
Hexcolor
"000"
|
Ident
"fuchsia"
->
Hexcolor
"f0f"
|
Ident
"white"
->
Hexcolor
"fff"
|
Ident
"yellow"
->
Hexcolor
"ff0"
|
Hexcolor
"808080"
->
Ident
"gray"
|
Hexcolor
"008000"
->
Ident
"green"
|
Hexcolor
"800000"
->
Ident
"maroon"
|
Hexcolor
"000080"
->
Ident
"navy"
|
Hexcolor
"8080000"
->
Ident
"olive"
|
Hexcolor
"800080"
->
Ident
"purple"
|
Hexcolor
"ff0000"
|
Hexcolor
"f00"
->
Ident
"red"
|
Hexcolor
"c0c0c0"
->
Ident
"silver"
|
Hexcolor
"008080"
->
Ident
"teal"
(* #aabbcc -> #abc *)
|
Hexcolor
h
when
Str
.
string_match
hex6
h
0
->
let
gr
n
=
Str
.
matched_group
n
h
in
...
...
@@ -52,7 +37,10 @@ let rec short = function
|
Function
(
"rgba"
,
Nary
(
","
,
[
r
;
g
;
b
;
Number
(
1
.,
None
)]))
->
short
(
Function
(
"rgb"
,
Nary
(
","
,
[
r
;
g
;
b
])))
|
v
->
v
(* TODO: hsl[a](...) *)
(* transform color names to shorter hex codes and vice-versa *)
|
v
->
Color_names
.
compress
v
let
transform
=
function
|
Expr
value
->
Expr
(
short
value
)
...
...
main.ml
View file @
34391515
...
...
@@ -5,8 +5,9 @@ type args = {
mutable
infiles
:
string
list
;
mutable
outfile
:
string
option
;
mutable
verbose
:
int
;
mutable
echo
:
bool
;
mutable
pretty
:
bool
;
mutable
echo
:
bool
;
mutable
pretty
:
bool
;
mutable
unfold
:
bool
;
}
(* Parse command-line arguments *)
...
...
@@ -17,6 +18,7 @@ let parse_args () =
verbose
=
1
;
echo
=
false
;
pretty
=
false
;
unfold
=
false
;
}
in
let
args_spec
=
[
(
"<file> ..."
,
Arg
.
Rest
(
fun
_
->
()
)
,
...
...
@@ -34,6 +36,9 @@ let parse_args () =
(
"--pretty"
,
Arg
.
Unit
(
fun
_
->
args
.
pretty
<-
true
)
,
" Minify, but pretty-print the parsed CSS (for debugging)"
);
(
"--unfold"
,
Arg
.
Unit
(
fun
_
->
args
.
unfold
<-
true
)
,
" Only unfold shorthands (for debugging)"
);
]
in
let
usage
=
...
...
@@ -72,6 +77,9 @@ let handle_args args =
match
args
with
|
{
echo
=
true
}
->
write_output
(
Stringify
.
string_of_stylesheet
stylesheet
)
|
{
unfold
=
true
}
->
let
stylesheet
=
Shorthand
.
unfold_stylesheet
stylesheet
in
write_output
(
Stringify
.
string_of_stylesheet
stylesheet
)
|
_
->
let
stylesheet
=
Color
.
compress
stylesheet
in
let
stylesheet
=
Shorthand
.
compress
stylesheet
in
...
...
@@ -102,8 +110,10 @@ let main () =
with
|
Loc_error
(
loc
,
msg
)
->
Util
.
prerr_loc_msg
(
args
.
verbose
>=
1
)
loc
(
"Error: "
^
msg
);
|
Failure
err
->
prerr_endline
(
"Error: "
^
err
);
|
Box_error
(
box
,
msg
)
->
prerr_endline
(
"Error: "
^
msg
^
": "
^
Stringify
.
string_of_box
box
);
|
Failure
msg
->
prerr_endline
(
"Error: "
^
msg
);
end
;
exit
1
...
...
shorthand.ml
View file @
34391515
...
...
@@ -9,7 +9,7 @@ module SS = Set.Make(String)
let
pattern
=
Str
.
regexp
(
"^
\\
(background
\\
|border
\\
|font
\\
|list-style"
^
"
\\
|outline
\\
|padding
\\
|margin
\\
)-
\\
(.*
\\
)$"
)
let
subprops
=
function
let
order
=
function
|
"background"
->
[
"color"
;
"image"
;
"repeat"
;
"attachment"
;
"position"
]
|
"border"
->
[
"width"
;
"style"
;
"color"
]
|
"font"
->
[
"style"
;
"variant"
;
"weight"
;
"size"
;
"family"
]
...
...
@@ -21,15 +21,23 @@ let subprops = function
let
rec
decls_mem
name
=
function
|
[]
->
false
|
(
nm
,
_
,
false
)
::
_
when
nm
=
name
->
true
|
(
nm
,
_
,
_
)
::
_
when
nm
=
name
->
true
|
_
::
tl
->
decls_mem
name
tl
let
rec
decls_find
name
=
function
|
[]
->
raise
Not_found
|
(
nm
,
value
,
false
)
::
_
when
nm
=
name
->
value
|
_
::
tl
->
decls_find
name
tl
(* find the value of the last declaration of some property (since the earlier
* values are overridden), unless an earlier !important value was found *)
let
decls_find
name
decls
=
let
rec
wrap
known
=
function
|
[]
->
known
|
(
nm
,
value
,
true
)
::
_
when
nm
=
name
->
Some
value
|
(
nm
,
value
,
false
)
::
tl
when
nm
=
name
->
wrap
(
Some
value
)
tl
|
_
::
tl
->
wrap
known
tl
in
match
wrap
None
decls
with
|
None
->
raise
Not_found
|
Some
value
->
value
let
order
base
decls
=
let
fold
base
decls
=
let
rec
filter
=
function
|
[]
->
[]
...
...
@@ -44,7 +52,7 @@ let order base decls =
|
_
::
tl
->
filter
tl
in
filter
(
subprops
base
)
filter
(
order
base
)
let
shorten_box_dims
=
function
|
[
top
;
right
;
bottom
;
left
]
...
...
@@ -56,16 +64,16 @@ let shorten_box_dims = function
let
shorten
decls
=
function
(* `font-size` and `font-family` are required for `font` *)
|
"font"
when
decls_mem
"font-size"
decls
&&
decls_mem
"font-family"
decls
->
Some
(
Concat
(
order
"font"
decls
))
Some
(
Concat
(
fold
"font"
decls
))
(* `border-style` is required for `border` *)
|
"border"
when
decls_mem
"border-style"
decls
->
Some
(
Concat
(
order
"border"
decls
))
Some
(
Concat
(
fold
"border"
decls
))
(* others require at least one property, which is the case when this function
* is called *)
|
(
"background"
|
"list-style"
|
"outline"
)
as
base
->
Some
(
Concat
(
order
base
decls
))
Some
(
Concat
(
fold
base
decls
))
(* margin and padding can only be shorthanded when all directions are known,
* merging into even shorter shorthands is done by `shorten_box_dims` *)
...
...
@@ -78,14 +86,161 @@ let shorten decls = function
|
_
->
None
let
rec
list_from
i
=
function
|
[]
when
i
>
0
->
raise
(
Invalid_argument
"l"
)
|
[]
->
[]
(* make the compiler happy *)
|
l
when
i
=
0
->
l
|
_
::
tl
->
list_from
(
i
-
1
)
tl
let
is_width
=
function
|
Ident
(
"thin"
|
"thick"
|
"medium"
)
|
Number
_
->
true
|
_
->
false
let
rec
unfold
=
function
|
[]
->
[]
(* do not unfold "<shorthand>: inherit;" *)
|
((
"background"
|
"border"
|
"font"
|
"list-style"
|
"outline"
|
"margin"
|
"padding"
)
,
Ident
"inherit"
,
_
)
as
orig
::
tl
->
orig
::
unfold
tl
(* background: [color] [image] [repeat] [attachment] [position] *)
|
(
"background"
,
Concat
values
,
imp
)
::
tl
->
let
make
sub
value
=
(
"background-"
^
sub
,
value
,
imp
)
in
let
id_color
=
function
|
[]
->
[]
|
[
color
]
when
Color_names
.
is_color
color
->
[
make
"color"
color
]
|
tl
->
raise
(
Box_error
(
Expr
(
Concat
tl
)
,
"invalid background shortcut"
))
(*| _ -> failwith "invalid background shortcut"*)
in
let
id_repeat
=
function
|
repeat
::
(
Uri
_
as
image
)
::
tl
->
make
"repeat"
repeat
::
make
"image"
image
::
id_color
tl
|
Uri
_
as
image
::
tl
->
make
"image"
image
::
id_color
tl
|
tl
->
id_color
tl
in
let
id_attachment
=
function
|
Ident
_
as
attachment
::
(
Ident
_
as
repeat
)
::
tl
->
make
"attachment"
attachment
::
make
"repeat"
repeat
::
id_repeat
tl
|
Ident
(
"scroll"
|
"fixed"
)
as
attachment
::
(
Uri
url
::
_
as
tl
)
->
make
"attachment"
attachment
::
id_repeat
tl
|
(
_
::
Uri
_
::
_
)
as
tl
|
tl
->
id_repeat
tl
in
let
id_pos
=
function
|
Number
_
as
posy
::
(
Number
_
as
posx
)
::
tl
|
(
Ident
(
"top"
|
"center"
|
"bottom"
)
as
posy
)
::
(
Ident
(
"left"
|
"center"
|
"right"
)
as
posx
)
::
tl
->
make
"position-y"
posy
::
make
"position-x"
posx
::
id_attachment
tl
|
tl
->
id_attachment
tl
in
List
.
rev
(
id_pos
(
List
.
rev
values
))
@
unfold
tl
|
(
"background"
,
(
Uri
_
as
image
)
,
imp
)
::
tl
->
(
"background-image"
,
image
,
imp
)
::
unfold
tl
|
(
"background"
,
color
,
imp
)
::
tl
->
(
"background-color"
,
color
,
imp
)
::
unfold
tl
(* border: [width] style [color] *)
|
(
"border"
,
Concat
[
Ident
_
as
style
]
,
imp
)
::
tl
->
(
"border-style"
,
style
,
imp
)
::
unfold
tl
|
(
"border"
,
Concat
[
width
;
Ident
_
as
style
;
color
]
,
imp
)
::
tl
->
(
"border-width"
,
width
,
imp
)
::
(
"border-style"
,
style
,
imp
)
::
(
"border-color"
,
color
,
imp
)
::
unfold
tl
|
(
"border"
,
Concat
[
Number
_
as
width
;
Ident
_
as
style
]
,
imp
)
::
tl
->
(
"border-width"
,
width
,
imp
)
::
(
"border-style"
,
style
,
imp
)
::
unfold
tl
|
(
"border"
,
Concat
[
Ident
_
as
style
;
color
]
,
imp
)
::
tl
->
(
"border-style"
,
style
,
imp
)
::
(
"border-color"
,
color
,
imp
)
::
unfold
tl
(* font: [style] [variant] [weight] size[/line-height] family *)
|
(
"font"
,
Concat
values
,
imp
)
as
orig
::
tl
->
let
replacement
=
let
make
sub
value
=
(
"font-"
^
sub
,
value
,
imp
)
in
let
identify
options
=
let
return
sub
=
assert
(
List
.
mem
sub
options
);
sub
in
function
|
Ident
"normal"
->
List
.
hd
options
|
Ident
(
"italic"
|
"oblique"
)
->
return
"style"
|
Ident
"small-caps"
->
return
"variant"
|
_
->
return
"weight"
in
match
values
with
|
[
size
;
family
]
->
[
make
"size"
size
;
make
"family"
family
]
|
[
first
;
size
;
family
]
->
[
make
(
identify
[
"weight"
;
"variant"
;
"style"
]
first
)
first
;
make
"size"
size
;
make
"family"
family
]
|
[
first
;
second
;
size
;
family
]
->
[
make
(
identify
[
"variant"
;
"style"
]
first
)
first
;
make
(
identify
[
"weight"
;
"variant"
]
second
)
second
;
make
"size"
size
;
make
"family"
family
]
|
[
style
;
variant
;
weight
;
size
;
family
]
->
[
make
"style"
style
;
make
"variant"
variant
;
make
"weight"
weight
;
make
"size"
size
;
make
"family"
family
]
|
_
->
[
orig
]
in
let
rec
split_size
=
function
|
[]
->
[]
|
(
"font-size"
,
Nary
(
"/"
,
[
size
;
line_height
])
,
_
)
::
tl
->
(
"font-size"
,
size
,
imp
)
::
(
"line-height"
,
line_height
,
imp
)
::
tl
|
hd
::
tl
->
hd
::
split_size
tl
in
split_size
replacement
@
unfold
tl
(* list-style: [type] [position] [image] *)
|
(
"list-style"
,
Concat
[
ltype
;
pos
;
image
]
,
imp
)
::
tl
->
(
"list-style-type"
,
ltype
,
imp
)
::
(
"list-style-position"
,
pos
,
imp
)
::
(
"list-style-image"
,
image
,
imp
)
::
unfold
tl
|
(
"list-style"
,
Concat
[
Ident
_
as
pos
;
Uri
_
as
image
]
,
imp
)
::
tl
->
(
"list-style-position"
,
pos
,
imp
)
::
(
"list-style-image"
,
image
,
imp
)
::
unfold
tl
|
(
"list-style"
,
Concat
[
ltype
;
Ident
_
as
pos
]
,
imp
)
::
tl
->
(
"list-style-type"
,
ltype
,
imp
)
::
(
"list-style-position"
,
pos
,
imp
)
::
unfold
tl
(* margin: top right bottom left
* | top right-left bottom
* | top-bottom right-left
* | top right bottom left
* | all
*)
|
((
"margin"
|
"padding"
)
as
base
,
value
,
imp
)
::
tl
->
let
(
top
,
right
,
bottom
,
left
)
=
match
value
with
|
Concat
[
top
;
right
;
bottom
;
left
]
->
(
top
,
right
,
bottom
,
left
)
|
Concat
[
top
;
right
;
bottom
]
->
(
top
,
right
,
bottom
,
right
)
|
Concat
[
top
;
right
]
->
(
top
,
right
,
top
,
right
)
|
_
->
(
value
,
value
,
value
,
value
)
in
let
make
dir
value
=
(
base
^
"-"
^
dir
,
value
,
imp
)
in
make
"top"
top
::
make
"right"
right
::
make
"bottom"
bottom
::
make
"left"
left
::
unfold
tl
|
hd
::
tl
->
hd
::
unfold
tl
let
make_shorthands
decls
=
(* unfold currently existing shorthands into separate properties for merging
* with override properties that are defined later on *)
let
decls
=
unfold
decls
in
(* find shorthand names for which properties are present *)
let
rec
find_props
=
function
|
[]
->
SS
.
empty
|
(
name
,
value
,
false
)
::
tl
when
Str
.
string_match
pattern
name
0
->
let
base
=
Str
.
matched_group
1
name
in
let
sub
=
Str
.
matched_group
2
name
in
if
List
.
mem
sub
(
subprops
base
)
if
List
.
mem
sub
(
order
base
)
then
SS
.
add
base
(
find_props
tl
)
else
find_props
tl
|
_
::
tl
->
find_props
tl
...
...
@@ -102,14 +257,13 @@ let make_shorthands decls =
(* filter out the original, partial properties, and append the shorthands *)
let
keep_prop
=
function
|
(
_
,
_
,
true
)
->
true
|
(
"line-height"
,
_
,
false
)
->
|
(
"line-height"
,
_
,
_
)
->
not
(
decls_mem
"font"
shorthands
)
|
(
name
,
_
,
false
)
->
|
(
name
,
_
,
_
)
->
not
(
Str
.
string_match
pattern
name
0
)
||
let
base
=
Str
.
matched_group
1
name
in
let
sub
=
Str
.
matched_group
2
name
in
not
(
List
.
mem
sub
(
subprops
base
))
||
not
(
decls_mem
base
shorthands
)
not
(
List
.
mem
sub
(
order
base
))
||
not
(
decls_mem
base
shorthands
)
in
List
.
filter
keep_prop
decls
@
shorthands
...
...
@@ -119,3 +273,10 @@ let transform = function
|
v
->
v
let
compress
=
Util
.
transform_stylesheet
transform
let
transform_unfold
=
function
|
Statement
(
Ruleset
(
selectors
,
decls
))
->
Statement
(
Ruleset
(
selectors
,
unfold
decls
))
|
v
->
v
let
unfold_stylesheet
=
Util
.
transform_stylesheet
transform_unfold
stringify.ml
View file @
34391515
...
...
@@ -46,12 +46,12 @@ let rec string_of_selector = function
|
Combinator
(
left
,
com
,
right
)
->
string_of_selector
left
^
" "
^
com
^
" "
^
string_of_selector
right
let
string_of_media_
feature
=
function
let
string_of_media_
expr
=
function
|
(
feature
,
None
)
->
"("
^
feature
^
")"
|
(
feature
,
Some
value
)
->
"("
^
feature
^
": "
^
string_of_expr
value
^
")"
let
string_of_media_query
=
let
features_str
=
cat
" and "
string_of_media_
feature
in
let
features_str
=
cat
" and "
string_of_media_
expr
in
function
|
(
None
,
None
,
[]
)
->
""
|
(
None
,
Some
mtype
,
[]
)
->
mtype
...
...
@@ -82,8 +82,16 @@ let stringify_condition w c =
in
str
(
transform
c
)
let
string_of_condition
=
stringify_condition
" "
let
block
=
function
""
->
" {}"
|
body
->
" {
\n
"
^
indent
body
^
"
\n
}"
let
string_of_descriptor_declaration
(
name
,
value
)
=
name
^
": "
^
string_of_expr
value
^
";"
let
string_of_keyframe_ruleset
(
expr
,
decls
)
=
string_of_expr
expr
^
block
(
cat
"
\n
"
string_of_declaration
decls
)
let
rec
string_of_statement
=
function
|
Ruleset
(
selectors
,
decls
)
->
cat
", "
string_of_selector
selectors
^
...
...
@@ -102,22 +110,16 @@ let rec string_of_statement = function
|
Page
(
Some
pseudo
,
decls
)
->
"@page :"
^
pseudo
^
block
(
cat
"
\n
"
string_of_declaration
decls
)
|
Font_face
decls
->
let
string_of_descriptor_declaration
(
name
,
value
)
=
name
^
": "
^
string_of_expr
value
^
";"
in
"@font-face"
^
block
(
cat
"
\n
"
string_of_descriptor_declaration
decls
)
|
Namespace
(
None
,
uri
)
->
"@namespace "
^
string_of_expr
uri
^
";"
|
Namespace
(
Some
prefix
,
uri
)
->
"@namespace "
^
prefix
^
" "
^
string_of_expr
uri
^
";"
|
Keyframes
(
prefix
,
id
,
rules
)
->
let
string_of_keyframe_ruleset
(
expr
,
decls
)
=
string_of_expr
expr
^
block
(
cat
"
\n
"
string_of_declaration
decls
)
in
"@"
^
prefix
^
"keyframes "
^
id
^
block
(
cat
"
\n\n
"
string_of_keyframe_ruleset
rules
)
|
Supports
(
condition
,
statements
)
->
"@supports "
^
string
ify_condition
" "
condition
^
"@supports "
^
string
_of_condition
condition
^
block
(
cat
"
\n\n
"
string_of_statement
statements
)
let
string_of_stylesheet
=
cat
"
\n\n
"
string_of_statement
...
...
@@ -189,3 +191,33 @@ let rec minify_statement = function
|
statement
->
string_of_statement
statement
let
minify_stylesheet
=
cat
""
minify_statement
(*
* Stringify any AST node in a box
*)
let
string_of_box
=
function
|
Expr
expr
->
string_of_expr
expr
|
Declaration
declaration
->
string_of_declaration
declaration
|
Selector
selector
->
string_of_selector
selector
|
Media_expr
media_expr
->
string_of_media_expr
media_expr
|
Media_query
media_query
->
string_of_media_query
media_query
|
Descriptor_declaration
descriptor_declaration
->
string_of_descriptor_declaration
descriptor_declaration
|
Keyframe_ruleset
keyframe_ruleset
->
string_of_keyframe_ruleset
keyframe_ruleset
|
Condition
condition
->
string_of_condition
condition
|
Statement
statement
->
string_of_statement
statement
|
Stylesheet
stylesheet
->
string_of_stylesheet
stylesheet
|
Clear
->
"<clear>"
|
_
->
raise
(
Invalid_argument
"box"
)
types.ml
View file @
34391515
...
...
@@ -72,3 +72,5 @@ type loc = string * int * int * int * int
exception
Syntax_error
of
string
exception
Loc_error
of
loc
*
string
exception
Box_error
of
box
*
string
util.ml
View file @
34391515
...
...
@@ -215,3 +215,7 @@ let transform_stylesheet f stylesheet =
and
TRAV_ALL
(
statement
,
Statement
)
in
trav_all_statement
stylesheet
(* Expression identification *)
let
is_color
=
Color_names
.
is_color
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment