From afbcc17d1279180db28a58044dca39b6e909c6b9 Mon Sep 17 00:00:00 2001 From: akianonymus Date: Sat, 25 Feb 2023 19:50:18 +0530 Subject: feat: Improve hsl parser follow https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hsl add support for deg, turn and all alpha values merge hsl and hsla into one parser less regex computation --- doc/colorizer.txt | 25 +++----- doc/index.html | 2 +- doc/modules/colorizer.buffer.html | 2 +- doc/modules/colorizer.color.html | 48 +++------------- doc/modules/colorizer.html | 2 +- doc/modules/colorizer.matcher.html | 2 +- doc/modules/colorizer.sass.html | 2 +- doc/modules/colorizer.tailwind.html | 2 +- doc/modules/colorizer.trie.html | 2 +- doc/modules/colorizer.utils.html | 2 +- lua/colorizer/color.lua | 111 ++++++++++++++++++++++-------------- lua/colorizer/matcher.lua | 8 ++- test/expectation.txt | 14 +++-- 13 files changed, 107 insertions(+), 115 deletions(-) diff --git a/doc/colorizer.txt b/doc/colorizer.txt index 0aaf865..1727fc4 100644 --- a/doc/colorizer.txt +++ b/doc/colorizer.txt @@ -387,9 +387,8 @@ Functions: ~ |hsl_to_rgb| - Converts an HSL color value to RGB. - |hsl_function_parser| - Parse for hsl() css function and return rgb hex. - - |hsla_function_parser| - Parse for hsl() css function and return rgb hex. + |hsl_function_parser| - Parse for hsl() hsla() css function and return rgb + hex. |hue_to_rgb| - Convert hsl colour values to rgb. @@ -434,28 +433,20 @@ hsl_to_rgb({h}, {s}, {l}) *colorizer.color.hsl_to_rgb* -hsl_function_parser({line}, {i}) *colorizer.color.hsl_function_parser* - Parse for hsl() css function and return rgb hex. - - Parameters: ~ - {line} - string: Line to parse - {i} - number: Index of line from where to start parsing - - returns:~ - number or nil: Index of line where the hsl function ended - string or nil: rgb hex value - +hsl_function_parser({line}, {i}, {opts}) *colorizer.color.hsl_function_parser* + Parse for hsl() hsla() css function and return rgb hex. + For more info: + https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hsl -hsla_function_parser({line}, {i}) *colorizer.color.hsla_function_parser* - Parse for hsl() css function and return rgb hex. Parameters: ~ {line} - string: Line to parse {i} - number: Index of line from where to start parsing + {opts} - table: Values passed from matchers like prefix returns:~ - number or nil: Index of line where the hsla function ended + number or nil: Index of line where the hsla/hsl function ended string or nil: rgb hex value diff --git a/doc/index.html b/doc/index.html index 0db74d8..7735382 100644 --- a/doc/index.html +++ b/doc/index.html @@ -87,7 +87,7 @@
generated by LDoc 1.4.6 -Last updated - September +Last updated - February
diff --git a/doc/modules/colorizer.buffer.html b/doc/modules/colorizer.buffer.html index fc0888e..6bce06a 100644 --- a/doc/modules/colorizer.buffer.html +++ b/doc/modules/colorizer.buffer.html @@ -333,7 +333,7 @@
generated by LDoc 1.4.6 -Last updated - September +Last updated - February
diff --git a/doc/modules/colorizer.color.html b/doc/modules/colorizer.color.html index 74d4e55..751214c 100644 --- a/doc/modules/colorizer.color.html +++ b/doc/modules/colorizer.color.html @@ -70,12 +70,8 @@ Converts an HSL color value to RGB. - hsl_function_parser (line, i) - Parse for hsl() css function and return rgb hex. - - - hsla_function_parser (line, i) - Parse for hsl() css function and return rgb hex. + hsl_function_parser (line, i, opts) + Parse for hsl() hsla() css function and return rgb hex. hue_to_rgb (p, q, t) @@ -174,10 +170,11 @@
- hsl_function_parser (line, i) + hsl_function_parser (line, i, opts)
- Parse for hsl() css function and return rgb hex. + Parse for hsl() hsla() css function and return rgb hex. + For more info: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hsl

Parameters:

