master 6b1a93596dab cached
7 files
39.7 KB
12.5k tokens
34 symbols
1 requests
Download .txt
Repository: angel-rs/css-color-filter-generator
Branch: master
Commit: 6b1a93596dab
Files: 7
Total size: 39.7 KB

Directory structure:
gitextract_trvixkk8/

├── LICENSE.md
├── README.md
├── cayman.css
├── index.css
├── index.html
├── index.js
└── normalize.css

================================================
FILE CONTENTS
================================================

================================================
FILE: LICENSE.md
================================================
MIT License

Copyright (c) Angel Rodriguez and contributors

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:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# 🎨 css-color-filter-generator

## [🔗 Use the interactive tool here](https://angel-rs.github.io/css-color-filter-generator/)

## [⚖️ License](./LICENSE.md)

## 🙏 Credits

- Original author of the color logic [Barrett Sonntag](https://codepen.io/sosuke) via [Codepen](https://codepen.io/sosuke/pen/Pjoqqp)
- [Sam Hartmann](https://github.com/Sammeeey) for contributing UI fixes & improvements
- [Wizard Rabbit](https://github.com/wzrabbit) for contributing RGB support


================================================
FILE: cayman.css
================================================
.highlight table td {
	 padding: 5px;
}
 .highlight table pre {
	 margin: 0;
}
 .highlight .cm {
	 color: #998;
	 font-style: italic;
}
 .highlight .cp {
	 color: #999;
	 font-weight: bold;
}
 .highlight .c1 {
	 color: #998;
	 font-style: italic;
}
 .highlight .cs {
	 color: #999;
	 font-weight: bold;
	 font-style: italic;
}
 .highlight .c, .highlight .cd {
	 color: #998;
	 font-style: italic;
}
 .highlight .err {
	 color: #a61717;
	 background-color: #e3d2d2;
}
 .highlight .gd {
	 color: #000;
	 background-color: #fdd;
}
 .highlight .ge {
	 color: #000;
	 font-style: italic;
}
 .highlight .gr {
	 color: #a00;
}
 .highlight .gh {
	 color: #999;
}
 .highlight .gi {
	 color: #000;
	 background-color: #dfd;
}
 .highlight .go {
	 color: #888;
}
 .highlight .gp {
	 color: #555;
}
 .highlight .gs {
	 font-weight: bold;
}
 .highlight .gu {
	 color: #aaa;
}
 .highlight .gt {
	 color: #a00;
}
 .highlight .kc {
	 color: #000;
	 font-weight: bold;
}
 .highlight .kd {
	 color: #000;
	 font-weight: bold;
}
 .highlight .kn {
	 color: #000;
	 font-weight: bold;
}
 .highlight .kp {
	 color: #000;
	 font-weight: bold;
}
 .highlight .kr {
	 color: #000;
	 font-weight: bold;
}
 .highlight .kt {
	 color: #458;
	 font-weight: bold;
}
 .highlight .k, .highlight .kv {
	 color: #000;
	 font-weight: bold;
}
 .highlight .mf {
	 color: #099;
}
 .highlight .mh {
	 color: #099;
}
 .highlight .il {
	 color: #099;
}
 .highlight .mi {
	 color: #099;
}
 .highlight .mo {
	 color: #099;
}
 .highlight .m, .highlight .mb, .highlight .mx {
	 color: #099;
}
 .highlight .sb {
	 color: #d14;
}
 .highlight .sc {
	 color: #d14;
}
 .highlight .sd {
	 color: #d14;
}
 .highlight .s2 {
	 color: #d14;
}
 .highlight .se {
	 color: #d14;
}
 .highlight .sh {
	 color: #d14;
}
 .highlight .si {
	 color: #d14;
}
 .highlight .sx {
	 color: #d14;
}
 .highlight .sr {
	 color: #009926;
}
 .highlight .s1 {
	 color: #d14;
}
 .highlight .ss {
	 color: #990073;
}
 .highlight .s {
	 color: #d14;
}
 .highlight .na {
	 color: #008080;
}
 .highlight .bp {
	 color: #999;
}
 .highlight .nb {
	 color: #0086b3;
}
 .highlight .nc {
	 color: #458;
	 font-weight: bold;
}
 .highlight .no {
	 color: #008080;
}
 .highlight .nd {
	 color: #3c5d5d;
	 font-weight: bold;
}
 .highlight .ni {
	 color: #800080;
}
 .highlight .ne {
	 color: #900;
	 font-weight: bold;
}
 .highlight .nf {
	 color: #900;
	 font-weight: bold;
}
 .highlight .nl {
	 color: #900;
	 font-weight: bold;
}
 .highlight .nn {
	 color: #555;
}
 .highlight .nt {
	 color: #000080;
}
 .highlight .vc {
	 color: #008080;
}
 .highlight .vg {
	 color: #008080;
}
 .highlight .vi {
	 color: #008080;
}
 .highlight .nv {
	 color: #008080;
}
 .highlight .ow {
	 color: #000;
	 font-weight: bold;
}
 .highlight .o {
	 color: #000;
	 font-weight: bold;
}
 .highlight .w {
	 color: #bbb;
}
 .highlight {
	 background-color: #f8f8f8;
}
 * {
	 box-sizing: border-box;
}
 body {
	 padding: 0;
	 margin: 0;
	 font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
	 font-size: 16px;
	 line-height: 1.5;
	 color: #606c71;
}
 #skip-to-content {
	 height: 1px;
	 width: 1px;
	 position: absolute;
	 overflow: hidden;
	 top: -10px;
}
 #skip-to-content:focus {
	 position: fixed;
	 top: 10px;
	 left: 10px;
	 height: auto;
	 width: auto;
	 background: #e19447;
	 outline: thick solid #e19447;
}
 a {
	 color: #1e6bb8;
	 text-decoration: none;
}
 a:hover {
	 text-decoration: underline;
}
 .btn {
	 display: inline-block;
	 margin-bottom: 1rem;
	 color: rgba(255, 255, 255, 0.7);
	 background-color: rgba(255, 255, 255, 0.08);
	 border-color: rgba(255, 255, 255, 0.2);
	 border-style: solid;
	 border-width: 1px;
	 border-radius: 0.3rem;
	 transition: color 0.2s, background-color 0.2s, border-color 0.2s;
}
 .btn:hover {
	 color: rgba(255, 255, 255, 0.8);
	 text-decoration: none;
	 background-color: rgba(255, 255, 255, 0.2);
	 border-color: rgba(255, 255, 255, 0.3);
}
 .btn + .btn {
	 margin-left: 1rem;
}
 @media screen and (min-width: 64em) {
	 .btn {
		 padding: 0.75rem 1rem;
	}
}
 @media screen and (min-width: 42em) and (max-width: 64em) {
	 .btn {
		 padding: 0.6rem 0.9rem;
		 font-size: 0.9rem;
	}
}
 @media screen and (max-width: 42em) {
	 .btn {
		 display: block;
		 width: 100%;
		 padding: 0.75rem;
		 font-size: 0.9rem;
	}
	 .btn + .btn {
		 margin-top: 1rem;
		 margin-left: 0;
	}
}
 .page-header {
	 color: #fff;
	 text-align: center;
	 background-color: #159957;
	 background-image: linear-gradient(120deg, #155799, #159957);
}
 @media screen and (min-width: 64em) {
	 .page-header {
		 padding: 4rem 6rem;
	}
}
 @media screen and (min-width: 42em) and (max-width: 64em) {
	 .page-header {
		 padding: 2rem 4rem;
	}
}
 @media screen and (max-width: 42em) {
	 .page-header {
		 padding: 2rem 1rem;
	}
}
 .project-name {
	 margin-top: 0;
	 margin-bottom: 0.1rem;
}
 @media screen and (min-width: 64em) {
	 .project-name {
		 font-size: 3.25rem;
	}
}
 @media screen and (min-width: 42em) and (max-width: 64em) {
	 .project-name {
		 font-size: 2.25rem;
	}
}
 @media screen and (max-width: 42em) {
	 .project-name {
		 font-size: 1.75rem;
	}
}
 .project-tagline {
	 margin-bottom: 2rem;
	 font-weight: normal;
	 opacity: 0.7;
}
 @media screen and (min-width: 64em) {
	 .project-tagline {
		 font-size: 1.25rem;
	}
}
 @media screen and (min-width: 42em) and (max-width: 64em) {
	 .project-tagline {
		 font-size: 1.15rem;
	}
}
 @media screen and (max-width: 42em) {
	 .project-tagline {
		 font-size: 1rem;
	}
}
 .main-content {
	 word-wrap: break-word;
}
 .main-content :first-child {
	 margin-top: 0;
}
 @media screen and (min-width: 64em) {
	 .main-content {
		 max-width: 64rem;
		 padding: 2rem 6rem;
		 margin: 0 auto;
		 font-size: 1.1rem;
	}
}
 @media screen and (min-width: 42em) and (max-width: 64em) {
	 .main-content {
		 padding: 2rem 4rem;
		 font-size: 1.1rem;
	}
}
 @media screen and (max-width: 42em) {
	 .main-content {
		 padding: 2rem 1rem;
		 font-size: 1rem;
	}
}
 .main-content kbd {
	 background-color: #fafbfc;
	 border: 1px solid #c6cbd1;
	 border-bottom-color: #959da5;
	 border-radius: 3px;
	 box-shadow: inset 0 -1px 0 #959da5;
	 color: #444d56;
	 display: inline-block;
	 font-size: 11px;
	 line-height: 10px;
	 padding: 3px 5px;
	 vertical-align: middle;
}
 .main-content img {
	 max-width: 100%;
}
 .main-content h1, .main-content h2, .main-content h3, .main-content h4, .main-content h5, .main-content h6 {
	 margin-top: 2rem;
	 margin-bottom: 1rem;
	 font-weight: normal;
	 color: #159957;
}
 .main-content p {
	 margin-bottom: 1em;
}
 .main-content code {
	 padding: 2px 4px;
	 font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
	 font-size: 0.9rem;
	 color: #567482;
	 background-color: #f3f6fa;
	 border-radius: 0.3rem;
}
 .main-content pre {
	 padding: 0.8rem;
	 margin-top: 0;
	 margin-bottom: 1rem;
	 font: 1rem Consolas, "Liberation Mono", Menlo, Courier, monospace;
	 color: #567482;
	 word-wrap: normal;
	 background-color: #f3f6fa;
	 border: solid 1px #dce6f0;
	 border-radius: 0.3rem;
}
 .main-content pre > code {
	 padding: 0;
	 margin: 0;
	 font-size: 0.9rem;
	 color: #567482;
	 word-break: normal;
	 white-space: pre;
	 background: transparent;
	 border: 0;
}
 .main-content .highlight {
	 margin-bottom: 1rem;
}
 .main-content .highlight pre {
	 margin-bottom: 0;
	 word-break: normal;
}
 .main-content .highlight pre, .main-content pre {
	 padding: 0.8rem;
	 overflow: auto;
	 font-size: 0.9rem;
	 line-height: 1.45;
	 border-radius: 0.3rem;
	 -webkit-overflow-scrolling: touch;
}
 .main-content pre code, .main-content pre tt {
	 display: inline;
	 max-width: initial;
	 padding: 0;
	 margin: 0;
	 overflow: initial;
	 line-height: inherit;
	 word-wrap: normal;
	 background-color: transparent;
	 border: 0;
}
 .main-content pre code:before, .main-content pre tt:before, .main-content pre code:after, .main-content pre tt:after {
	 content: normal;
}
 .main-content ul, .main-content ol {
	 margin-top: 0;
}
 .main-content blockquote {
	 padding: 0 1rem;
	 margin-left: 0;
	 color: #819198;
	 border-left: 0.3rem solid #dce6f0;
}
 .main-content blockquote > :first-child {
	 margin-top: 0;
}
 .main-content blockquote > :last-child {
	 margin-bottom: 0;
}
 .main-content table {
	 display: block;
	 width: 100%;
	 overflow: auto;
	 word-break: normal;
	 word-break: keep-all;
	 -webkit-overflow-scrolling: touch;
}
 .main-content table th {
	 font-weight: bold;
}
 .main-content table th, .main-content table td {
	 padding: 0.5rem 1rem;
	 border: 1px solid #e9ebec;
}
 .main-content dl {
	 padding: 0;
}
 .main-content dl dt {
	 padding: 0;
	 margin-top: 1rem;
	 font-size: 1rem;
	 font-weight: bold;
}
 .main-content dl dd {
	 padding: 0;
	 margin-bottom: 1rem;
}
 .main-content hr {
	 height: 2px;
	 padding: 0;
	 margin: 1rem 0;
	 background-color: #eff0f1;
	 border: 0;
}
 .site-footer {
	 padding-top: 2rem;
	 margin-top: 2rem;
	 border-top: solid 1px #eff0f1;
}
 @media screen and (min-width: 64em) {
	 .site-footer {
		 font-size: 1rem;
	}
}
 @media screen and (min-width: 42em) and (max-width: 64em) {
	 .site-footer {
		 font-size: 1rem;
	}
}
 @media screen and (max-width: 42em) {
	 .site-footer {
		 font-size: 0.9rem;
	}
}
 .site-footer-owner {
	 display: block;
	 font-weight: bold;
}
 .site-footer-credits {
	 color: #819198;
}
 @media screen and (max-width: 42em) {
	 .input-section {
		 flex-direction: column !important;
		 gap: 0.5rem;
	}
	 .material-textfield {
		 width: 100%;
	}
	 #color-input {
		 width: 100% !important;
	}
	 .colorwheel {
		 width: 100%;
	}
	 #color-radio {
		 width: 100%;
		 margin-left: initial;
	}
	 .action-button {
		 width: 100% !important;
		 margin-left: initial !important;
	}
	 .action-button:after {
		 width: 100% !important;
		 transform: initial !important;
		 top: 0 !important;
		 left: 0 !important;
	}
}


