feat: added palettes generator script, some rust samples and wcag-compliace tests

pull/1/head
Pocco81 2 years ago
parent 86248b77f1
commit 4285b456a5

1
.gitignore vendored

@ -0,0 +1 @@
node_modules/

@ -0,0 +1,263 @@
#!/bin/bash
# ---- sys
NC=" \033[0m"
coerce=false
lowercase=false
file=""
prefix=""
original_palette="storm"
verbosity=0
script_help=$(
cat <<EOF
Generate missing Catppuccin palettes from a base file (e.g. generate a dawn.conf & a dusk.conf from a storm.conf file)
Usages:
#0: $(basename "$0") <flag> [arg]
Flags:
-f, --file specify file (mandatory)
-v, --verbose increase verbosity by 1
-o, --original-palette the palette used in the based file (given by --file)
-l, --lowercase replaces with lowercased hex codes
-c, --coerce force the creation of new palette files (useful when those files already exist)
-p, --prefix specify which prefix to use for the hex codes. Surround it with double quotes if needed.
-h, --help see this message
EOF
)
palette_names=(
storm
dusk
dawn
)
declare -A dusk=(
[white]='C6D0F5'
[peach]='FAB387'
[gray2]='ADB5D8'
[black0]='101019'
[black1]='181825'
[gray1]='959BBA'
[blue]='90C1FB'
[green]='A6E3A1'
[sapphire]='74C7EC'
[black3]='323044'
[black4]='4B4B62'
[black5]='63657F'
[teal]='94E2D5'
[gray0]='7C809D'
[rosewater]='F5E0DC'
[maroon]='EBA0AC'
[lavender]='C9CBFF'
[yellow]='F9E2AF'
[flamingo]='F2CDCD'
[sky]='89DCEB'
[mauve]='CBA6F7'
[black2]='1E1E2E'
[pink]='F5C2E7'
[red]='F38BA8'
)
declare -A storm=(
[white]='C5CFF5'
[sapphire]='34C3DC'
[pink]='F5BFE7'
[rosewater]='F5DFDA'
[black2]='24273A'
[flamingo]='F2CBCB'
[red]='F67E98'
[maroon]='F1949B'
[peach]='FEA571'
[black1]='1F2233'
[sky]='89DCFD'
[gray1]='8289AA'
[lavender]='C2CBFE'
[black3]='2B3045'
[green]='A1DF8E'
[black4]='3E435E'
[yellow]='F1D8A4'
[gray2]='A6AFD2'
[blue]='83ABF9'
[black0]='1A1B26'
[gray0]='5F6587'
[teal]='85E0D1'
[black5]='4F5473'
[mauve]='C59FF6'
)
declare -A dawn=(
[black4]='CCC9D1'
[peach]='FE6811'
[black3]='E6E3E5'
[pink]='EC83D0'
[black0]='D3D0D2'
[black1]='EDEDED'
[blue]='1D65F5'
[lavender]='7287FD'
[mauve]='8F46EF'
[black5]='B5B1BF'
[maroon]='E63B4A'
[rosewater]='E5AC9F'
[green]='509E31'
[gray1]='86819C'
[black2]='FBF8F4'
[white]='575279'
[gray2]='6E6A8B'
[sky]='04A5E5'
[sapphire]='209FB5'
[red]='D20F39'
[teal]='289886'
[gray0]='9D99AE'
[flamingo]='DF7F7F'
[yellow]='E49320'
)
function prompt() {
local type=${1} # error, success, warning, info
local message=${2}
local modifiers=${3}
if [[ $1 == "-i" || $1 == "--info" ]]; then
type=""
fi
case ${type} in
"-e" | "--error")
printf "\033[0;31m${modifiers}ERROR: %s${NC}\n" "${message}"
;;
"-s" | "--success")
printf "\033[0;32m${modifiers}SUCCESS: %s${NC}\n" "${message}"
;;
"-w" | "--warning")
printf "\033[0;33m${modifiers}WARNING: %s${NC}\n" "${message}"
;;
*)
printf "\033[0;34m${modifiers}INFO: %s${NC}\n" "${message}"
;;
esac
}
function verbose_print() {
# $1 = message
# $2 = modifiers
if [[ $verbosity -gt 0 ]]; then
printf "\033[3;29m${2}%s${NC}\n" "${1}"
fi
}
function generate_palettes() {
capitalization_char='\U' # uppercase
[[ $lowercase == true ]] && {
capitalization_char='\L' # lowercase
}
new_array=()
for val in "${palette_names[@]}"; do
[[ "$val" != "$original_palette" ]] && new_array+=("$val")
done
palette_names=("${new_array[@]}")
unset new_array
for palette in "${palette_names[@]}"; do
printf " GENERATING: \033[3;32m%s${NC}\n" "$palette"
local dest_file="${palette}.${file##*.}"
prompt -w "creating $dest_file..." "\t• "
if [[ -f $dest_file ]]; then
if [[ ! $coerce == true ]]; then
prompt -e "file '$dest_file' already exists. Use --coerce to force it's replacement" "\t• "
exit 1
fi
fi
cp "$file" "$dest_file"
prompt -i "replacing colors..." "\t• "
for clr in "${!storm[@]}"; do
local curr_color=$(eval "echo \${${original_palette}[$clr]}")
local dest_color=$(eval "echo \${${palette}[${clr}]}")
verbose_print "modifying ${clr}" "\t + "
sed -i "s/${curr_color}/${prefix}${capitalization_char}${dest_color}/gI" "$dest_file"
done
done
}
function detect_original_palette() {
prompt -w "detecting palette..."
original_palette=""
for palette in "${palette_names[@]}"; do
for clr in "${!storm[@]}"; do
if grep -q $(eval "echo \${${palette}[${clr}]}") "$file"; then
original_palette=$palette
break 2
fi
done
done
if [[ $original_palette == "" ]]; then
prompt -e "couldn't detect the original palette"
exit 1
else
prompt -s "detected '$original_palette'"
fi
}
main() {
if [[ ! "$#" -gt 0 ]]; then
prompt -e "you must provide at least the file you want to generate the missing palettes from"
else
local help_used=false
while [ "$1" != "" ]; do
case $1 in
-v | --verbose)
verbosity=$((verbosity + 1))
;;
-f | --file)
file=$2
shift
;;
-o | --original-palette)
origianl_palette=$2
shift
;;
-l | --lowercase)
lowercase=true
;;
-c | --coerce)
coerce=true
;;
-p | --prefix)
prefix=$2
shift
;;
-h | --help)
help_used=true
echo "$script_help"
;;
*)
echo "ERROR: command ($1) not recognized"
;;
esac
shift
done
if [[ $help_used != "true" ]]; then
if [[ $file != "" ]]; then
[[ -f $file ]] && {
prompt "updating colors..."
if [[ original_palette != "storm" || original_palette != "dusk" || original_palette != "dawn" ]]; then
detect_original_palette
fi
generate_palettes
} || prompt -e "file ${1} does not exist"
else
prompt -e "please profive a file to use a base using the --file flag"
fi
fi
fi
}
main "$@"