@@ -188,42 +185,15 @@
  • i number: Index of line from where to start parsing
  • - - -

    Returns:

    -
      -
    1. - number|nil: Index of line where the hsl function ended
    2. -
    3. - string|nil: rgb hex value
    4. -
    - - - - -
    -
    - - hsla_function_parser (line, i) -
    -
    - Parse for hsl() css function and return rgb hex. - - -

    Parameters:

    -

    Returns:

    1. - number|nil: Index of line where the hsla function ended
    2. + number|nil: Index of line where the hsla/hsl function ended
    3. string|nil: rgb hex value
    @@ -424,7 +394,7 @@
    generated by LDoc 1.4.6 -Last updated - September +Last updated - February
    diff --git a/doc/modules/colorizer.html b/doc/modules/colorizer.html index 9e56230..e9fcd62 100644 --- a/doc/modules/colorizer.html +++ b/doc/modules/colorizer.html @@ -490,7 +490,7 @@ Setup an autocmd which enables colorizing for the filetypes and options specifie
    generated by LDoc 1.4.6 -Last updated - September +Last updated - February
    diff --git a/doc/modules/colorizer.matcher.html b/doc/modules/colorizer.matcher.html index dd142eb..3034bb2 100644 --- a/doc/modules/colorizer.matcher.html +++ b/doc/modules/colorizer.matcher.html @@ -140,7 +140,7 @@ Do not try make the function again if it is present in the cache
    generated by LDoc 1.4.6 -Last updated - September +Last updated - February
    diff --git a/doc/modules/colorizer.sass.html b/doc/modules/colorizer.sass.html index dc4f6f4..cf0d133 100644 --- a/doc/modules/colorizer.sass.html +++ b/doc/modules/colorizer.sass.html @@ -182,7 +182,7 @@
    generated by LDoc 1.4.6 -Last updated - September +Last updated - February
    diff --git a/doc/modules/colorizer.tailwind.html b/doc/modules/colorizer.tailwind.html index c6048ac..346a21a 100644 --- a/doc/modules/colorizer.tailwind.html +++ b/doc/modules/colorizer.tailwind.html @@ -136,7 +136,7 @@
    generated by LDoc 1.4.6 -Last updated - September +Last updated - February
    diff --git a/doc/modules/colorizer.trie.html b/doc/modules/colorizer.trie.html index f2bbd89..9071219 100644 --- a/doc/modules/colorizer.trie.html +++ b/doc/modules/colorizer.trie.html @@ -64,7 +64,7 @@
    generated by LDoc 1.4.6 -Last updated - September +Last updated - February
    diff --git a/doc/modules/colorizer.utils.html b/doc/modules/colorizer.utils.html index a787177..d6a0216 100644 --- a/doc/modules/colorizer.utils.html +++ b/doc/modules/colorizer.utils.html @@ -319,7 +319,7 @@
    generated by LDoc 1.4.6 -Last updated - September +Last updated - February
    diff --git a/lua/colorizer/color.lua b/lua/colorizer/color.lua index 9cfac2a..37f8f30 100644 --- a/lua/colorizer/color.lua +++ b/lua/colorizer/color.lua @@ -86,76 +86,99 @@ function color.hsl_to_rgb(h, s, l) 255 * color.hue_to_rgb(p, q, h - 1 / 3) end +local CSS_HSLA_FN_MINIMUM_LENGTH = #"hsla(0,0%,0%)" - 1 local CSS_HSL_FN_MINIMUM_LENGTH = #"hsl(0,0%,0%)" - 1 ----Parse for hsl() css function and return rgb hex. +---Parse for hsl() hsla() css function and return rgb hex. +-- For more info: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hsl ---@param line string: Line to parse ---@param i number: Index of line from where to start parsing ----@return number|nil: Index of line where the hsl function ended +---@param opts table: Values passed from matchers like prefix +---@return number|nil: Index of line where the hsla/hsl function ended ---@return string|nil: rgb hex value -function color.hsl_function_parser(line, i) - if #line < i + CSS_HSL_FN_MINIMUM_LENGTH then - return - end - local h, s, l, match_end = line:sub(i):match "^hsl%(%s*(%d+)%s*,%s*(%d+)%%%s*,%s*(%d+)%%%s*%)()" - if not match_end then - h, s, l, match_end = line:sub(i):match "^hsl%(%s*(%d+)%s+(%d+)%%%s+(%d+)%%%s*%)()" - if not match_end then - return - end +function color.hsl_function_parser(line, i, opts) + local min_len = CSS_HSLA_FN_MINIMUM_LENGTH + local min_commas, min_spaces = 2, 2 + local pattern = "^" + .. opts.prefix + .. "%(%s*([.%d]+)([deg]*)([turn]*)(,?)(%s?)%s*(%d+)%%(,?)(%s?)%s*(%d+)%%%s*(/?,?)%s*([.%d]*)([%%]?)%s*%)()" + + if opts.prefix == "hsl" then + min_len = CSS_HSL_FN_MINIMUM_LENGTH end - h = tonumber(h) - if h > 360 then + + if #line < i + min_len then return end - s = tonumber(s) - if s > 100 then + + local h, deg, turn, csep1, ssep1, s, csep2, ssep2, l, sep3, a, percent_sign, match_end = line:sub(i):match(pattern) + if not match_end then return end - l = tonumber(l) - if l > 100 then - return + if a == "" then + a = nil + else + min_commas = min_commas + 1 end - local r, g, b = color.hsl_to_rgb(h / 360, s / 100, l / 100) - if r == nil or g == nil or b == nil then + + -- the text after hue should be either deg or empty + if not ((deg == "") or (deg == "deg") or (turn == "turn")) then return end - local rgb_hex = string.format("%02x%02x%02x", r, g, b) - return match_end - 1, rgb_hex -end -local CSS_HSLA_FN_MINIMUM_LENGTH = #"hsla(0,0%,0%,0)" - 1 ----Parse for hsl() css function and return rgb hex. ----@param line string: Line to parse ----@param i number: Index of line from where to start parsing ----@return number|nil: Index of line where the hsla function ended ----@return string|nil: rgb hex value -function color.hsla_function_parser(line, i) - if #line < i + CSS_HSLA_FN_MINIMUM_LENGTH then + local c_seps = ("%s%s%s"):format(csep1, csep2, sep3) + local s_seps = ("%s%s"):format(ssep1, ssep2) + -- comma separator syntax + if c_seps:match "," then + if not (#c_seps:match ",*" == min_commas) then + return + end + -- space separator syntax with decimal or percentage alpha + elseif #s_seps:match "%s*" >= min_spaces then + if a then + if not (c_seps == "/") then + return + end + end + else return end - local h, s, l, a, match_end = line:sub(i):match "^hsla%(%s*(%d+)%s*,%s*(%d+)%%%s*,%s*(%d+)%%%s*,%s*([.%d]+)%s*%)()" - if not match_end then - h, s, l, a, match_end = line:sub(i):match "^hsla%(%s*(%d+)%s+(%d+)%%%s+(%d+)%%%s+([.%d]+)%s*%)()" - if not match_end then - return + + if not a then + a = 1 + else + a = tonumber(a) + -- if percentage, then convert to decimal + if percent_sign == "%" then + a = a / 100 + end + -- although alpha doesn't support larger values than 1, css anyways renders it at 1 + if a > 1 then + a = 1 end end - a = tonumber(a) - if not a or a > 1 then - return + + h = tonumber(h) or 1 + -- single turn is 360 + if turn == "turn" then + h = 360 * h end - h = tonumber(h) + + -- if hue angle if greater than 360, then calculate the hue within 360 if h > 360 then - return + local turns = h / 360 + h = 360 * (turns - floor(turns)) end + + -- if saturation or luminance percentage is greater than 100 then reset it to 100 s = tonumber(s) if s > 100 then - return + s = 100 end l = tonumber(l) if l > 100 then - return + l = 100 end + local r, g, b = color.hsl_to_rgb(h / 360, s / 100, l / 100) if r == nil or g == nil or b == nil then return diff --git a/lua/colorizer/matcher.lua b/lua/colorizer/matcher.lua index dba67c0..d55a673 100644 --- a/lua/colorizer/matcher.lua +++ b/lua/colorizer/matcher.lua @@ -17,7 +17,7 @@ local parser = { ["_rgb"] = color.rgb_function_parser, ["_rgba"] = color.rgba_function_parser, ["_hsl"] = color.hsl_function_parser, - ["_hsla"] = color.hsla_function_parser, + ["_hsla"] = color.hsl_function_parser, } local matcher = {} @@ -49,7 +49,7 @@ function matcher.compile(matchers, matchers_trie) if prefix then local fn = "_" .. prefix if parser[fn] then - return parser[fn](line, i, matchers[fn]) + return parser[fn](line, i, matchers[prefix]) end end @@ -145,6 +145,10 @@ function matcher.make(options) table.insert(matchers_prefix, "hsl") end + for _, value in ipairs(matchers_prefix) do + matchers[value] = { prefix = value } + end + loop_parse_fn = matcher.compile(matchers, matchers_prefix) MATCHER_CACHE[matcher_key] = loop_parse_fn diff --git a/test/expectation.txt b/test/expectation.txt index d04bf92..37472e0 100644 --- a/test/expectation.txt +++ b/test/expectation.txt @@ -20,8 +20,11 @@ White rgb(0,0,0) rgb(10, 100 , 100) rgba(200,30,0,1) rgba(200,30,0,0.5) -hsl(300,50%,50%) hsla(300,50%,50%,0.5) -hsla(300,50%,50%,1.0000000000000001) +hsl(300 50% 50%) hsl(300 50% 50% / 1) hsl(100 80% 50% / 0.4) +hsl(990 80% 50% / 0.4) hsl(720 80% 50% / 0.4) +hsl(1turn 80% 50% / 0.4) hsl(0.4turn 80% 50% / 0.4) hsl(1.4turn 80% 50% / 0.4) +hsla(300 50% 50%) hsla(300 50% 50% / 1) +hsla(300 50% 50% / 0.4) hsla(300,50%,50%,05) hsla(360,50%,50%,1.0000000000000001) ]] @@ -37,9 +40,10 @@ Blueberry Gray1000 BlueGree BlueGray matcher#add rgb(10,256,100) rgb (10,255,100) -rgb(10, 1 00 , 100) -hsla(300,50%,50%,05) -hsla(300,50%,50%,1.000000000000001) +rgb(10, 1 00 , 100) +hsl(300 50% 50% 1) +hsl(300 50% 50 / 1) +hsla(10 10% 10% 1) hsla(300,50%,50,1.0000000000000001) hsla(300,50,50,1.0000000000000001) hsla(361,50,50,1.0000000000000001) -- cgit v1.2.3-70-g09d2