Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: 3.11
- name: Install dependencies
run: |
python -m pip install --upgrade pip setuptools tox
python -m pip install --upgrade pip setuptools tox build
- name: Tests
run: |
python -m tox
Expand All @@ -39,19 +39,19 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: 3.11
- name: Setup Node
uses: actions/setup-node@v1
with:
node-version: '14'
node-version: '22'
- name: Install dependencies
run: |
python -m pip install --upgrade pip setuptools tox
npm install -g jshint
python -m pip install --upgrade pip setuptools tox build
- name: Lint
run: |
python -m tox
Expand All @@ -65,14 +65,14 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: 3.11
- name: Install dependencies
run: |
python -m pip install --upgrade pip setuptools tox
python -m pip install --upgrade pip setuptools tox build
- name: Install Aspell
run: |
sudo apt-get install aspell aspell-en
Expand Down
4 changes: 3 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# ExportHtml

## 2.17.5
## 2.18.0

- **NEW**: New colorblind filters.
- **CHORE**: Updates to support newer dependencies.
- **FIX**: Remove unnecessary dependencies.
- **FIX**: Fix typo in settings configuration.

Expand Down
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

ExportHtml is released under the MIT license.

Copyright (c) 2012 - 2023 Isaac Muse <isaacmuse@gmail.com>
Copyright (c) 2012 - 2025 Isaac Muse <isaacmuse@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

Expand Down
7 changes: 3 additions & 4 deletions lib/color_scheme_matcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
import codecs
import re
from .file_strip.json import sanitize_json
from .st_colormod import Color
from .tmtheme import ColorSRGBX11
from mdpopups.st_colormod import Color
from os import path
from collections import namedtuple
from plistlib import readPlistFromBytes
Expand Down Expand Up @@ -77,14 +77,13 @@ class SchemeColors(
[
'fg', 'fg_simulated', 'bg', "bg_simulated", "style", "color_gradient",
"fg_selector", "bg_selector", "style_selectors", "color_gradient_selector"
],
verbose=False
]
)
):
"""Scheme colors."""


class SchemeSelectors(namedtuple('SchemeSelectors', ['name', 'scope'], verbose=False)):
class SchemeSelectors(namedtuple('SchemeSelectors', ['name', 'scope'])):
"""Scheme selectors."""


Expand Down
98 changes: 58 additions & 40 deletions lib/color_scheme_tweaker.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
"""
from __future__ import absolute_import
import sublime
from .st_colormod import Color
from mdpopups.coloraide import util
from mdpopups.st_colormod import Color
from mdpopups.coloraide import algebra as alg
import re

NEW_SCHEMES = int(sublime.version()) >= 3150
Expand All @@ -18,7 +18,7 @@
r'''(?x)
^(?:
(brightness|saturation|hue|contrast|colorize|glow)\((-?[\d]+|[\d]*\.[\d]+)\)|
(sepia|grayscale|invert)
(sepia|grayscale|invert|protan|deutan|tritan)
)
(?:@(fg|bg))?$
'''
Expand Down Expand Up @@ -107,60 +107,78 @@ def hue(color, deg):
def contrast(color, factor):
"""Adjust contrast."""

r, g, b = [util.round_half_up(util.clamp(c * 255, 0, 255)) for c in util.no_nan(color.coords())]
r, g, b = [alg.round_half_up(alg.clamp(c * 255, 0, 255)) for c in alg.no_nans(color[:-1])]
# Algorithm can't handle any thing beyond +/-255 (or a factor from 0 - 2)
# Convert factor between (-255, 255)
f = (util.clamp(factor, 0.0, 2.0) - 1.0) * 255.0
f = (alg.clamp(factor, 0.0, 2.0) - 1.0) * 255.0
f = (259 * (f + 255)) / (255 * (259 - f))

# Increase/decrease contrast accordingly.
r = util.clamp(util.round_half_up((f * (r - 128)) + 128), 0, 255)
g = util.clamp(util.round_half_up((f * (g - 128)) + 128), 0, 255)
b = util.clamp(util.round_half_up((f * (b - 128)) + 128), 0, 255)
color.red = r / 255
color.green = g / 255
color.blue = b / 255
r = alg.clamp(alg.round_half_up((f * (r - 128)) + 128), 0, 255)
g = alg.clamp(alg.round_half_up((f * (g - 128)) + 128), 0, 255)
b = alg.clamp(alg.round_half_up((f * (b - 128)) + 128), 0, 255)
color['red'] = r / 255
color['green'] = g / 255
color['blue'] = b / 255

@staticmethod
def protan(color):
"""Invert the color."""

color.filter('protan', in_place=True)

@staticmethod
def deutan(color):
"""Invert the color."""

color.filter('deutan', in_place=True)

@staticmethod
def tritan(color):
"""Invert the color."""

color.filter('tritan', in_place=True)

@staticmethod
def invert(color):
"""Invert the color."""

r, g, b = [int(util.round_half_up(util.clamp(c * 255, 0, 255))) for c in util.no_nan(color.coords())]
r, g, b = [int(alg.round_half_up(alg.clamp(c * 255, 0, 255))) for c in alg.no_nans(color[:-1])]
r ^= 0xFF
g ^= 0xFF
b ^= 0xFF
color.red = r / 255
color.green = g / 255
color.blue = b / 255
color['red'] = r / 255
color['green'] = g / 255
color['blue'] = b / 255

@staticmethod
def saturation(color, factor):
"""Saturate or unsaturate the color by the given factor."""

s = util.no_nan(color.get('hsl.saturation')) / 100.0
s = util.clamp(s + factor - 1.0, 0.0, 1.0)
s = alg.no_nan(color.get('hsl.saturation')) / 100.0
s = alg.clamp(s + factor - 1.0, 0.0, 1.0)
color.set('hsl.saturation', s * 100)

@staticmethod
def grayscale(color):
"""Convert the color with a grayscale filter."""

luminance = color.luminance()
color.red = luminance
color.green = luminance
color.blue = luminance
color['red'] = luminance
color['green'] = luminance
color['blue'] = luminance

@staticmethod
def sepia(color):
"""Apply a sepia filter to the color."""

red, green, blue = util.no_nan(color.coords())
r = util.clamp((red * .393) + (green * .769) + (blue * .189), 0, 1)
g = util.clamp((red * .349) + (green * .686) + (blue * .168), 0, 1)
b = util.clamp((red * .272) + (green * .534) + (blue * .131), 0, 1)
color.red = r
color.green = g
color.blue = b
red, green, blue = alg.no_nans(color[:-1])
r = alg.clamp((red * .393) + (green * .769) + (blue * .189), 0, 1)
g = alg.clamp((red * .349) + (green * .686) + (blue * .168), 0, 1)
b = alg.clamp((red * .272) + (green * .534) + (blue * .131), 0, 1)
color['red'] = r
color['green'] = g
color['blue'] = b

@staticmethod
def _get_overage(c):
Expand Down Expand Up @@ -206,9 +224,9 @@ def brightness(cls, color, factor):
Brightness is determined by perceived luminance.
"""