@ -0,0 +1,131 @@
/* See LICENSE file for copyright and license details. */
/* appearance */
static const unsigned int borderpx = 1; /* border pixel of windows */
static const unsigned int snap = 32; /* snap pixel */
static const int showbar = 1; /* 0 means no bar */
static const int topbar = 1; /* 0 means bottom bar */
static const char *fonts[] = { "monospace:size=10" };
static const char dmenufont[] = "monospace:size=10";
static const char col_gray1[] = "#5F6587";
static const char col_gray2[] = "#8289AA";
static const char col_gray3[] = "#A6AFD2";
static const char col_gray4[] = "#C5CFF5";
static const char col_teal[] = "#78DCCC";
static const char *colors[][3] = {
/* fg bg border */
[SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
[SchemeSel] = { col_gray4, col_teal, col_teal },
};
/* tagging */
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
static const Rule rules[] = {
/* xprop(1):
* WM_CLASS(STRING) = instance, class
* WM_NAME(STRING) = title
*/
/* class instance title tags mask isfloating monitor */
{ "Gimp", NULL, NULL, 0, 1, -1 },
{ "Firefox", NULL, NULL, 1 << 8, 0, -1 },
};
static const int ruleperiod = 5; /* number of seconds before rules are ignored */
/* layout(s) */
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
static const int nmaster = 1; /* number of clients in master area */
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
static const LayoutMonitorRule lm_rules[] = {
/* >=w, >=h, req'd layout, new nmaster, new mfact */
{ 3000, 0, 0, 2, 0.66 },
};
static const Layout layouts[] = {
/* symbol arrange function */
{ "[]=", tile }, /* first entry is default */
{ "><>", NULL }, /* no layout function means floating behavior */
{ "[M]", monocle },
{ "TTT", bstack },
{ "===", bstackhoriz },
};
/* key definitions */
#define MODKEY Mod1Mask
#define TAGKEYS(KEY,TAG) \
{ KeyPress, MODKEY, KEY, view, {.ui = 1 << TAG} }, \
{ KeyPress, MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
{ KeyPress, MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
{ KeyPress, MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
/* commands */
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_teal, "-sf", col_gray4, NULL };
static const char *termcmd[] = { "st", NULL };
#include "movestack.c"
static Key keys[] = {
/* modifier key function argument */
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
{ MODKEY, XK_b, togglebar, {0} },
{ MODKEY, XK_j, focusstack, {.i = +1 } },
{ MODKEY, XK_k, focusstack, {.i = -1 } },
{ MODKEY, XK_i, incnmaster, {.i = +1 } },
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
{ MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } },
{ MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } },
{ MODKEY, XK_Return, zoom, {0} },
{ MODKEY, XK_Tab, view, {0} },
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
{ MODKEY|ShiftMask, XK_x, killunsel, {0} },
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
{ MODKEY, XK_u, setlayout, {.v = &layouts[3]} },
{ MODKEY, XK_o, setlayout, {.v = &layouts[4]} },
{ MODKEY, XK_space, setlayout, {0} },
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
{ MODKEY, XK_0, view, {.ui = ~0 } },
{ MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
{ MODKEY, XK_comma, focusmon, {.i = -1 } },
{ MODKEY, XK_period, focusmon, {.i = +1 } },
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
{ MODKEY|ControlMask, XK_comma, tagallmon, {.i = -1 } },
{ MODKEY|ControlMask, XK_period, tagallmon, {.i = +1 } },
TAGKEYS( XK_1, 0)
TAGKEYS( XK_2, 1)
TAGKEYS( XK_3, 2)
TAGKEYS( XK_4, 3)
TAGKEYS( XK_5, 4)
TAGKEYS( XK_6, 5)
TAGKEYS( XK_7, 6)
TAGKEYS( XK_8, 7)
TAGKEYS( XK_9, 8)
{ KeyPress, MODKEY|ShiftMask, XK_q, quit, {0} },
};
/* button definitions */
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
static Button buttons[] = {
/* click event mask button function argument */
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
{ ClkWinTitle, 0, Button2, zoom, {0} },
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
{ ClkTagBar, 0, Button1, view, {0} },
{ ClkTagBar, 0, Button3, toggleview, {0} },
{ ClkTagBar, MODKEY, Button1, tag, {0} },
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
};

@ -1,5 +1,3 @@
// Simple program made by a simple programmer
#![warn(rust_2018_idioms)] #![warn(rust_2018_idioms)]
#![allow(elided_lifetimes_in_paths)] #![allow(elided_lifetimes_in_paths)]

@ -0,0 +1,961 @@
use crate::context::DrawContext;
use crate::controller::Controller;
use crate::font::FontCache;
use crate::scene::*;
use crate::wayland::*;
use crate::*;
use smithay_client_toolkit::reexports::calloop::{EventLoop, LoopHandle, RegistrationToken};
use smithay_client_toolkit::seat::keyboard::ModifiersState;
use smithay_client_toolkit::shm::AutoMemPool;
use smithay_client_toolkit::WaylandSource;
use std::cell::RefCell;
use std::ops::{Deref, DerefMut};
use std::rc::Rc;
use smithay_client_toolkit::reexports::client::{
global_filter,
protocol::wl_buffer::WlBuffer,
protocol::wl_callback,
protocol::wl_compositor::WlCompositor,
protocol::wl_output::{self, WlOutput},
protocol::wl_pointer::{self, WlPointer},
protocol::wl_region::WlRegion,
protocol::wl_seat::{self, Capability, WlSeat},
protocol::wl_shm::WlShm,
protocol::wl_surface::WlSurface,
Attached, Display, GlobalError, GlobalManager, Interface, Main, Proxy,
};
use smithay_client_toolkit::reexports::protocols::wlr::unstable::layer_shell::v1::client::{
zwlr_layer_shell_v1::ZwlrLayerShellV1, zwlr_layer_surface_v1,
zwlr_layer_surface_v1::ZwlrLayerSurfaceV1,
};
pub struct Application<M, C>
where
C: Controller<M> + Clone + 'static,
{
display: Display,
globals: Rc<RefCell<Globals>>,
global_manager: GlobalManager,
pub inner: Vec<InnerApplication<M, C>>,
token: RegistrationToken,
}
struct Context {
pending_cb: bool,
time: Option<u32>,
render_node: Option<RenderNode>,
font_cache: FontCache,
}
pub struct CoreApplication<M, C>
where
C: Controller<M> + Clone,
{
pub controller: C,
ctx: Context,
globals: Rc<RefCell<Globals>>,
mempool: AutoMemPool,
widget: Box<dyn Widget<M>>,
surface: Option<Surface>,
}
pub struct InnerApplication<M, C>
where
C: Controller<M> + Clone,
{
core: CoreApplication<M, C>,
cb: Box<dyn FnMut(&mut CoreApplication<M, C>, Event<M>)>,
}
impl Surface {
fn new(
surface: Main<WlSurface>,
shell: Shell,
region: Main<WlRegion>,
previous: Option<Surface>,
) -> Self {
Surface {
alive: true,
surface,
shell,
region,
previous: if let Some(surface) = previous {
Some(Box::new(surface))
} else {
None
},
buffer: None,
}
}
fn commit(&mut self) {
self.surface.commit();
std::mem::drop(&mut self.previous);
self.previous = None;
}
fn destroy(&mut self) {
self.alive = false;
self.surface.destroy();
self.region.destroy();
self.shell.destroy();
if let Some(buffer) = self.buffer.as_ref() {
buffer.destroy();
}
self.buffer = None;
}
fn destroy_previous(&mut self) {
if let Some(surface) = self.previous.as_mut() {
surface.destroy();
}
self.previous = None;
}
fn set_size(&self, width: u32, height: u32) {
self.shell.set_size(width, height);
}
fn damage(&self, report: &[Region]) {
self.surface.attach(self.buffer.as_ref(), 0, 0);
for d in report {
self.surface
.damage(d.x as i32, d.y as i32, d.width as i32, d.height as i32);
}
}
fn attach_buffer(&mut self, buffer: WlBuffer) {
self.buffer = Some(buffer);
}
}
impl Globals {
fn new() -> Self {
Self {
outputs: Vec::new(),
seats: Vec::new(),
shm: None,
compositor: None,
shell: None,
}
}
pub fn create_shell_surface_from<M, C>(
&self,
geometry: &dyn Widget<M>,
config: ShellConfig,
previous: Option<Surface>,
) -> Option<Surface>
where
M: 'static,
C: Controller<M> + Clone + 'static,
{
if self.compositor.is_some() {
match config {
ShellConfig::LayerShell(config) => {
if let Some(layer_shell) = self.shell.as_ref() {
let region = self.compositor.as_ref().unwrap().create_region();
let wl_surface = self.compositor.as_ref().unwrap().create_surface();
let layer_surface = layer_shell.get_layer_surface(
&wl_surface,
config.output.as_ref(),
config.layer,
config.namespace.clone(),
);
if let Some(anchor) = &config.anchor {
layer_surface.set_anchor(*anchor);
}
wl_surface.quick_assign(|_, _, _| {});
layer_surface.set_exclusive_zone(config.exclusive);
layer_surface.set_keyboard_interactivity(config.interactivity);
layer_surface.set_size(geometry.width() as u32, geometry.height() as u32);
layer_surface.set_margin(
config.margin[0],
config.margin[1],
config.margin[2],
config.margin[3],
);
wl_surface.commit();
assign_surface::<M, C>(&layer_surface);
return Some(Surface::new(
wl_surface,
Shell::LayerShell {
surface: layer_surface,
config,
},
region,
previous,
));
}
}
}
}
None
}
pub fn create_mempool(&self) -> AutoMemPool {
let attached = Attached::from(self.shm.clone().unwrap());
AutoMemPool::new(attached).unwrap()
}
pub fn get_outputs(&self) -> Vec<Output> {
self.outputs.clone()
}
pub fn get_seats(&self) -> &[Seat] {
&self.seats
}
}
impl Output {
fn new(output: Main<WlOutput>) -> Self {
Output {
width: 0,
height: 0,
scale: 1,
name: String::new(),
output,
}
}
}
impl<M, C> Application<M, C>
where
M: 'static,
C: Controller<M> + Clone + 'static,
{
pub fn new(pointer: bool) -> (Self, EventLoop<'static, Self>) {
let display = Display::connect_to_env().unwrap();
let event_queue = display.create_event_queue();
let attached_display = (*display).clone().attach(event_queue.token());
let display_handle = display.clone();
let globals = Globals::new();
let global_manager = GlobalManager::new_with_cb(
&attached_display,
global_filter!(
[
ZwlrLayerShellV1,
1,
|layer_shell: Main<ZwlrLayerShellV1>, mut application: DispatchData| {
if let Some(application) = application.get::<Application<M, C>>() {
if let Ok(mut globals) = application.globals.try_borrow_mut() {
globals.shell = Some(layer_shell);
}
}
}
],
[
WlShm,
1,
|shm: Main<WlShm>, mut application: DispatchData| {
shm.quick_assign(|_, _, _| {});
if let Some(application) = application.get::<Application<M, C>>() {
if let Ok(mut globals) = application.globals.try_borrow_mut() {
globals.shm = Some(shm);
}
}
}
],
[
WlCompositor,
4,
|compositor: Main<WlCompositor>, mut application: DispatchData| {
if let Some(application) = application.get::<Application<M, C>>() {
if let Ok(mut globals) = application.globals.try_borrow_mut() {
globals.compositor = Some(compositor);
}
}
}
],
[WlSeat, 7, move |seat: Main<WlSeat>, _: DispatchData| {
seat.quick_assign(move |wl_seat, event, mut application| match event {
wl_seat::Event::Capabilities { capabilities } => {
if let Some(application) = application.get::<Application<M, C>>() {
if pointer
&& capabilities & Capability::Pointer == Capability::Pointer
{
let pointer = wl_seat.get_pointer();
assign_pointer::<M, C>(&pointer);
}
if let Ok(mut globals) = application.globals.try_borrow_mut() {
let mut found = None;
for seat in &mut globals.seats {
if wl_seat.eq(&seat.seat) {
found = Some(());
seat.capabilities = capabilities;
}
}
if found.is_none() {
globals.seats.push(Seat {
capabilities,
seat: wl_seat,
});
}
}
}
}
_ => {}
});
}],
[
WlOutput,
3,
|output: Main<WlOutput>, _application: DispatchData| {
output.quick_assign(move |wl_output, event, mut application| match event {
wl_output::Event::Geometry {
x: _,
y: _,
physical_width: _,
physical_height: _,
subpixel: _,
make,
model: _,
transform: _,
} => {
if let Some(application) = application.get::<Application<M, C>>() {
if let Ok(mut globals) = application.globals.try_borrow_mut() {
let mut found = None;
for output in &mut globals.outputs {
if wl_output.eq(&output.output) {
found = Some(());
output.name = make.clone();
}
}
if found.is_none() {
let mut output = Output::new(wl_output);
output.name = make;
globals.outputs.push(output);
}
}
}
}
wl_output::Event::Mode {
flags: _,
width,
height,
refresh: _,
} => {
if let Some(application) = application.get::<Application<M, C>>() {
if let Ok(mut globals) = application.globals.try_borrow_mut() {
let mut found = None;
for output in &mut globals.outputs {
if wl_output.eq(&output.output) {
found = Some(());
output.width = width;
output.height = height;
}
}
if found.is_none() {
let mut output = Output::new(wl_output);
output.width = width;
output.height = height;
globals.outputs.push(output);
}
}
}
}
wl_output::Event::Scale { factor } => {
if let Some(application) = application.get::<Application<M, C>>() {
if let Ok(mut globals) = application.globals.try_borrow_mut() {
let mut found = None;
for output in &mut globals.outputs {
if wl_output.eq(&output.output) {
found = Some(());
output.scale = factor;
}
}
if found.is_none() {
let mut output = Output::new(wl_output);
output.scale = factor;
globals.outputs.push(output);
}
}
}
}
wl_output::Event::Done => {}
_ => {}
});
}
]
),
);
let event_loop = EventLoop::try_new().expect("Failed to initialize the event loop!");
let token = WaylandSource::new(event_queue)
.quick_insert(event_loop.handle())
.unwrap();
let (mut application, mut event_loop) = (
Application {
display,
globals: Rc::new(RefCell::new(globals)),
global_manager,
inner: Vec::new(),
token,
},
event_loop,
);
for _ in 0..2 {
display_handle.flush().unwrap();
event_loop.dispatch(None, &mut application).unwrap();
}
(application, event_loop)
}
fn get_index(&self, surface: &WlSurface) -> usize {
for i in 0..self.inner.len() {
if self.inner[i].eq(surface) {
return i;
}
}
0
}
fn get_application(&mut self, surface: &WlSurface) -> Option<&mut InnerApplication<M, C>> {
for inner in &mut self.inner {
if inner.eq(surface) {
return Some(inner);
}
}
None
}
pub fn get_global<I>(&self) -> Result<Main<I>, GlobalError>
where
I: Interface + AsRef<Proxy<I>> + From<Proxy<I>>,
{
self.global_manager.instantiate_range::<I>(0, 1 << 8)
}
pub fn create_empty_inner_application<Data: 'static>(
&mut self,
controller: C,
widget: impl Widget<M> + 'static,
handle: LoopHandle<'_, Data>,
cb: impl FnMut(&mut CoreApplication<M, C>, Event<M>) + 'static,
) {
let inner_application =
InnerApplication::empty(controller, widget, self.globals.clone(), cb);
self.inner.push(inner_application);
handle.update(&self.token).unwrap();
}
pub fn create_inner_application_from<Data: 'static>(
&mut self,
controller: C,
config: ShellConfig,
widget: impl Widget<M> + 'static,
handle: LoopHandle<'_, Data>,
cb: impl FnMut(&mut CoreApplication<M, C>, Event<M>) + 'static,
) {
let inner_application =
InnerApplication::new(controller, widget, config, self.globals.clone(), cb);
self.inner.push(inner_application);
handle.update(&self.token).unwrap();
}
pub fn create_inner_application<Data: 'static>(
&mut self,
controller: C,
widget: impl Widget<M> + 'static,
handle: LoopHandle<'_, Data>,
cb: impl FnMut(&mut CoreApplication<M, C>, Event<M>) + 'static,
) {
let inner_application =
InnerApplication::normal(controller, widget, self.globals.clone(), cb);
self.inner.push(inner_application);
handle.update(&self.token).unwrap();
}
pub fn run(mut self, event_loop: &mut EventLoop<'static, Self>) {
loop {
self.display.flush().unwrap();
event_loop.dispatch(None, &mut self).unwrap();
}
}
}
impl<M, C> Deref for InnerApplication<M, C>
where
C: Controller<M> + Clone + 'static,
{
type Target = CoreApplication<M, C>;
fn deref(&self) -> &Self::Target {
&self.core
}
}
impl<M, C> DerefMut for InnerApplication<M, C>
where
C: Controller<M> + Clone + 'static,
{
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.core
}
}
impl<M, C> CoreApplication<M, C>
where
M: 'static,
C: Controller<M> + Clone + 'static,
{
pub fn poll(&mut self, ev: Event<M>) -> C {
let mut ctl = self.controller.clone();
let mut sync_ctx = SyncContext::new(&mut ctl, &mut self.ctx.font_cache);
self.widget.sync(&mut sync_ctx, ev);
ctl
}
pub fn sync(&mut self, ev: Event<M>) -> bool {
let mut sync_ctx = SyncContext::new(&mut self.controller, &mut self.ctx.font_cache);
let mut damage = self.widget.sync(&mut sync_ctx, ev);
while let Ok(msg) = sync_ctx.sync() {
damage = damage.max(self.widget.sync(&mut sync_ctx, Event::Message(&msg)));
}
if damage == Damage::Frame {
if self.ctx.time.is_none() {
self.ctx.time = Some(0);
}
}
damage.is_some() && !self.ctx.pending_cb
}
pub fn destroy(&mut self) {
if let Some(surface) = self.surface.as_mut() {
surface.destroy();
}
}
pub fn get_layer_surface(&self) -> ZwlrLayerSurfaceV1 {
match &self.surface.as_ref().unwrap().shell {
Shell::LayerShell { config: _, surface } => surface.detach(),
}
}
pub fn is_hidden(&self) -> bool {
if let Some(surface) = self.surface.as_ref() {
return !surface.alive;
} else {
true
}
}
pub fn replace_surface(&mut self) {
if let Some(surface) = self.surface.as_mut() {
surface.destroy();
surface.alive = true;
match &surface.shell {
Shell::LayerShell { config, surface: _ } => {
self.surface = self.globals.borrow().create_shell_surface_from::<M, C>(
self.widget.deref(),
ShellConfig::LayerShell(config.clone()),
Some(surface.clone()),
);
}
}
} else {
self.surface = self.globals.borrow().create_shell_surface_from::<M, C>(
self.widget.deref(),
ShellConfig::LayerShell(LayerShellConfig::default()),
None,
);
}
}
pub fn replace_surface_by(&mut self, config: ShellConfig) {
if let Some(surface) = self.surface.as_mut() {
surface.destroy();
surface.alive = true;
self.surface = self.globals.borrow().create_shell_surface_from::<M, C>(
self.widget.deref(),
config,
Some(surface.clone()),
);
} else {
self.surface = self.globals.borrow().create_shell_surface_from::<M, C>(
self.widget.deref(),
config,
None,
);
}
}
}
impl<M, C> Geometry for InnerApplication<M, C>
where
C: Controller<M> + Clone + 'static,
{
fn width(&self) -> f32 {
self.widget.width()
}
fn height(&self) -> f32 {
self.widget.height()
}
fn set_size(&mut self, width: f32, height: f32) -> Result<(), (f32, f32)> {
if let Some(surface) = self.surface.as_ref() {
surface.set_size(width as u32, height as u32);
surface.surface.commit();
}
Ok(())
}
}
impl<M, C> InnerApplication<M, C>
where
M: 'static,
C: Controller<M> + Clone + 'static,
{
pub fn empty(
controller: C,
widget: impl Widget<M> + 'static,
globals: Rc<RefCell<Globals>>,
cb: impl FnMut(&mut CoreApplication<M, C>, Event<M>) + 'static,
) -> Self {
let mempool = globals.borrow().create_mempool();
let mut default = InnerApplication {
core: CoreApplication {
controller,
ctx: Context {
pending_cb: false,
time: None,
font_cache: FontCache::new(),
render_node: None,
},
surface: None,
widget: Box::new(widget),
mempool,
globals,
},
cb: Box::new(cb),
};
default.sync(Event::Prepare);
default
}
pub fn normal(
controller: C,
widget: impl Widget<M> + 'static,
globals: Rc<RefCell<Globals>>,
cb: impl FnMut(&mut CoreApplication<M, C>, Event<M>) + 'static,
) -> Self {
let mempool = globals.borrow().create_mempool();
let mut default = InnerApplication {
core: CoreApplication {
controller,
ctx: Context {
pending_cb: false,
time: None,
font_cache: FontCache::new(),
render_node: None,
},
surface: None,
widget: Box::new(widget),
mempool,
globals,
},
cb: Box::new(cb),
};
default.sync(Event::Prepare);
default.replace_surface();
default
}
pub fn new(
controller: C,
widget: impl Widget<M> + 'static,
config: ShellConfig,
globals: Rc<RefCell<Globals>>,
cb: impl FnMut(&mut CoreApplication<M, C>, Event<M>) + 'static,
) -> Self {
let mempool = globals.borrow().create_mempool();
let mut new = InnerApplication {
core: CoreApplication {
controller,
ctx: Context {
pending_cb: false,
time: None,
font_cache: FontCache::new(),
render_node: None,
},
surface: None,
widget: Box::new(widget),
mempool,
globals,
},
cb: Box::new(cb),
};
new.sync(Event::Prepare);
new.replace_surface_by(config);
new
}
fn eq(&self, wl_surface: &WlSurface) -> bool {
if let Some(surface) = &self.surface {
return surface.surface.detach().eq(wl_surface);
}
false
}
pub fn roundtrip(&mut self, ev: Event<M>) -> Result<RenderNode, ()> {
let width = self.width();
let height = self.height();
// Sending the event to the widget tree
if self.sync(ev) || ev.is_frame() {
// Calling the application´s closure
(self.cb)(&mut self.core, ev);
if !self.is_hidden() {
let current_width = self.width();
let current_height = self.height();
// Resizing the surface in case the widget changed size
if ev.is_frame() {
self.ctx.render_node = None;
} else if width != current_width || height != current_height {
let _ = self.set_size(current_width, current_height);
return Err(());
}
// Creating the render node
let render_node = self.core.widget.create_node(0., 0.);
self.ctx.pending_cb = true;
return Ok(render_node);
}
} else {
// Calling the application´s closure
(self.cb)(&mut self.core, ev);
}
Err(())
}
fn render(&mut self, time: u32, recent_node: RenderNode) {
let width = recent_node.width();
let height = recent_node.height();
if Some(time).ne(&self.core.ctx.time) || time == 0 {
if let Ok((buffer, wl_buffer)) =
Buffer::new(&mut self.core.mempool, width as i32, height as i32)
{
let mut v = Vec::new();
let mut ctx =
DrawContext::new(buffer.backend, &mut self.core.ctx.font_cache, &mut v);
if let Some(render_node) = self.core.ctx.render_node.as_mut() {
if let Err(region) = render_node.draw_merge(
recent_node,
&mut ctx,
&Instruction::empty(0., 0., width, height),
None,
) {
ctx.damage_region(&Background::Transparent, region, false);
}
} else {
ctx.damage_region(
&Background::Transparent,
Region::new(0., 0., width, height),
false,
);
recent_node.render(&mut ctx, None);
self.core.ctx.render_node = Some(recent_node);
}
self.core.ctx.pending_cb = false;
if let Some(surface) = self.core.surface.as_mut() {
surface.attach_buffer(wl_buffer);
surface.damage(&v);
surface.commit();
if let Some(_) = self.core.ctx.time {
self.core.ctx.time = Some(time);
frame_callback::<M, C>(time, surface.surface.clone());
}
}
}
}
}
pub fn callback(&mut self, ev: Event<M>) {
if self.ctx.time.is_none() || ev.is_cb() {
if let Ok(render_node) = self.roundtrip(ev) {
if let Some(surface) = self.surface.as_ref() {
draw_callback::<M, C>(&surface.surface, render_node);
}
}
} else {
let width = self.width();
let height = self.height();
self.sync(ev);
let current_width = self.width();
let current_height = self.height();
// Resizing the surface in case the widget changed size
if width != current_width || height != current_height {
let _ = self.set_size(current_width, current_height);
}
}
}
}
fn frame_callback<M, C>(time: u32, surface: Main<WlSurface>)
where
M: 'static,
C: Controller<M> + Clone + 'static,
{
let h = surface.detach();
surface
.frame()
.quick_assign(move |_, event, mut application| match event {
wl_callback::Event::Done { callback_data } => {
let timeout = (callback_data - time).min(50);
if let Some(application) = application.get::<Application<M, C>>() {
if let Some(inner_application) = application.get_application(&h) {
inner_application.ctx.time = None;
inner_application.callback(Event::Callback(timeout));
}
}
}
_ => {}
});
surface.commit();
}
fn draw_callback<M, C>(surface: &Main<WlSurface>, mut recent_node: RenderNode)
where
M: 'static,
C: Controller<M> + Clone + 'static,
{
let h = surface.detach();
surface
.frame()
.quick_assign(move |_, event, mut application| match event {
wl_callback::Event::Done { callback_data } => {
if let Some(application) = application.get::<Application<M, C>>() {
let inner_application = application.get_application(&h).unwrap();
inner_application.render(callback_data, std::mem::take(&mut recent_node));
}
}
_ => {}
});
surface.commit();
}
impl From<ModifiersState> for Modifiers {
fn from(modifer_state: ModifiersState) -> Modifiers {
Modifiers {
ctrl: modifer_state.ctrl,
alt: modifer_state.alt,
shift: modifer_state.shift,
caps_lock: modifer_state.caps_lock,
logo: modifer_state.logo,
num_lock: modifer_state.num_lock,
}
}
}
fn assign_pointer<M, C>(pointer: &Main<WlPointer>)
where
M: 'static,
C: Controller<M> + Clone + 'static,
{
let mut index = 0;
let mut input = Pointer::Enter;
let (mut x, mut y) = (0., 0.);
pointer.quick_assign(move |_, event, mut inner| match event {
wl_pointer::Event::Leave { serial: _, surface } => {
input = Pointer::Leave;
if let Some(application) = inner.get::<Application<M, C>>() {
if let Some(inner_application) = application.get_application(&surface) {
inner_application.callback(Event::Pointer(x as f32, y as f32, input));
}
}
}
wl_pointer::Event::Button {
serial: _,
time,
button,
state,
} => {
input = Pointer::MouseClick {
time,
button: MouseButton::new(button),
pressed: state == wl_pointer::ButtonState::Pressed,
};
}
wl_pointer::Event::Frame => {
if let Some(application) = inner.get::<Application<M, C>>() {
let inner_application = application.inner.get_mut(index).unwrap();
inner_application.callback(Event::Pointer(x as f32, y as f32, input));
}
}
wl_pointer::Event::Axis {
time: _,
axis,
value,
} => {
input = Pointer::Scroll {
orientation: match axis {
wl_pointer::Axis::VerticalScroll => Orientation::Vertical,
wl_pointer::Axis::HorizontalScroll => Orientation::Horizontal,
_ => Orientation::Vertical,
},
value: value as f32,
}
}
wl_pointer::Event::Enter {
serial: _,
surface,
surface_x,
surface_y,
} => {
if let Some(application) = inner.get::<Application<M, C>>() {
x = surface_x;
y = surface_y;
index = application.get_index(&surface);
}
}
wl_pointer::Event::Motion {
time: _,
surface_x,
surface_y,
} => {
x = surface_x;
y = surface_y;
input = Pointer::Hover;
}
_ => {}
});
}
fn assign_surface<M, C>(shell: &Main<ZwlrLayerSurfaceV1>)
where
M: 'static,
C: Controller<M> + Clone + 'static,
{
shell.quick_assign(move |shell, event, mut inner| match event {
zwlr_layer_surface_v1::Event::Configure {
serial,
width,
height,
} => {
shell.ack_configure(serial);
println!("\nCONFIGURE - {} : {} X {}\n", serial, width, height);
if let Some(application) = inner.get::<Application<M, C>>() {
for inner_application in &mut application.inner {
if let Some(app_surface) = inner_application.surface.as_mut() {
match &app_surface.shell {
Shell::LayerShell { config: _, surface } => {
if shell.eq(surface) {
app_surface.destroy_previous();
let _ = inner_application
.widget
.set_size(width as f32, height as f32);
if inner_application.ctx.pending_cb {
if let Ok(render_node) =
inner_application.roundtrip(Event::Frame)
{
draw_callback::<M, C>(
&inner_application
.surface
.as_ref()
.unwrap()
.surface,
render_node,
);
}
} else {
if let Ok(render_node) =
inner_application.roundtrip(Event::Frame)
{
inner_application.render(0, render_node);
}
}
}
}
}
}
}
}
}
_ => unreachable!(),
});
}