================================================
FILE: index.css
================================================
a {
  font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
}

a span {
  user-select: none;
}

label {
  position: absolute;
  font-size: 1rem;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  background-color: white;
  color: gray;
  padding: 0 0.3rem;
  margin: 0 0.5rem;
  transition: .1s ease-out;
  transform-origin: left top;
  pointer-events: none;
}

input {
  font-size: 1rem;
  outline: none;
  border: 1px solid gray;
  border-radius: 5px;
  padding: 1rem 0.7rem;
  color: gray;
  transition: 0.1s ease-out;
}

input:focus {
  border-color: #155799;
}

input:focus + label {
  color: #155799;
  top: 0;
  transform: translateY(-50%) scale(.9);
}

input:not(:placeholder-shown) + label {
  top: 0;
  transform: translateY(-50%) scale(.9);
}

section[class*="section"] {
  padding: 10px 0px;
}

code:hover {
  cursor: pointer;
}

.colorwheel__input {
  display: block;
  width: 5em;
  height: 3.25em;
  margin-left: 1em;
  padding: 0.5em;
  background-color: transparent;
  transition: outline 0.5 ease-in-out;
}

.colorwheel__input:hover {
  outline: 1px solid #155799;
}

#color-input {
  width: 250px;
}

#color-input:disabled + label {
  background-color: #ececec;
}