red, green, blue = [util.round_half_up(util.clamp(c * 255, 0, 255)) for c in util.no_nan(color.coords())]
red, green, blue = [alg.round_half_up(alg.clamp(c * 255, 0, 255)) for c in alg.no_nans(color[:-1])]
channels = ["r", "g", "b"]
total_lumes = util.clamp(util.clamp(color.luminance(), 0, 1) * 255 + (255.0 * factor) - 255.0, 0.0, 255.0)
total_lumes = alg.clamp(alg.clamp(color.luminance(), 0, 1) * 255 + (255.0 * factor) - 255.0, 0.0, 255.0)

if total_lumes == 255.0:
# white
Expand All @@ -218,7 +236,7 @@ def brightness(cls, color, factor):
r, g, b = 0, 0, 0
else:
# Adjust Brightness
pts = (total_lumes - util.clamp(color.luminance(), 0, 1) * 255)
pts = (total_lumes - alg.clamp(color.luminance(), 0, 1) * 255)
slots = set(channels)
components = [float(red) + pts, float(green) + pts, float(blue) + pts]
count = 0
Expand All @@ -229,12 +247,12 @@ def brightness(cls, color, factor):
components = list(cls._distribute_overage(components, overage, slots))
count += 1

r = util.clamp(util.round_half_up(components[0]), 0, 255) / 255.0
g = util.clamp(util.round_half_up(components[1]), 0, 255) / 255.0
b = util.clamp(util.round_half_up(components[2]), 0, 255) / 255.0
color.red = r
color.green = g
color.blue = b
r = alg.clamp(alg.round_half_up(components[0]), 0, 255) / 255.0
g = alg.clamp(alg.round_half_up(components[1]), 0, 255) / 255.0
b = alg.clamp(alg.round_half_up(components[2]), 0, 255) / 255.0
color['red'] = r
color['green'] = g
color['blue'] = b


class ColorTweaker(object):
Expand Down Expand Up @@ -292,7 +310,7 @@ def _filter_colors(self, *args, **kwargs):
name = f[0]
value = f[1]
context = f[2]
if name in ("grayscale", "sepia", "invert"):
if name in ("grayscale", "sepia", "invert", "tritan", "protan", "deutan"):
if context != "bg":
self._apply_filter(rgba_fg, name)
if context != "fg":
Expand Down Expand Up @@ -358,7 +376,7 @@ def get_filters(self):

filters = []
for f in self.filters:
if f[0] in ("invert", "grayscale", "sepia"):
if f[0] in ("invert", "grayscale", "sepia", "tritan", "protan", "deutan"):
filters.append(f[0])
elif f[0] in ("hue", "colorize"):
filters.append(f[0] + "(%d)" % int(f[1]))
Expand Down Expand Up @@ -416,7 +434,7 @@ def _filter_colors(self, *args, **kwargs):
name = f[0]
value = f[1]
context = f[2]
if name in ("grayscale", "sepia", "invert"):
if name in ("grayscale", "sepia", "invert", "tritan", "protan", "deutan"):
if context != "bg":
self._apply_filter(rgba_fg, name)
if context != "fg":
Expand Down Expand Up @@ -516,7 +534,7 @@ def get_filters(self):

filters = []
for f in self.filters:
if f[0] in ("invert", "grayscale", "sepia"):
if f[0] in ("invert", "grayscale", "sepia", "tritan", "protan", "deutan"):
filters.append(f[0])
elif f[0] in ("hue", "colorize"):
filters.append(f[0] + "(%d)" % int(f[1]))
Expand Down
1 change: 1 addition & 0 deletions lib/file_strip/json.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# noqa: A005
"""
File Strip.

Expand Down
Loading