{
  "version": 1,
  "workflows": [
    {
      "id": "6B99D184-A810-4CAA-B790-CB2246255632",
      "defaultIntroducedVersion": 6,
      "name": "Convert Color",
      "nameLocalizationKey": "convert_color_format",
      "summary": "HEX · RGB · RGBA · HSL · HSLA",
      "symbolName": "paintpalette",
      "isEnabled": true,
      "requiresTrustConfirmation": false,
      "sortOrder": 6,
      "mode": "scriptFilter",
      "supportedTypes": [
        "color"
      ],
      "script": {
        "source": "inline",
        "code": "ObjC.import(\"Foundation\");\n\nfunction readJSON() {\n    var data = $.NSFileHandle.fileHandleWithStandardInput.readDataToEndOfFile;\n    var text = $.NSString.alloc.initWithDataEncoding(data, $.NSUTF8StringEncoding).js;\n    return JSON.parse(text);\n}\n\nfunction writeJSON(value) {\n    var text = JSON.stringify(value);\n    var data = $(text).dataUsingEncoding($.NSUTF8StringEncoding);\n    $.NSFileHandle.fileHandleWithStandardOutput.writeData(data);\n}\n\nfunction parseColor(value) {\n    var input = value.trim().toLowerCase();\n    var match;\n\n    if ((match = input.match(/^#([0-9a-f]{3,8})$/))) {\n        var hex = match[1];\n        if (hex.length === 3 || hex.length === 4) {\n            hex = hex.split(\"\").map(function (character) {\n                return character + character;\n            }).join(\"\");\n        }\n        if (hex.length === 6) {\n            hex += \"ff\";\n        }\n        if (hex.length !== 8) {\n            return null;\n        }\n        return {\n            red: parseInt(hex.slice(0, 2), 16),\n            green: parseInt(hex.slice(2, 4), 16),\n            blue: parseInt(hex.slice(4, 6), 16),\n            alpha: parseInt(hex.slice(6, 8), 16) / 255\n        };\n    }\n\n    match = input.match(/^rgba?\\(\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})(?:\\s*,\\s*([01]?\\.?\\d*))?\\s*\\)$/);\n    if (match) {\n        var red = Number(match[1]);\n        var green = Number(match[2]);\n        var blue = Number(match[3]);\n        if (red > 255 || green > 255 || blue > 255) {\n            return null;\n        }\n        return {\n            red: red,\n            green: green,\n            blue: blue,\n            alpha: match[4] === undefined ? 1 : Number(match[4])\n        };\n    }\n\n    match = input.match(/^hsla?\\(\\s*(\\d+)\\s*,\\s*(\\d+)%\\s*,\\s*(\\d+)%\\s*(?:,\\s*([01]?\\.?\\d*))?\\s*\\)$/);\n    if (!match) {\n        return null;\n    }\n\n    var hue = Number(match[1]);\n    var saturation = Number(match[2]) / 100;\n    var lightness = Number(match[3]) / 100;\n    if (hue < 0 || hue >= 360) {\n        return null;\n    }\n\n    var chroma = (1 - Math.abs(2 * lightness - 1)) * saturation;\n    var x = chroma * (1 - Math.abs((hue / 60) % 2 - 1));\n    var m = lightness - chroma / 2;\n    var rgb;\n\n    if (hue < 60) rgb = [chroma, x, 0];\n    else if (hue < 120) rgb = [x, chroma, 0];\n    else if (hue < 180) rgb = [0, chroma, x];\n    else if (hue < 240) rgb = [0, x, chroma];\n    else if (hue < 300) rgb = [x, 0, chroma];\n    else rgb = [chroma, 0, x];\n\n    return {\n        red: Math.round((rgb[0] + m) * 255),\n        green: Math.round((rgb[1] + m) * 255),\n        blue: Math.round((rgb[2] + m) * 255),\n        alpha: match[4] === undefined ? 1 : Number(match[4])\n    };\n}\n\nfunction padHex(value) {\n    return value.toString(16).padStart(2, \"0\");\n}\n\nfunction formatNumber(value, digits) {\n    return Number(value).toFixed(digits);\n}\n\nfunction asHex(color) {\n    var value = \"#\" + padHex(color.red) + padHex(color.green) + padHex(color.blue);\n    if (color.alpha < 1) {\n        value += padHex(Math.round(color.alpha * 255));\n    }\n    return value;\n}\n\nfunction asRGB(color) {\n    return \"rgb(\" + color.red + \", \" + color.green + \", \" + color.blue + \")\";\n}\n\nfunction asRGBA(color) {\n    return \"rgba(\" + color.red + \", \" + color.green + \", \" + color.blue + \", \" +\n        formatNumber(color.alpha, 1) + \")\";\n}\n\nfunction hslComponents(color) {\n    var red = color.red / 255;\n    var green = color.green / 255;\n    var blue = color.blue / 255;\n    var maximum = Math.max(red, green, blue);\n    var minimum = Math.min(red, green, blue);\n    var delta = maximum - minimum;\n    var hue = 0;\n    var lightness = (maximum + minimum) / 2;\n    var saturation = delta === 0 ? 0 : delta / (1 - Math.abs(2 * lightness - 1));\n\n    if (delta !== 0) {\n        if (maximum === red) hue = 60 * (((green - blue) / delta) % 6);\n        else if (maximum === green) hue = 60 * ((blue - red) / delta + 2);\n        else hue = 60 * ((red - green) / delta + 4);\n    }\n    if (hue < 0) hue += 360;\n\n    return {\n        hue: Math.round(hue),\n        saturation: Math.round(saturation * 100),\n        lightness: Math.round(lightness * 100)\n    };\n}\n\nfunction asHSL(color) {\n    var hsl = hslComponents(color);\n    return \"hsl(\" + hsl.hue + \", \" + hsl.saturation + \"%, \" + hsl.lightness + \"%)\";\n}\n\nfunction asHSLA(color) {\n    var hsl = hslComponents(color);\n    return \"hsla(\" + hsl.hue + \", \" + hsl.saturation + \"%, \" + hsl.lightness + \"%, \" +\n        formatNumber(color.alpha, 1) + \")\";\n}\n\nfunction conversions(color) {\n    return [\n        { id: \"hex\", title: \"Convert to HEX\", icon: \"number\", value: asHex(color) },\n        { id: \"rgb\", title: \"Convert to RGB\", icon: \"r.square.fill\", value: asRGB(color) },\n        { id: \"rgba\", title: \"Convert to RGBA\", icon: \"a.square.fill\", value: asRGBA(color) },\n        { id: \"hsl\", title: \"Convert to HSL\", icon: \"h.square.fill\", value: asHSL(color) },\n        { id: \"hsla\", title: \"Convert to HSLA\", icon: \"h.square\", value: asHSLA(color) }\n    ];\n}\n\nfunction main() {\n    var payload = readJSON();\n    var original = ((payload.paste && payload.paste.text) || \"\").trim();\n    var color = parseColor(original);\n    if (!color) {\n        throw new Error(\"Unsupported color value\");\n    }\n\n    var available = conversions(color).filter(function (conversion) {\n        return conversion.value !== original;\n    });\n\n    if (payload.phase === \"filter\") {\n        writeJSON({\n            version: 1,\n            actions: available.map(function (conversion) {\n                return {\n                    id: conversion.id,\n                    title: conversion.title,\n                    subtitle: conversion.value,\n                    icon: conversion.icon,\n                    argument: null\n                };\n            })\n        });\n        return;\n    }\n\n    if (payload.phase !== \"execute\") {\n        throw new Error(\"Unsupported phase\");\n    }\n\n    var selected = available.find(function (conversion) {\n        return conversion.id === payload.actionID;\n    });\n    if (!selected) {\n        throw new Error(\"Unknown color action\");\n    }\n\n    writeJSON({\n        version: 1,\n        result: {\n            type: \"text\",\n            value: selected.value\n        }\n    });\n}\n\nmain();\n",
        "scriptPath": "",
        "interpreterPath": "/usr/bin/osascript",
        "arguments": [
          "-l",
          "JavaScript"
        ],
        "workingDirectory": "",
        "filterTimeout": 5,
        "executeTimeout": 5
      },
      "workflowVersion": 1
    }
  ]
}