@ -0,0 +1,326 @@
{
"name": "wcag-compliance",
"version": "0.1.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "wcag-compliance",
"version": "0.1.0",
"license": "MIT",
"dependencies": {
"color-contrast-checker": "^2.1.0",
"execa": "^6.1.0"
}
},
"node_modules/color-contrast-checker": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/color-contrast-checker/-/color-contrast-checker-2.1.0.tgz",
"integrity": "sha512-6Y0aIEej3pwZTVlicIqVzhO6T4izDWouaIXnYoDdTuFFAMQ9nnN0dgHNP9J94jRnH6asjPq1/wzUKxwoNbWtRQ=="
},
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
"dependencies": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
"which": "^2.0.1"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/execa": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/execa/-/execa-6.1.0.tgz",
"integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==",
"dependencies": {
"cross-spawn": "^7.0.3",
"get-stream": "^6.0.1",
"human-signals": "^3.0.1",
"is-stream": "^3.0.0",
"merge-stream": "^2.0.0",
"npm-run-path": "^5.1.0",
"onetime": "^6.0.0",
"signal-exit": "^3.0.7",
"strip-final-newline": "^3.0.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sindresorhus/execa?sponsor=1"
}
},
"node_modules/get-stream": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
"integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/human-signals": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz",
"integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==",
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/is-stream": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
"integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
},
"node_modules/merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
},
"node_modules/mimic-fn": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
"integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/npm-run-path": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz",
"integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==",
"dependencies": {
"path-key": "^4.0.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/npm-run-path/node_modules/path-key": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
"integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/onetime": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
"integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
"dependencies": {
"mimic-fn": "^4.0.0"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"engines": {
"node": ">=8"
}
},
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"dependencies": {
"shebang-regex": "^3.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/shebang-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"engines": {
"node": ">=8"
}
},
"node_modules/signal-exit": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
},
"node_modules/strip-final-newline": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
"integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dependencies": {
"isexe": "^2.0.0"
},
"bin": {
"node-which": "bin/node-which"
},
"engines": {
"node": ">= 8"
}
}
},
"dependencies": {
"color-contrast-checker": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/color-contrast-checker/-/color-contrast-checker-2.1.0.tgz",
"integrity": "sha512-6Y0aIEej3pwZTVlicIqVzhO6T4izDWouaIXnYoDdTuFFAMQ9nnN0dgHNP9J94jRnH6asjPq1/wzUKxwoNbWtRQ=="
},
"cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
"requires": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
"which": "^2.0.1"
}
},
"execa": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/execa/-/execa-6.1.0.tgz",
"integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==",
"requires": {
"cross-spawn": "^7.0.3",
"get-stream": "^6.0.1",
"human-signals": "^3.0.1",
"is-stream": "^3.0.0",
"merge-stream": "^2.0.0",
"npm-run-path": "^5.1.0",
"onetime": "^6.0.0",
"signal-exit": "^3.0.7",
"strip-final-newline": "^3.0.0"
}
},
"get-stream": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
"integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="
},
"human-signals": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz",
"integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ=="
},
"is-stream": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
"integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA=="
},
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
},
"merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
},
"mimic-fn": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
"integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw=="
},
"npm-run-path": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz",
"integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==",
"requires": {
"path-key": "^4.0.0"
},
"dependencies": {
"path-key": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
"integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="
}
}
},
"onetime": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
"integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
"requires": {
"mimic-fn": "^4.0.0"
}
},
"path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
},
"shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"requires": {
"shebang-regex": "^3.0.0"
}
},
"shebang-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
},
"signal-exit": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
},
"strip-final-newline": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
"integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw=="
},
"which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"requires": {
"isexe": "^2.0.0"
}
}
}
}

