Skip to content

Commit

Permalink
implement basic colour conversion utility (#33)
Browse files Browse the repository at this point in the history
* implement basic colour conversion utility

* Add debounce and clipboard buttons

* Update cypress tests
  • Loading branch information
JStruk authored Dec 6, 2023
1 parent 83bdfd2 commit 7965c77
Show file tree
Hide file tree
Showing 11 changed files with 178 additions and 8 deletions.
2 changes: 1 addition & 1 deletion cypress/e2e/utils/PHPArrayToJson.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe('PHP Array To Json', () => {
it('should display the results of the inspected string', () => {
cy.get('textarea').type(phpArray)

cy.contains('Convert').click()
cy.get('button').contains('Convert').click()

cy.contains(`"${key}":"${value}"`)
})
Expand Down
4 changes: 2 additions & 2 deletions cypress/e2e/utils/csvtojson.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ describe('CSV to JSON', () => {
const CSVData = "Name,Age,Height\nJoe,25,5'10\nMike,30,6'0"

cy.get('textarea[placeholder="CSV Data"]').type(CSVData, { scrollBehavior: 'center' })
cy.contains('Convert').click()
cy.get('button').contains('Convert').click()

const expectedJSON = CSVToJSON(CSVData)
cy.get('textarea[placeholder="JSON format"]').invoke('val').should('equal', expectedJSON)
})

it('should return an empty array if the CSV data cannot be parsed', () => {
cy.get('textarea[placeholder="CSV Data"]').type('I am the walrus', { scrollBehavior: 'center' })
cy.contains('Convert').click()
cy.get('button').contains('Convert').click()
cy.get('textarea[placeholder="JSON format"]').invoke('val').should('equal', '[]')
})
})
4 changes: 2 additions & 2 deletions cypress/e2e/utils/jsontocsv.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe('CSV to JSON', () => {
const JSONData = '[{"name": "John Doe", "age": "15"}]'

cy.get('textarea[placeholder="JSON Data"]').type(JSONData, { parseSpecialCharSequences: false })
cy.contains('Convert').click()
cy.get('button').contains('Convert').click()

const expectedCSV = JSONtoCSV(JSONData)
cy.get('textarea[placeholder="CSV format"]').invoke('val').should('equal', expectedCSV)
Expand All @@ -23,7 +23,7 @@ describe('CSV to JSON', () => {

it('should return an empty array if the CSV data cannot be parsed', () => {
cy.get('textarea[placeholder="JSON Data"]').type('I am the walrus')
cy.contains('Convert').click()
cy.get('button').contains('Convert').click()
cy.get('textarea[placeholder="CSV format"]').invoke('val').should('equal', '')
})
})
26 changes: 26 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
},
"dependencies": {
"colortranslator": "^3.0.2",
"lorem-ipsum": "^2.0.8",
"vue": "^3.2.38",
"vue-debounce": "^4.0.1",
"vue-gtag": "^2.0.1",
"vue-json-pretty": "^2.2.3",
"vue-router": "^4.1.5"
Expand Down
2 changes: 2 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import App from './App.vue'
import router from './router'
import './assets/style.css'
import VueGtag from 'vue-gtag'
import { vue3Debounce } from 'vue-debounce'

const app = createApp(App)

Expand All @@ -15,4 +16,5 @@ app.use(VueGtag,
},
router
)
app.directive('debounce', vue3Debounce({ lock: true }))
app.mount('#app')
6 changes: 6 additions & 0 deletions src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import JSONToPHPArray from '@/views/JSONToPHPArray.vue'
import Base64Encode from '@/views/Base64Encode.vue'
import Base64Decode from '@/views/Base64Decode.vue'
import LineSort from '@/views/LineSort.vue'
import ColorConverter from '@/views/ColorConverter.vue'

export const routes = [
{
Expand Down Expand Up @@ -89,6 +90,11 @@ export const routes = [
name: 'LineSort',
component: LineSort,
},
{
path: 'color-converter',
name: 'ColorConverter',
component: ColorConverter,
},
],
},
]
Expand Down
12 changes: 12 additions & 0 deletions src/utilities/ColorConverter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { ColorTranslator } from 'colortranslator'

export function ColorConverter(colorCode: string) {
const translator: ColorTranslator = new ColorTranslator(colorCode)

return {
rgb: translator.RGB,
hex: translator.HEX,
hsl: translator.HSL,
cmyk: translator.CMYK,
}
}
77 changes: 77 additions & 0 deletions src/views/ColorConverter.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<template>
<div class="border-2 space-y-4 flex flex-col text-right items-center text-purple-500">
<div class="flex mb-12">
<div class="p-2 w-48">
<p class="text-xl font-bold">Enter color code:</p>
<p class="text-xs">Accept RGB, HEX, CMYK, HSL</p>
</div>
<div class="flex flex-col overflow-ellipsis">
<input type="text" v-model="colorInput" v-debounce:300ms="convert"
class="border rounded border-black p-1 w-96 text-black text-xl">
<p v-if="errorMessage" class="text-red-500 text-sm text-left">{{ errorMessage }}</p>
</div>
</div>
<div class="flex">
<p class="text-lg w-48 p-2">Color:</p>
<input type="text" class="border rounded border-gray-300 p-1 w-96" :style="{ backgroundColor: hex }" readonly>
</div>
<div class="flex">
<p class="text-lg w-48 p-2">RGB:</p>
<input type="text" id="rgb" v-model="rgb" class="border rounded border-gray-300 p-1 w-96 text-black" readonly>
<button class="bg-purple-500 hover:bg-purple-600 text-white text-sm leading-6 font-medium mx-4 rounded-lg p-2"
type="button" @click="copyToClipboard(rgb)">Copy to Clipboard
</button>
</div>
<div class="flex">
<p class="text-lg w-48 p-2">HEX:</p>
<input type="text" id="hex" v-model="hex" class="border rounded border-gray-300 p-1 w-96 text-black" readonly>
<button class="bg-purple-500 hover:bg-purple-600 text-white text-sm leading-6 font-medium mx-4 rounded-lg p-2"
type="button" @click="copyToClipboard(hex)">Copy to Clipboard
</button>
</div>
<div class="flex">
<p class="text-lg w-48 p-2">CMYK:</p>
<input type="text" id="cmyk" v-model="cmyk" class="border rounded border-gray-300 p-1 w-96 text-black" readonly>
<button class="bg-purple-500 hover:bg-purple-600 text-white text-sm leading-6 font-medium mx-4 rounded-lg p-2"
type="button" @click="copyToClipboard(cmyk)">Copy to Clipboard
</button>
</div>
<div class="flex">
<p class="text-lg w-48 p-2">HSL:</p>
<input type="text" id="hsl" v-model="hsl" class="border rounded border-gray-300 p-1 w-96 text-black" readonly>
<button class="bg-purple-500 hover:bg-purple-600 text-white text-sm leading-6 font-medium mx-4 rounded-lg p-2"
type="button" @click="copyToClipboard(hsl)">Copy to Clipboard
</button>
</div>
</div>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import { ColorConverter } from '@/utilities/ColorConverter'
import { copyToClipboard } from '@/helpers/CopyToClipboard'
const colorInput = ref<string>('')
const rgb = ref<string>('')
const hex = ref<string>('')
const hsl = ref<string>('')
const cmyk = ref<string>('')
let errorMessage = ref<string | null>('')
function convert() {
try {
const convertedColorCodes = ColorConverter(colorInput.value.toLowerCase())
errorMessage.value = null
rgb.value = convertedColorCodes.rgb
hex.value = convertedColorCodes.hex
hsl.value = convertedColorCodes.hsl
cmyk.value = convertedColorCodes.cmyk
} catch (e: any) {
if (colorInput.value) {
errorMessage.value = e.message
}
}
}
</script>
7 changes: 4 additions & 3 deletions src/views/ToolsView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ const links = [
{ route: 'Dates', label: 'Dates' },
{ route: 'PHPToJSON', label: 'PHP To JSON' },
{ route: 'JSONToPHP', label: 'JSON To PHP' },
{ route: 'Base64Encode', label: 'Base64Encode' },
{ route: 'Base64Decode', label: 'Base64Decode' },
{ route: 'LineSort', label: 'LineSort' }
{ route: 'Base64Encode', label: 'Base64 Encode' },
{ route: 'Base64Decode', label: 'Base64 Decode' },
{ route: 'LineSort', label: 'Line Sort' },
{ route: 'ColorConverter', label: 'Color Converter' }
]
</script>
44 changes: 44 additions & 0 deletions tests/utilities/ColorConverter.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { ColorConverter } from '@/utilities/ColorConverter'
import { describe, expect, it } from 'vitest'

describe('ColorConverter', () => {
it('converts RGB color codes', () => {
const RGB: string = 'rgb(255, 255, 255)'

const converted = ColorConverter(RGB)

expect(converted.hex).toBe('#FFFFFF')
expect(converted.hsl).toBe('hsl(0, 0%, 100%)')
expect(converted.cmyk).toBe('device-cmyk(0%, 0%, 0%, 0%)')
})

it('converts HEX color codes', () => {
const HEX: string = '#FFFFFF'

const converted = ColorConverter(HEX)

expect(converted.rgb).toBe('rgb(255 255 255)')
expect(converted.hsl).toBe('hsl(0 0% 100%)')
expect(converted.cmyk).toBe('device-cmyk(0% 0% 0% 0%)')
})

it('converts HSL color codes', () => {
const HSL= 'hsl(288, 8%, 55%)'

const converted = ColorConverter(HSL)

expect(converted.rgb).toBe('rgb(145.758, 131.07, 149.43)')
expect(converted.hex).toBe('#928395')
expect(converted.cmyk).toBe('device-cmyk(2.457338%, 12.286689%, 0%, 41.4%)')
})

it('converts CMYK color codes', () => {
const CMYK= 'cmyk(100%, 26%, 0%, 0%)'

const converted = ColorConverter(CMYK)

expect(converted.rgb).toBe('rgb(0, 188.7, 255)')
expect(converted.hex).toBe('#00BDFF')
expect(converted.hsl).toBe('hsl(195.6, 100%, 50%)')
})
})

0 comments on commit 7965c77

Please sign in to comment.