.disabled {
  background-color: #ececec !important;
  color: #999999 !important;
  pointer-events: none;
  cursor: default;
}

.disabled:after {
  background-color: #ececec !important;
}

.material-textfield {
  position: relative;
}

.btn3d {
	position: relative;
	top: -6px;
	border: 0;
	transition: all 40ms linear;
	margin-top: 10px;
	margin-bottom: 10px;
	margin-left: 2px;
	margin-right: 2px;
}

.btn3d:active:focus,
.btn3d:focus:hover,
.btn3d:focus {
	-moz-outline-style: none;
	outline: medium none;
}

.btn3d:active,
.btn3d.active {
	top: 2px;
}

.btn3d.btn-default {
	box-shadow: 0 0 0 1px transparent inset, 0 0 0 2px rgba(255, 255, 255, 0.10) inset, 0 8px 0 0 #BEBEBE, 0 8px 8px 1px rgba(0, 0, 0, .2);
}

.btn3d.btn-default:active,
.btn3d.btn-default.active {
	box-shadow: 0 0 0 1px transparent inset, 0 0 0 1px rgba(255, 255, 255, 0.15) inset, 0 1px 3px 1px rgba(0, 0, 0, .1);
}

.copyable .pos {
  position: relative;
}

.copyable:hover .copy {
  opacity: 1;
}

.action-button {
  border-radius: 10px;
  display: block;
  height: 50px;
  width: 186px;
  position: relative;
  overflow: hidden;
  text-decoration: none;
  letter-spacing: 1px;
  color: white;
  font-size: 18px;
  text-align: center;
  font-weight: bold;
  margin-left: 30px;
}