@ -0,0 +1,32 @@
{
"name": "wcag-compliance",
"version": "0.1.0",
"description": "An accessibility checker tool for validating the color contrast of Catppuccin's palettes based on WCAG 2.0 and WCAG 2.1 standards",
"main": "./src/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/catppuccin/catppuccin.git"
},
"keywords": [
"wcag",
"wcag-aa",
"color",
"contrast",
"verifier",
"accessibility",
"standard"
],
"author": "Pocco81",
"license": "MIT",
"bugs": {
"url": "https://github.com/catppuccin/catppuccin/issues"
},
"homepage": "https://github.com/catppuccin/catppuccin#readme",
"dependencies": {
"color-contrast-checker": "^2.1.0",
"execa": "^6.1.0"
}
}

@ -0,0 +1,110 @@
// import { platform } from 'os';
const os = require('os')
const execa = require("execa")
const ColorContrastChecker = require('color-contrast-checker')
const {stdout} = execa('echo', ['unicorns']);
console.log(stdout);
function get_git_root() {
try {
let cmd = ''
if (platform() === 'win32') {
cmd = `git rev-parse --show-toplevel `
} else {
cmd = `(git rev-parse --show-toplevel )`
}
const { stdout } = execa.shellSync(cmd)
return stdout
} catch (e) {
return ''
}
}
// console.log(execa.shellSync("echo 'hello'"))
// /* File System Object */
// var fs = require('fs');
//
// pr
/* Read File */
// fs.readFile(get_git_root() + "palettes.json", bar)
function bar (err, data)
{
/* If an error exists, show it, otherwise show the file */
err ? Function("error","throw error")(err) : console.log(JSON.stringify(data) );
};
// const fs = require("fs")
//
// var ccc = new ColorContrastChecker();
// var palettes = fs.readFileSync('../../palettes.json', 'utf8');
// var palettes = fs.readFile('test.json', 'utf8');
// fs.readFile("../../../palettes.json", function(text){
// palettes = text.split("\n")
// });
// for (var key in palettes) {
// console.log(key)
// if (ccc.isLevelAA(background, rainbow[key], 14)) {
// console.log(" •" + key + ": ✅");
// } else {
// console.log(" •" + key + ": ❌");
// }
// }
// const background = "#1E1D2F"
// var rainbow = {
// rosewater: "#F5E0DC",
// flamingo: "#F2CDCD",
// mauve: "#DDB6F2",
// pink: "#F5C2E7",
// red: "#F28FAD",
// maroon: "#E8A2AF",
// peach: "#F8BD96",
// yellow: "#FAE3B0",
// green: "#ABE9B3",
// blue: "#96CDFB",
// sky: "#89DCEB",
// teal: "#B5E8E0",
// lavender: "#C9CBFF",
// white: "#D9E0EE",
// gray2: "#C3BAC6",
// gray1: "#988BA2",
// gray0: "#6E6C7E",
// black4: "#575268",
// black3: "#302D41",
// black2: "#1E1D2F",
// black1: "#1A1823",
// black0: "#131020",
// }
//
// console.log("\t---- WCAG conformance level AA on Catppuccin ----\n")
//
// for (var key in rainbow) {
// if (ccc.isLevelAA(background, rainbow[key], 14)) {
// console.log(" •" + key + ": ✅");
// } else {
// console.log(" •" + key + ": ❌");
// }
// }
// var color1 = "#FFFFFF";
// var color2 = "#000000";
//
// if (ccc.isLevelAA(color1, color2, 14)) {
// console.log("Valid Level AA");
// } else {
// console.log("Invalid Contrast");
// }
//
// console.log("Hello world!")

@ -0,0 +1,3 @@
{
"hello": "world"
}
Loading…
Cancel
Save