-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from drinking-code/v1.1.0
Merge v1.1.0
- Loading branch information
Showing
17 changed files
with
521 additions
and
457 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,75 +1,63 @@ | ||
import CSS_COLOR_NAMES from "./html-colors"; | ||
import toPx from "./css-length-converter"; | ||
import CSS_COLOR_NAMES from "./external/bobspace:html-colors"; | ||
import toPx from "./external/heygrady:units:length"; | ||
|
||
function _getAttributeFromString(string, method, ...data) { | ||
if (!string) return false | ||
string = string.split(' ') | ||
for (let i in string) { | ||
const res = method(string, Number(i), ...data) | ||
if (res) return res | ||
} | ||
} | ||
|
||
function _getColor(border, i) { | ||
const val = border[i] | ||
/** @returns {string} */ | ||
function convertPlainColor(val) { | ||
if (!val) return '#000' | ||
val = val?.toLowerCase() | ||
// color is a hex code | ||
if (val.toLowerCase().match(/#([0-9a-f]{3}){1,2}/)) return val | ||
if (val?.match(/#([0-9a-f]{3}){1,2}/)) return val | ||
// color is a function (rgb, rgba, hsl, hsla) | ||
if (val.startsWith('rgb') || val.startsWith('hsl')) { | ||
let color = val; | ||
if (!val.endsWith(')')) | ||
for (let j = 1; !border[i + j - 1].endsWith(')'); j++) { | ||
color += border[i + j] | ||
} | ||
if (color[3] === 'a') | ||
color = color.replace('a', '').replace(/,[^),]+\)/, ')') | ||
return color | ||
} | ||
else if (val?.match(/^(rgb|hsl)a?\(([^,]{1,3},? *){3}(\d*\.?\d+)?\)/)) | ||
return val | ||
.replace('a', '') | ||
.replace(/\((([\d%]{1,3}, *){2}([\d%]{1,3}))(, *\d*\.?\d+)?\)/, '($1)') | ||
// color is a html color name | ||
if ( | ||
CSS_COLOR_NAMES.map(color => color.toLowerCase()) | ||
.includes(val.toLowerCase()) | ||
) return val | ||
return false | ||
else if (CSS_COLOR_NAMES.map(color => color.toLowerCase()) | ||
.includes(val.toLowerCase())) | ||
return val | ||
else if (val === 'currentcolor') { | ||
return 'currentcolor' | ||
} else return '#000' | ||
} | ||
|
||
function _getOpacity(border, i) { | ||
let val = border[i] | ||
if (val.startsWith('rgba') || val.startsWith('hsla')) { | ||
if (!val.endsWith(')')) | ||
for (let j = 1; !border[i + j - 1].endsWith(')'); j++) { | ||
val += border[i + j] | ||
} | ||
return val.replace(/(rgb|hsl)a?\(([^,)]+,){3}/, '').replace(/\)$/, '') | ||
} | ||
if (border.length - 1 === i) | ||
return 1 | ||
/** @returns {number} */ | ||
function convertColorOpacity(val) { | ||
if (val?.startsWith('rgba') || val?.startsWith('hsla')) { | ||
return Number(val.match(/(\d*\.?\d+)?\)$/)[1]) | ||
} else return 1 | ||
} | ||
|
||
const htmlLengthNotSvgError = new Error('<RoundDiv> Border lengths must be either "thin", "medium", "thick", or in one of the following units: ch, cm, em, ex, in, mm, pc, pt, px, rem, vh, vmax, vmin, vw.') | ||
|
||
function unitCheck(length) { | ||
if (length?.match(/(cap|ic|lh|rlh|vi|vm|vb|Q|mozmm)/g)) throw htmlLengthNotSvgError | ||
return length | ||
const htmlLengthNotSvgErrorTemplate = (a, b) => `<RoundDiv> ${a} must be ${b ? `either ${b}, or` : ''} in one of the following units: ch, cm, em, ex, in, mm, pc, pt, px, rem, vh, vmax, vmin, vw.` | ||
const htmlBorderLengthNotSvgError = | ||
new Error(htmlLengthNotSvgErrorTemplate('border lengths', '"thin", "medium", "thick"')) | ||
const htmlBorderRadiusNotSvgError = | ||
new Error(htmlLengthNotSvgErrorTemplate('border radii')) | ||
|
||
function toNumber(length, element, err) { | ||
if (!length) return false | ||
if (typeof length === 'number' || !length.match(/\D+/)) | ||
return Number(length); | ||
else if (length?.match(/(cap|ic|lh|rlh|vi|vm|vb|Q|mozmm)/g)) | ||
if (err) throw err | ||
else return false | ||
else if (length?.match(/(\d+(\.\d+)?(ch|cm|em|ex|in|mm|pc|pt|px|rem|vh|vmax|vmin|vw)|0)/)) | ||
return toPx(element, length) | ||
} | ||
|
||
function _getWidth(border, i, element) { | ||
const val = border[i] | ||
// width is 0 | ||
if (val === '0') return 0 | ||
/** @returns {number} */ | ||
function convertBorderWidth(val, element) { | ||
if (!val) return 0 | ||
// width is a word | ||
if (val.toLowerCase() === 'thin') return 1 | ||
if (val.toLowerCase() === 'medium') return 3 | ||
if (val.toLowerCase() === 'thick') return 5 | ||
unitCheck(val) | ||
if (val?.toLowerCase() === 'thin') | ||
return 1 | ||
else if (val?.toLowerCase() === 'medium') | ||
return 3 | ||
else if (val?.toLowerCase() === 'thick') | ||
return 5 | ||
// width is <length> | ||
if (val.match(/(\d+(\.\d+)?(ch|cm|em|ex|in|mm|pc|pt|px|rem|vh|vmax|vmin|vw)|0)/)) | ||
return toPx(element, val) | ||
return false | ||
else | ||
return toNumber(val, element, htmlBorderLengthNotSvgError) || 0 | ||
} | ||
|
||
const getWidth = s => _getAttributeFromString(s, _getWidth), | ||
getColor = s => _getAttributeFromString(s, _getColor), | ||
getOpacity = s => _getAttributeFromString(s, _getOpacity) | ||
|
||
export {getWidth, getColor, unitCheck, getOpacity} | ||
export {convertPlainColor, convertColorOpacity, convertBorderWidth, toNumber, htmlBorderRadiusNotSvgError} |
File renamed without changes.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
/** | ||
* @param {number} height | ||
* @param {number} width | ||
* @param {number | Array<number>} radius | ||
* | ||
* @returns {string} SVG path data | ||
* */ | ||
export default function generateSvgSquircle(height, width, radius) { | ||
/* from right to left top left corner upper (right half) */ | ||
const ratios = [1.528665037, 1.0884928889, 0.8684068148, 0.07491140741, 0.6314939259, 0.1690595556, 0.3728238519]; | ||
const roundToNthPlace = 1; | ||
|
||
if (typeof radius === 'number') | ||
radius = Array(4).fill(radius) | ||
else if (radius.length === 2) | ||
radius.push(radius[0]) | ||
if (radius.length === 3) | ||
radius.push(radius[1]) | ||
|
||
height = Number(height); | ||
width = Number(width); | ||
|
||
const _rawRadius = [...radius].map(n => Number(n)) | ||
const max = radius.length - 1 | ||
const next = i => i === max ? 0 : i + 1 | ||
const prev = i => i === 0 ? max : i - 1 | ||
radius = _rawRadius.map((radius, i) => | ||
Math.min( | ||
radius, | ||
Math.min( | ||
height - _rawRadius[i % 2 === 0 ? prev(i) : next(i)], | ||
height / 2 | ||
), | ||
Math.min( | ||
width - _rawRadius[i % 2 === 0 ? next(i) : prev(i)], | ||
width / 2 | ||
) | ||
) | ||
) | ||
|
||
const [a0x, a1x, a2x, a3y, a3x, b1y, b1x] = Array(7) | ||
.fill(Array(4).fill(0)) | ||
.map((a, i) => a.map((b, j) => radius[j] * ratios[i])), | ||
[b0y, b0x] = [a3y, a3x] | ||
|
||
if (isNaN(height)) throw new Error(`'height' must be a number`); | ||
if (isNaN(width)) throw new Error(`'width' must be a number`); | ||
if (radius.includes(NaN)) throw new Error(`'radius' must be a number or an array containing 2 to 4 numbers`); | ||
|
||
const a0xF = x => Math.min(x / 2, a0x[0]), | ||
a0xw = a0xF(width), | ||
a0xh = a0xF(height) | ||
|
||
/*function mapRange(number, in_min, in_max, out_min, out_max) { | ||
return (number - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; | ||
}*/ | ||
|
||
// const maxRadius = Math.max(...radius); | ||
|
||
const yOffsetF = (x) => 0, | ||
hyOffset = yOffsetF(height) || 0, | ||
wyOffset = yOffsetF(width) || 0 | ||
|
||
const startPoint = `${a0xw},${wyOffset}` | ||
|
||
return `M${startPoint} | ||
${width / 2 < a0x[1] | ||
? '' | ||
: `L${width - a0xw},0` | ||
} | ||
C${width - a1x[1]},0,${width - a2x[1]},0,${width - a3x[1]},${a3y[1]} | ||
C${width - b1x[1]},${b1y[1]},${width - b1y[1]},${b1x[1]},${width - b0y[1]},${b0x[1]} | ||
C${width},${a2x[1]},${width},${a1x[1]}, | ||
${width - hyOffset},${a0xh} | ||
${height / 2 < a0x[2] | ||
? '' | ||
: `L${width},${height - a0xh}` | ||
} | ||
C${width},${height - a1x[2]},${width},${height - a2x[2]},${width - a3y[2]},${height - a3x[2]} | ||
C${width - b1y[2]},${height - b1x[2]},${width - b1x[2]},${height - b1y[2]},${width - b0x[2]},${height - b0y[2]} | ||
C${width - a2x[2]},${height},${width - a1x[2]},${height}, | ||
${width - a0xw},${height - wyOffset} | ||
${width / 2 < a0x[3] | ||
? '' | ||
: `L${a0xw},${height}` | ||
} | ||
C${a1x[3]},${height},${a2x[3]},${height},${a3x[3]},${height - a3y[3]} | ||
C${b1x[3]},${height - b1y[3]},${b1y[3]},${height - b1x[3]},${b0y[3]},${height - b0x[3]} | ||
C0,${height - a2x[3]},0,${height - a1x[3]}, | ||
${hyOffset},${height - a0xh} | ||
${height / 2 < a0x[0] | ||
? '' | ||
: `L0,${a0xh}` | ||
} | ||
C0,${a1x[0]},0,${a2x[0]},${a3y[0]},${a3x[0]} | ||
C${b1y[0]},${b1x[0]},${b1x[0]},${b1y[0]},${b0x[0]},${b0y[0]} | ||
C${a2x[0]},0,${a1x[0]},0,${startPoint} | ||
Z` | ||
.replace(/[\n ]/g, '') | ||
.replace(/NaN/g, '0') | ||
.replace(/\d+\.\d+/g, match => | ||
Math.round(Number(match) * (10 ** roundToNthPlace)) / (10 ** roundToNthPlace) | ||
) | ||
} |
Oops, something went wrong.