.action-button:after {
  position: absolute;
  content:'';
  display: inline-block;
  background: rgba(59,173,227,1);
  background: linear-gradient(45deg, rgba(59,173,227,1) 0%, #155799 45%, #159957 100%);
  height: 50px;
  width: 372px;
  z-index: -1;
  transform: translateX(-280px);
  transition: transform 400ms ease-in;
}

.action-button:hover {
  cursor: pointer;
  text-decoration: none;
}

.action-button:hover:after {
  transform: translateX(-200px);
}

.action-button span {
  position: relative;
  top: 13px;
}

.copy {
  color: #159957;
  font-size: 15px;
  -webkit-transition: opacity 0.35s ease-in-out;
     -moz-transition: opacity 0.35s ease-in-out;
       -o-transition: opacity 0.35s ease-in-out;
          transition: opacity 0.35s ease-in-out;
}

.copy:hover {
  cursor: pointer;
  font-weight: 400;
}

.pixel {
  display: inline-block;
  background-color: #000;
  width: 50px;
  height: 50px;
}

.filterDetail {
  font-family: "Consolas", "Menlo", "Ubuntu Mono", monospace;
}

.color-wrapper {
  display: flex;
  flex-direction: row;
}

.color-content {
  padding-left: 15px;
  max-width: 600px;
}

.input-section {
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}

.real-section, .filtered-section {
  min-height: 150px;
}

.copied::after {
  position: absolute;
  top: -15px;
  right: -8px;
  display: block;
  content: "Copied!";
  font-size: 0.75em;
  padding: 2px 3px;
  color: #fff;
  background-color: #0eaf5e;
  border-radius: 3px;
  opacity: 0;
  will-change: opacity, transform;
  animation: showcopied 1.5s ease;
}

@keyframes showcopied {
  0% {
    opacity: 0;
    transform: translateY(0);
  }
  85% {
    opacity: 1;
    transform: translateY(-15px);
  }
  100% {
    opacity: 0;
    transform: translateY(-15px);
  }
}


================================================
FILE: index.html
================================================
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link href="https://afeld.github.io/emoji-css/emoji.css" rel="stylesheet" />
    <link rel="stylesheet" href="normalize.css" />
    <link rel="stylesheet" href="cayman.css" />
    <link rel="stylesheet" href="index.css" />
    <title>CSS Color Filter Generator</title>
  </head>
  <body>
    <section class="page-header">
      <h1 class="project-name">css-color-filter-generator</h1>
      <h2 class="project-tagline"></h2>
      <a
        href="https://github.com/angel-rs/css-color-filter-generator"
        class="btn"
        >View on GitHub</a
      >
    </section>

    <section class="main-content">
      <div>
        <section class="input-section">
          <div class="material-textfield">
            <input
              disabled
              id="color-input"
              class="target"
              type="text"
              placeholder="#000"
              type="text"
              maxlength="18"
              oninput="validateColor(this.value)"
            />
            <label>Desired Hex or RGB Color</label>
          </div>
          <div class="colorwheel">
            <input id="color-radio" class="colorwheel__input" type="color" />
          </div>
          <a
            id="action-button"
            class="btn3d btn-default action-button disabled"
            onclick="compute()"
            ><span>Get Filter!</span></a
          >
        </section>

        <section class="real-section">
          <p>Real pixel:</p>

          <div class="color-wrapper">
            <div id="realPixel" class="pixel"></div>

            <div class="color-content">
              <span class="copyable" data-clipboard-text="rgb(0, 0, 0)">
                <b>RGB </b><code id="realPixelTextRGB">rgb(0, 0, 0)</code>
                <span class="copy">Copy</span>
                <span class="pos"></span>
              </span>
              <br />
              <span class="copyable" data-clipboard-text="#000">
                <b>HEX </b><code id="realPixelTextHEX">#000</code>
                <span class="copy">Copy</span>
                <span class="pos"> </span>
              </span>
            </div>
          </div>
        </section>

        <section class="filtered-section">
          <p>Filtered pixel, style applied through CSS</p>

          <div class="color-wrapper">
            <div id="filterPixel" class="pixel"></div>

            <div class="color-content">
              <span
                class="copyable"
                data-clipboard-text="filter: brightness(0) saturate(100%)"
              >
                <code id="filterPixelText"
                  >filter: brightness(0) saturate(100%)</code
                >
                <span class="copy">Copy</span>
                <span class="pos"></span>
              </span>
            </div>
          </div>
        </section>

        <span id="lossDetail"> Loss: 0 </span>
      </div>

      <footer class="site-footer">
        <span class="site-footer-owner"
          ><a href="https://github.com/angel-rs/css-color-filter-generator"
            >css-color-filter-generator</a
          >
          is maintained by
          <a href="https://github.com/angel-rs">angel-rs</a>.</span
        >
        <span class="site-footer-credits"
          >This page was generated by
          <a href="https://pages.github.com">GitHub Pages</a>.</span
        >
        <span class="site-footer-note"
          >Made with <i class="em em-coffee"></i> and <i class="em em-heart"></i
        ></span>
      </footer>
    </section>

    <script src="https://unpkg.com/clipboard@2/dist/clipboard.min.js"></script>
    <script src="index.js"></script>
  </body>
</html>


================================================
FILE: index.js
================================================
const colorRadio = document.getElementById("color-radio");
const colorInput = document.getElementById("color-input");

colorRadio.addEventListener("change", () => {
  colorInput.value = colorRadio.value;
  validateColor(colorInput.value);
});

colorInput.addEventListener("input", () => {
  validateColor(colorInput.value);

  switch (colorInput.value.length) {
    case 4:
      colorRadio.value = "#" + hexexpand(colorInput.value);
      break;
    case 7:
      colorRadio.value = colorInput.value;
      break;
    default:
      colorRadio.value = "#000000";
      break;
  }
});

// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
function expandHex(hextexp) {
  const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
  hextexp = hextexp.replace(shorthandRegex, (m, r, g, b) => {
    return r + r + g + g + b + b;
  });
  return hextexp;
}

function rgbToHex(r, g, b) {
  function componentToHex(c) {
    var hex = c.toString(16);
    return hex.length == 1 ? "0" + hex : hex;
  }

  return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
}

function hexToRgb(hex) {
  const expandedHex = expandHex(hex);
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(expandedHex);
  return result
    ? [
        parseInt(result[1], 16),
        parseInt(result[2], 16),
        parseInt(result[3], 16),
      ]
    : null;
}

function trimRgb(rgb) {
  const [r, g, b] = rgb
    .replace(/rgb\(|\) /i, "")
    .split(",")
    .map((x) => parseInt(x));
  return [r, g, b];
}

class Color {
  constructor(r, g, b) {
    this.set(r, g, b);
  }

  toRgb() {
    return `rgb(${Math.round(this.r)}, ${Math.round(this.g)}, ${Math.round(
      this.b
    )})`;
  }

  toHex() {
    return rgbToHex(Math.round(this.r), Math.round(this.g), Math.round(this.b));
  }

  set(r, g, b) {
    this.r = this.clamp(r);
    this.g = this.clamp(g);
    this.b = this.clamp(b);
  }

  hueRotate(angle = 0) {
    angle = (angle / 180) * Math.PI;
    const sin = Math.sin(angle);
    const cos = Math.cos(angle);

    this.multiply([
      0.213 + cos * 0.787 - sin * 0.213,
      0.715 - cos * 0.715 - sin * 0.715,
      0.072 - cos * 0.072 + sin * 0.928,
      0.213 - cos * 0.213 + sin * 0.143,
      0.715 + cos * 0.285 + sin * 0.14,
      0.072 - cos * 0.072 - sin * 0.283,
      0.213 - cos * 0.213 - sin * 0.787,
      0.715 - cos * 0.715 + sin * 0.715,
      0.072 + cos * 0.928 + sin * 0.072,
    ]);
  }

  grayscale(value = 1) {
    this.multiply([
      0.2126 + 0.7874 * (1 - value),
      0.7152 - 0.7152 * (1 - value),
      0.0722 - 0.0722 * (1 - value),
      0.2126 - 0.2126 * (1 - value),
      0.7152 + 0.2848 * (1 - value),
      0.0722 - 0.0722 * (1 - value),
      0.2126 - 0.2126 * (1 - value),
      0.7152 - 0.7152 * (1 - value),
      0.0722 + 0.9278 * (1 - value),
    ]);
  }

  sepia(value = 1) {
    this.multiply([
      0.393 + 0.607 * (1 - value),
      0.769 - 0.769 * (1 - value),
      0.189 - 0.189 * (1 - value),
      0.349 - 0.349 * (1 - value),
      0.686 + 0.314 * (1 - value),
      0.168 - 0.168 * (1 - value),
      0.272 - 0.272 * (1 - value),
      0.534 - 0.534 * (1 - value),
      0.131 + 0.869 * (1 - value),
    ]);
  }

  saturate(value = 1) {
    this.multiply([
      0.213 + 0.787 * value,
      0.715 - 0.715 * value,
      0.072 - 0.072 * value,
      0.213 - 0.213 * value,
      0.715 + 0.285 * value,
      0.072 - 0.072 * value,
      0.213 - 0.213 * value,
      0.715 - 0.715 * value,
      0.072 + 0.928 * value,
    ]);
  }

  multiply(matrix) {
    const newR = this.clamp(
      this.r * matrix[0] + this.g * matrix[1] + this.b * matrix[2]
    );
    const newG = this.clamp(
      this.r * matrix[3] + this.g * matrix[4] + this.b * matrix[5]
    );
    const newB = this.clamp(
      this.r * matrix[6] + this.g * matrix[7] + this.b * matrix[8]
    );
    this.r = newR;
    this.g = newG;
    this.b = newB;
  }

  brightness(value = 1) {
    this.linear(value);
  }
  contrast(value = 1) {
    this.linear(value, -(0.5 * value) + 0.5);
  }

  linear(slope = 1, intercept = 0) {
    this.r = this.clamp(this.r * slope + intercept * 255);
    this.g = this.clamp(this.g * slope + intercept * 255);
    this.b = this.clamp(this.b * slope + intercept * 255);
  }

  invert(value = 1) {
    this.r = this.clamp((value + (this.r / 255) * (1 - 2 * value)) * 255);
    this.g = this.clamp((value + (this.g / 255) * (1 - 2 * value)) * 255);
    this.b = this.clamp((value + (this.b / 255) * (1 - 2 * value)) * 255);
  }

  hsl() {
    // Code taken from https://stackoverflow.com/a/9493060/2688027, licensed under CC BY-SA.
    const r = this.r / 255;
    const g = this.g / 255;
    const b = this.b / 255;
    const max = Math.max(r, g, b);
    const min = Math.min(r, g, b);
    let h,
      s,
      l = (max + min) / 2;

    if (max === min) {
      h = s = 0;
    } else {
      const d = max - min;
      s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
      switch (max) {
        case r:
          h = (g - b) / d + (g < b ? 6 : 0);
          break;

        case g:
          h = (b - r) / d + 2;
          break;

        case b:
          h = (r - g) / d + 4;
          break;
      }
      h /= 6;
    }

    return {
      h: h * 100,
      s: s * 100,
      l: l * 100,
    };
  }

  clamp(value) {
    if (value > 255) {
      value = 255;
    } else if (value < 0) {
      value = 0;
    }
    return value;
  }
}

class Solver {
  constructor(target, baseColor) {
    this.target = target;
    this.targetHSL = target.hsl();
    this.reusedColor = new Color(0, 0, 0);
  }

  solve() {
    const result = this.solveNarrow(this.solveWide());
    return {
      values: result.values,
      loss: result.loss,
      filter: this.css(result.values),
      filterRaw: this.raw(result.values),
    };
  }

  solveWide() {
    const A = 5;
    const c = 15;
    const a = [60, 180, 18000, 600, 1.2, 1.2];

    let best = { loss: Infinity };
    for (let i = 0; best.loss > 25 && i < 3; i++) {
      const initial = [50, 20, 3750, 50, 100, 100];
      const result = this.spsa(A, a, c, initial, 1000);
      if (result.loss < best.loss) {
        best = result;
      }
    }
    return best;
  }

  solveNarrow(wide) {
    const A = wide.loss;
    const c = 2;
    const A1 = A + 1;
    const a = [0.25 * A1, 0.25 * A1, A1, 0.25 * A1, 0.2 * A1, 0.2 * A1];
    return this.spsa(A, a, c, wide.values, 500);
  }

  spsa(A, a, c, values, iters) {
    const alpha = 1;
    const gamma = 0.16666666666666666;

    let best = null;
    let bestLoss = Infinity;
    const deltas = new Array(6);
    const highArgs = new Array(6);
    const lowArgs = new Array(6);

    for (let k = 0; k < iters; k++) {
      const ck = c / Math.pow(k + 1, gamma);
      for (let i = 0; i < 6; i++) {
        deltas[i] = Math.random() > 0.5 ? 1 : -1;
        highArgs[i] = values[i] + ck * deltas[i];
        lowArgs[i] = values[i] - ck * deltas[i];
      }

      const lossDiff = this.loss(highArgs) - this.loss(lowArgs);
      for (let i = 0; i < 6; i++) {
        const g = (lossDiff / (2 * ck)) * deltas[i];
        const ak = a[i] / Math.pow(A + k + 1, alpha);
        values[i] = fix(values[i] - ak * g, i);
      }

      const loss = this.loss(values);
      if (loss < bestLoss) {
        best = values.slice(0);
        bestLoss = loss;
      }
    }
    return { values: best, loss: bestLoss };

    function fix(value, idx) {
      let max = 100;
      if (idx === 2 /* saturate */) {
        max = 7500;
      } else if (idx === 4 /* brightness */ || idx === 5 /* contrast */) {
        max = 200;
      }

      if (idx === 3 /* hue-rotate */) {
        if (value > max) {
          value %= max;
        } else if (value < 0) {
          value = max + (value % max);
        }
      } else if (value < 0) {
        value = 0;
      } else if (value > max) {
        value = max;
      }
      return value;
    }
  }

  loss(filters) {
    // Argument is array of percentages.
    const color = this.reusedColor;
    color.set(0, 0, 0);

    color.invert(filters[0] / 100);
    color.sepia(filters[1] / 100);
    color.saturate(filters[2] / 100);
    color.hueRotate(filters[3] * 3.6);
    color.brightness(filters[4] / 100);
    color.contrast(filters[5] / 100);

    const colorHSL = color.hsl();
    return (
      Math.abs(color.r - this.target.r) +
      Math.abs(color.g - this.target.g) +
      Math.abs(color.b - this.target.b) +
      Math.abs(colorHSL.h - this.targetHSL.h) +
      Math.abs(colorHSL.s - this.targetHSL.s) +
      Math.abs(colorHSL.l - this.targetHSL.l)
    );
  }

  raw(filters) {
    function fmt(idx, multiplier = 1) {
      return Math.round(filters[idx] * multiplier);
    }
    return `brightness(0) saturate(100%) invert(${fmt(0)}%) sepia(${fmt(
      1
    )}%) saturate(${fmt(2)}%) hue-rotate(${fmt(3, 3.6)}deg) brightness(${fmt(
      4
    )}%) contrast(${fmt(5)}%)`;
  }

  css(filters) {
    function fmt(idx, multiplier = 1) {
      return Math.round(filters[idx] * multiplier);
    }
    return `filter: brightness(0) saturate(100%) invert(${fmt(0)}%) sepia(${fmt(
      1
    )}%) saturate(${fmt(2)}%) hue-rotate(${fmt(3, 3.6)}deg) brightness(${fmt(
      4
    )}%) contrast(${fmt(5)}%);`;
  }
}

function compute() {
  const input = document.getElementById("color-input").value;
  let rgb;

  if (isHEXValid(input)) {
    rgb = hexToRgb(input);
  } else if (isRGBValid(input)) {
    rgb = trimRgb(input);
  } else {
    alert("Invalid format!");
    return;
  }

  if (rgb.length !== 3) {
    alert("Invalid format!");
    return;
  }

  const color = new Color(rgb[0], rgb[1], rgb[2]);
  const solver = new Solver(color);
  const result = solver.solve();
  let lossMsg = "";
  const res = {
    color,
    solver,
    result,
    lossMsg,
  };

  if (res.result.loss < 1) {
    res.lossMsg = "This is a perfect result.";
  } else if (res.result.loss < 5) {
    res.lossMsg = "This is close enough.";
  } else if (res.result.loss < 15) {
    res.lossMsg = "The color is somewhat off. Consider running it again.";
  } else {
    res.lossMsg = "The color is extremely off. Run it again!";
  }

  const filterPixel = document.getElementById("filterPixel");
  const filterPixelText = document.getElementById("filterPixelText");
  const lossDetail = document.getElementById("lossDetail");
  const realPixel = document.getElementById("realPixel");
  const realPixelTextRGB = document.getElementById("realPixelTextRGB");
  const realPixelTextHEX = document.getElementById("realPixelTextHEX");
  const rgbColor = res.color.toRgb();
  const hexColor = res.color.toHex();

  realPixel.style.backgroundColor = rgbColor;
  realPixelTextRGB.innerText = rgbColor;
  realPixelTextRGB.parentElement.setAttribute("data-clipboard-text", rgbColor);
  realPixelTextHEX.innerText = hexColor;
  realPixelTextHEX.parentElement.setAttribute("data-clipboard-text", hexColor);

  filterPixel.style.filter = String(res.result.filterRaw);
  filterPixel.style.webkitFilter = String(res.result.filterRaw);

  filterPixelText.innerText = res.result.filter;
  filterPixelText.parentElement.setAttribute(
    "data-clipboard-text",
    res.result.filter
  );

  lossDetail.innerHTML = `Loss: ${res.result.loss.toFixed(1)}. <b>${
    res.lossMsg
  }</b>`;
}

function isHEXValid(color) {
  const HEXColorRegExp = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;
  const isValid = HEXColorRegExp.test(color);

  if (isValid) {
    return true;
  } else {
    return false;
  }
}

function isRGBValid(color) {
  const RGBColorRegExp = /^(rgb\()?\d{1,3}, ?\d{1,3}, ?\d{1,3}(\))?$/i;

  if (!RGBColorRegExp.test(color)) return false;

  color = color.toLowerCase();
  const startCheck = color.startsWith("rgb");
  const endCheck = color.endsWith(")");
  if ((startCheck && !endCheck) || (!startCheck && endCheck)) return false;

  const [r, g, b] = color
    .replace(/^rgb\(|\)| /, "")
    .split(",")
    .map((x) => parseInt(x));
  console.log(r, g, b);
  if (r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255) {
    return true;
  } else {
    return false;
  }
}

function validateColor(color) {
  const submitButton = document.getElementById("action-button");

  if (isHEXValid(color) || isRGBValid(color)) {
    submitButton.classList.remove("disabled");
  } else if (!submitButton.classList.contains("disabled")) {
    submitButton.classList.add("disabled");
  }
}

function onStart() {
  const initialColor = new URLSearchParams(document.location.search).get(
    "color"
  );
  if (initialColor && isHEXValid(`#${initialColor}`)) {
    document
      .getElementById("color-input")
      .setAttribute("value", `#${initialColor}`);
    document
      .getElementById("color-radio")
      .setAttribute("value", `#${initialColor}`);
    validateColor(`#${initialColor}`);
    compute();
  }

  const copyableElements = document.querySelectorAll(".copyable");
  const copyEl = document.querySelectorAll(".pos");

  new ClipboardJS("span.copyable");

  copyableElements.forEach((el, index) => {
    el.addEventListener("click", () => {
      copyEl[index].classList.add("copied");

      setTimeout(() => {
        copyEl[index].classList.remove("copied");
      }, 1500);
    });
  });

  document.addEventListener("DOMContentLoaded", function () {
    document.getElementById("color-input").removeAttribute("disabled");
  });
}

onStart();


================================================
FILE: normalize.css
================================================
/*! normalize.css v3.0.2 | MIT License | git.io/normalize */

/**
 * 1. Set default font family to sans-serif.
 * 2. Prevent iOS text size adjust after orientation change, without disabling
 *    user zoom.
 */

html {
  font-family: sans-serif; /* 1 */
  -ms-text-size-adjust: 100%; /* 2 */
  -webkit-text-size-adjust: 100%; /* 2 */
}

/**
 * Remove default margin.
 */

body {
  margin: 0;
}

/* HTML5 display definitions
   ========================================================================== */

/**
 * Correct `block` display not defined for any HTML5 element in IE 8/9.
 * Correct `block` display not defined for `details` or `summary` in IE 10/11
 * and Firefox.
 * Correct `block` display not defined for `main` in IE 11.
 */

article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
main,
menu,
nav,
section,
summary {
  display: block;
}

/**
 * 1. Correct `inline-block` display not defined in IE 8/9.
 * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
 */

audio,
canvas,
progress,
video {
  display: inline-block; /* 1 */
  vertical-align: baseline; /* 2 */
}

/**
 * Prevent modern browsers from displaying `audio` without controls.
 * Remove excess height in iOS 5 devices.
 */

audio:not([controls]) {
  display: none;
  height: 0;
}

/**
 * Address `[hidden]` styling not present in IE 8/9/10.
 * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
 */

[hidden],
template {
  display: none;
}

/* Links
   ========================================================================== */

/**
 * Remove the gray background color from active links in IE 10.
 */

a {
  background-color: transparent;
}

/**
 * Improve readability when focused and also mouse hovered in all browsers.
 */

a:active,
a:hover {
  outline: 0;
}

/* Text-level semantics
   ========================================================================== */

/**
 * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
 */

abbr[title] {
  border-bottom: 1px dotted;
}

/**
 * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
 */

b,
strong {
  font-weight: bold;
}

/**
 * Address styling not present in Safari and Chrome.
 */

dfn {
  font-style: italic;
}

/**
 * Address variable `h1` font-size and margin within `section` and `article`
 * contexts in Firefox 4+, Safari, and Chrome.
 */

h1 {
  font-size: 2em;
  margin: 0.67em 0;
}

/**
 * Address styling not present in IE 8/9.
 */

mark {
  background: #ff0;
  color: #000;
}

/**
 * Address inconsistent and variable font size in all browsers.
 */

small {
  font-size: 80%;
}

/**
 * Prevent `sub` and `sup` affecting `line-height` in all browsers.
 */

sub,
sup {
  font-size: 75%;
  line-height: 0;
  position: relative;
  vertical-align: baseline;
}

sup {
  top: -0.5em;
}

sub {
  bottom: -0.25em;
}

/* Embedded content
   ========================================================================== */

/**
 * Remove border when inside `a` element in IE 8/9/10.
 */

img {
  border: 0;
}

/**
 * Correct overflow not hidden in IE 9/10/11.
 */

svg:not(:root) {
  overflow: hidden;
}

/* Grouping content
   ========================================================================== */

/**
 * Address margin not present in IE 8/9 and Safari.
 */

figure {
  margin: 1em 40px;
}

/**
 * Address differences between Firefox and other browsers.
 */

hr {
  -moz-box-sizing: content-box;
  box-sizing: content-box;
  height: 0;
}

/**
 * Contain overflow in all browsers.
 */

pre {
  overflow: auto;
}

/**
 * Address odd `em`-unit font size rendering in all browsers.
 */

code,
kbd,
pre,
samp {
  font-family: monospace, monospace;
  font-size: 1em;
}

/* Forms
   ========================================================================== */

/**
 * Known limitation: by default, Chrome and Safari on OS X allow very limited
 * styling of `select`, unless a `border` property is set.
 */

/**
 * 1. Correct color not being inherited.
 *    Known issue: affects color of disabled elements.
 * 2. Correct font properties not being inherited.
 * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
 */

button,
input,
optgroup,
select,
textarea {
  color: inherit; /* 1 */
  font: inherit; /* 2 */
  margin: 0; /* 3 */
}

/**
 * Address `overflow` set to `hidden` in IE 8/9/10/11.
 */

button {
  overflow: visible;
}

/**
 * Address inconsistent `text-transform` inheritance for `button` and `select`.
 * All other form control elements do not inherit `text-transform` values.
 * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
 * Correct `select` style inheritance in Firefox.
 */

button,
select {
  text-transform: none;
}

/**
 * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
 *    and `video` controls.
 * 2. Correct inability to style clickable `input` types in iOS.
 * 3. Improve usability and consistency of cursor style between image-type
 *    `input` and others.
 */

button,
html input[type="button"], /* 1 */
input[type="reset"],
input[type="submit"] {
  -webkit-appearance: button; /* 2 */
  cursor: pointer; /* 3 */
}

/**
 * Re-set default cursor for disabled elements.
 */

button[disabled],
html input[disabled] {
  cursor: default;
}

/**
 * Remove inner padding and border in Firefox 4+.
 */

button::-moz-focus-inner,
input::-moz-focus-inner {
  border: 0;
  padding: 0;
}

/**
 * Address Firefox 4+ setting `line-height` on `input` using `!important` in
 * the UA stylesheet.
 */

input {
  line-height: normal;
}

/**
 * It's recommended that you don't attempt to style these elements.
 * Firefox's implementation doesn't respect box-sizing, padding, or width.
 *
 * 1. Address box sizing set to `content-box` in IE 8/9/10.
 * 2. Remove excess padding in IE 8/9/10.
 */

input[type="checkbox"],
input[type="radio"] {
  box-sizing: border-box; /* 1 */
  padding: 0; /* 2 */
}

/**
 * Fix the cursor style for Chrome's increment/decrement buttons. For certain
 * `font-size` values of the `input`, it causes the cursor style of the
 * decrement button to change from `default` to `text`.
 */

input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
  height: auto;
}

