Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🚀 - IP Address Mask Generator #252

Open
nicholas-ochoa opened this issue Apr 11, 2023 · 2 comments
Open

🚀 - IP Address Mask Generator #252

nicholas-ochoa opened this issue Apr 11, 2023 · 2 comments
Labels
contributions welcome Architecture is clear and community can help feature New feature or request P3 This issue has low priority scope: kit Related to @maskito/kit

Comments

@nicholas-ochoa
Copy link

Which package(s) are relevant/related to the feature request?

@maskito/kit

Description

An IP Address mask generator seems like it would be a good fit for this library. I've tried to build it out myself, but haven't had much success aside from just validating the final IP address after it has been typed (not using Maskito).

@nicholas-ochoa nicholas-ochoa added the feature New feature or request label Apr 11, 2023
@nsbarsukov nsbarsukov added P3 This issue has low priority scope: kit Related to @maskito/kit labels Apr 21, 2023
@Alexei-Y
Copy link

Alexei-Y commented Sep 13, 2023

A solution for the IP address mask generator is not yet available.
Perhaps my solution for the IPv4 format will be useful to someone.

I would adjust the mask parameter based on the required validation criteria.
However, in my specific situation, I have chosen to stick with this condition.

const maskitoOptions: MaskitoOptions = {
    mask: /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?(\b){0,1}){0,4}$/,
    postprocessors: [
        ({value, selection}) => {

            const [initialFrom, initialTo] = selection;
            let [from, to] = selection;

            const processedIntegerPart = Array.from(value).reduce(
                (formattedValuePart, char, i) => {

                    const partsOfIp = formattedValuePart.split('.');
                    const lastPartOfIp = partsOfIp[partsOfIp.length - 1] ?? '';

                    const isPositionForSeparator =
                        !(char === '.') &&
                        formattedValuePart.length &&
                        lastPartOfIp.length === 3;

                    if (partsOfIp.length >= 4 && char === '.') {
                        return formattedValuePart;
                    }

                    if (!isPositionForSeparator) {
                        return formattedValuePart + char;
                    }

                    if (i <= initialFrom) {
                        from++;
                    }

                    if (i <= initialTo) {
                        to++;
                    }

                    return formattedValuePart + '.' + char;
                },
                '',
            );

            return {
                value: processedIntegerPart,
                selection: [from, to],
            };
        },
    ],
};

@waterplea waterplea added the contributions welcome Architecture is clear and community can help label Oct 3, 2023
@KyleSmith0905
Copy link

I've built upon the above code and added a port (also, the ip parts weren't being bounded between 0 - 255 so I fixed that too).

Here is the code if you would like to use it:

const ipAndPortMask: MaskitoOptions = {
	mask: /^(((\d+\.){0,2}\d+\.?)|((\d+\.){3}\d+))(:([0-9]{0,5}))?$/,
	postprocessors: [
		({ value, selection }) => {
			const [initialFrom, initialTo] = selection;
			let [from, to] = selection;
			// Ensures ip parts stays at or below 255
			const boundIpParts = (ip: string) => {
				let partsOfIp = ip.split('.');
				partsOfIp = partsOfIp.map((part) => {
					const partNum = parseInt(part);
					if (partNum > 255) return '255';
					// Handle when ip part contains multiple zeros
					if (part.startsWith('0') && part.endsWith('0')) return '0';
					else if (part.startsWith('0') && part !== '0') return part = part.replaceAll('0', '');
					return part;
				})
				return partsOfIp.join('.')
			}
			// Ensures port stays at or below 65535
			const boundPort = (ip: string) => {
				const address = ip.split(':')[0] ?? '';
				let port = ip.split(':')[1] ?? '';
				// Handle when ip part contains multiple zeros
				if (port.startsWith('0') && port.endsWith('0')) port = '0';
				else if (port.startsWith('0') && port !== '0') port = port.replaceAll('0', '');
				const portNum = parseInt(port);
				if (portNum > 65535) return port = '65535';
				return `${address}:${port}`;
			}
			const processedIntegerPart = Array.from(value).reduce(
				(formattedValuePart, char, i) => {
					if (formattedValuePart.includes(':')) {
						return boundPort(formattedValuePart + char);
					}
					const partsOfIp = formattedValuePart.split('.');
					const lastPartOfIp = partsOfIp[partsOfIp.length - 1] ?? '';
					const isPositionForSeparator = (
						!(char === '.') &&
						formattedValuePart.length &&
						(
							lastPartOfIp.length === 3 ||
							partsOfIp[partsOfIp.length - 1].startsWith('0')
						)
					)
					if (partsOfIp.length > 4) {
						return formattedValuePart;
					}
					if (!isPositionForSeparator) {
						return boundIpParts(formattedValuePart + char);
					}
					if (i <= initialFrom) {
						from++;
					}
					if (i <= initialTo) {
						to++;
					}
					if (partsOfIp.length >= 4) {
						if (char === ':') char = ''
						return formattedValuePart + ':' + char;
					}
					else {
						return formattedValuePart + '.' + char;
					}
				},
				''
			);
			return {
				value: processedIntegerPart,
				selection: [from, to],
			};
		},
	],
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
contributions welcome Architecture is clear and community can help feature New feature or request P3 This issue has low priority scope: kit Related to @maskito/kit
Projects
No open projects
Status: 💡 Backlog
Development

No branches or pull requests

5 participants