--- /dev/null
+USING: tools.test ;
+
+IN: colors.flex-hex
+
+{ "00b000" } [ "#zqbttv" flex-hex ] unit-test
+
+{ "0f0000" } [ "f" flex-hex ] unit-test
+{ "000f00" } [ "0f" flex-hex ] unit-test
+{ "000f00" } [ "0f0" flex-hex ] unit-test
+{ "0f0f00" } [ "0f0f" flex-hex ] unit-test
+{ "0ff000" } [ "0f0f0f0" flex-hex ] unit-test
+
+{ "ad0e0e" } [ "adamlevine" flex-hex ] unit-test
+{ "000000" } [ "MrT" flex-hex ] unit-test
+{ "00c000" } [ "sick" flex-hex ] unit-test
+{ "c0a000" } [ "crap" flex-hex ] unit-test
+{ "c00000" } [ "chucknorris" flex-hex ] unit-test
+
+{ "6ecde0" } [
+ "6db6ec49efd278cd0bc92d1e5e072d68" flex-hex
+] unit-test
--- /dev/null
+! Copyright (C) 2013 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: colors colors.hex grouping kernel lexer math math.parser
+regexp.classes sequences splitting ;
+
+IN: colors.flex-hex
+
+<PRIVATE
+
+: hex-only ( str -- str' )
+ [ dup hex-digit? [ drop CHAR: 0 ] unless ] map ;
+
+: pad-length ( str -- n )
+ length dup 3 mod [ 3 swap - + ] unless-zero ;
+
+: three-groups ( str -- array )
+ dup pad-length [ CHAR: 0 pad-tail ] [ 3 / group ] bi ;
+
+: hex-rgb ( array -- array' )
+ [
+ 8 short tail*
+ 2 short head
+ 2 CHAR: 0 pad-head
+ ] map ;
+
+PRIVATE>
+
+: flex-hex ( str -- hex )
+ "#" ?head drop hex-only three-groups hex-rgb "" join ;
+
+: flex-hex>rgba ( str -- rgba )
+ flex-hex hex>rgba ;
+
+SYNTAX: FLEXHEXCOLOR: scan-token flex-hex>rgba suffix! ;