/**
 * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
 * 2. Address `box-sizing` set to `border-box` in Safari and Chrome
 *    (include `-moz` to future-proof).
 */

input[type="search"] {
  -webkit-appearance: textfield; /* 1 */
  -moz-box-sizing: content-box;
  -webkit-box-sizing: content-box; /* 2 */
  box-sizing: content-box;
}

/**
 * Remove inner padding and search cancel button in Safari and Chrome on OS X.
 * Safari (but not Chrome) clips the cancel button when the search input has
 * padding (and `textfield` appearance).
 */

input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
  -webkit-appearance: none;
}

/**
 * Define consistent border, margin, and padding.
 */

fieldset {
  border: 1px solid #c0c0c0;
  margin: 0 2px;
  padding: 0.35em 0.625em 0.75em;
}

/**
 * 1. Correct `color` not being inherited in IE 8/9/10/11.
 * 2. Remove padding so people aren't caught out if they zero out fieldsets.
 */

legend {
  border: 0; /* 1 */
  padding: 0; /* 2 */
}

/**
 * Remove default vertical scrollbar in IE 8/9/10/11.
 */

textarea {
  overflow: auto;
}

/**
 * Don't inherit the `font-weight` (applied by a rule above).
 * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
 */

optgroup {
  font-weight: bold;
}

/* Tables
   ========================================================================== */

/**
 * Remove most spacing between table cells.
 */

table {
  border-collapse: collapse;
  border-spacing: 0;
}

td,
th {
  padding: 0;
}
Download .txt
gitextract_trvixkk8/

├── LICENSE.md
├── README.md
├── cayman.css
├── index.css
├── index.html
├── index.js
└── normalize.css
Download .txt
SYMBOL INDEX (34 symbols across 1 files)

FILE: index.js
  function expandHex (line 26) | function expandHex(hextexp) {
  function rgbToHex (line 34) | function rgbToHex(r, g, b) {
  function hexToRgb (line 43) | function hexToRgb(hex) {
  function trimRgb (line 55) | function trimRgb(rgb) {
  class Color (line 63) | class Color {
    method constructor (line 64) | constructor(r, g, b) {
    method toRgb (line 68) | toRgb() {
    method toHex (line 74) | toHex() {
    method set (line 78) | set(r, g, b) {
    method hueRotate (line 84) | hueRotate(angle = 0) {
    method grayscale (line 102) | grayscale(value = 1) {
    method sepia (line 116) | sepia(value = 1) {
    method saturate (line 130) | saturate(value = 1) {
    method multiply (line 144) | multiply(matrix) {
    method brightness (line 159) | brightness(value = 1) {
    method contrast (line 162) | contrast(value = 1) {
    method linear (line 166) | linear(slope = 1, intercept = 0) {
    method invert (line 172) | invert(value = 1) {
    method hsl (line 178) | hsl() {
    method clamp (line 217) | clamp(value) {
  class Solver (line 227) | class Solver {
    method constructor (line 228) | constructor(target, baseColor) {
    method solve (line 234) | solve() {
    method solveWide (line 244) | solveWide() {
    method solveNarrow (line 260) | solveNarrow(wide) {
    method spsa (line 268) | spsa(A, a, c, values, iters) {
    method loss (line 324) | loss(filters) {
    method raw (line 347) | raw(filters) {
    method css (line 358) | css(filters) {
  function compute (line 370) | function compute() {
  function isHEXValid (line 438) | function isHEXValid(color) {
  function isRGBValid (line 449) | function isRGBValid(color) {
  function validateColor (line 471) | function validateColor(color) {
  function onStart (line 481) | function onStart() {
Condensed preview — 7 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (44K chars).
[
  {
    "path": "LICENSE.md",
    "chars": 1084,
    "preview": "MIT License\n\nCopyright (c) Angel Rodriguez and contributors\n\nPermission is hereby granted, free of charge, to any person"
  },
  {
    "path": "README.md",
    "chars": 468,
    "preview": "# 🎨 css-color-filter-generator\n\n## [🔗 Use the interactive tool here](https://angel-rs.github.io/css-color-filter-generat"
  },
  {
    "path": "cayman.css",
    "chars": 9782,
    "preview": ".highlight table td {\n\t padding: 5px;\n}\n .highlight table pre {\n\t margin: 0;\n}\n .highlight .cm {\n\t color: #998;\n\t font-s"
  },
  {
    "path": "index.css",
    "chars": 4266,
    "preview": "a {\n  font-family: \"Open Sans\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\n\na span {\n  user-select: none;\n}\n\nlabe"
  },
  {
    "path": "index.html",
    "chars": 3882,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />"
  },
  {
    "path": "index.js",
    "chars": 13353,
    "preview": "const colorRadio = document.getElementById(\"color-radio\");\nconst colorInput = document.getElementById(\"color-input\");\n\nc"
  },
  {
    "path": "normalize.css",
    "chars": 7797,
    "preview": "/*! normalize.css v3.0.2 | MIT License | git.io/normalize */\n\n/**\n * 1. Set default font family to sans-serif.\n * 2. Pre"
  }
]

About this extraction

This page contains the full source code of the angel-rs/css-color-filter-generator GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 7 files (39.7 KB), approximately 12.5k tokens, and a symbol index with 34 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!