| 
									
										
										
										
											2020-05-14 21:50:35 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  | 	Author Tobias Koppers @sokra | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** @template T @typedef {(string | Record<string, string | string[] | T>)[] | Record<string, string | string[] | T>} ContainerOptionsFormat */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @template T | 
					
						
							|  |  |  |  * @template N | 
					
						
							|  |  |  |  * @param {ContainerOptionsFormat<T>} options options passed by the user | 
					
						
							| 
									
										
										
										
											2020-05-26 05:14:19 +08:00
										 |  |  |  * @param {function(string | string[], string) : N} normalizeSimple normalize a simple item | 
					
						
							|  |  |  |  * @param {function(T, string) : N} normalizeOptions normalize a complex item | 
					
						
							| 
									
										
										
										
											2020-05-14 21:50:35 +08:00
										 |  |  |  * @param {function(string, N): void} fn processing function | 
					
						
							|  |  |  |  * @returns {void} | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const process = (options, normalizeSimple, normalizeOptions, fn) => { | 
					
						
							|  |  |  | 	const array = items => { | 
					
						
							|  |  |  | 		for (const item of items) { | 
					
						
							|  |  |  | 			if (typeof item === "string") { | 
					
						
							| 
									
										
										
										
											2020-05-26 05:14:19 +08:00
										 |  |  | 				fn(item, normalizeSimple(item, item)); | 
					
						
							| 
									
										
										
										
											2020-05-14 21:50:35 +08:00
										 |  |  | 			} else if (item && typeof item === "object") { | 
					
						
							|  |  |  | 				object(item); | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				throw new Error("Unexpected options format"); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 	const object = obj => { | 
					
						
							|  |  |  | 		for (const [key, value] of Object.entries(obj)) { | 
					
						
							|  |  |  | 			if (typeof value === "string" || Array.isArray(value)) { | 
					
						
							| 
									
										
										
										
											2020-05-26 05:14:19 +08:00
										 |  |  | 				fn(key, normalizeSimple(value, key)); | 
					
						
							| 
									
										
										
										
											2020-05-14 21:50:35 +08:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2020-05-26 05:14:19 +08:00
										 |  |  | 				fn(key, normalizeOptions(value, key)); | 
					
						
							| 
									
										
										
										
											2020-05-14 21:50:35 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 	if (!options) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} else if (Array.isArray(options)) { | 
					
						
							|  |  |  | 		array(options); | 
					
						
							|  |  |  | 	} else if (typeof options === "object") { | 
					
						
							|  |  |  | 		object(options); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		throw new Error("Unexpected options format"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @template T | 
					
						
							|  |  |  |  * @template R | 
					
						
							|  |  |  |  * @param {ContainerOptionsFormat<T>} options options passed by the user | 
					
						
							| 
									
										
										
										
											2020-05-26 05:14:19 +08:00
										 |  |  |  * @param {function(string | string[], string) : R} normalizeSimple normalize a simple item | 
					
						
							|  |  |  |  * @param {function(T, string) : R} normalizeOptions normalize a complex item | 
					
						
							| 
									
										
										
										
											2020-05-14 21:50:35 +08:00
										 |  |  |  * @returns {[string, R][]} parsed options | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const parseOptions = (options, normalizeSimple, normalizeOptions) => { | 
					
						
							|  |  |  | 	/** @type {[string, R][]} */ | 
					
						
							|  |  |  | 	const items = []; | 
					
						
							|  |  |  | 	process(options, normalizeSimple, normalizeOptions, (key, value) => { | 
					
						
							|  |  |  | 		items.push([key, value]); | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | 	return items; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @template T | 
					
						
							|  |  |  |  * @param {string} scope scope name | 
					
						
							|  |  |  |  * @param {ContainerOptionsFormat<T>} options options passed by the user | 
					
						
							|  |  |  |  * @returns {Record<string, string | string[] | T>} options to spread or pass | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const scope = (scope, options) => { | 
					
						
							|  |  |  | 	/** @type {Record<string, string | string[] | T>} */ | 
					
						
							|  |  |  | 	const obj = {}; | 
					
						
							|  |  |  | 	process( | 
					
						
							|  |  |  | 		options, | 
					
						
							|  |  |  | 		item => /** @type {string | string[] | T} */ (item), | 
					
						
							|  |  |  | 		item => /** @type {string | string[] | T} */ (item), | 
					
						
							|  |  |  | 		(key, value) => { | 
					
						
							| 
									
										
										
										
											2020-05-21 01:15:16 +08:00
										 |  |  | 			obj[ | 
					
						
							|  |  |  | 				key.startsWith("./") ? `${scope}${key.slice(1)}` : `${scope}/${key}` | 
					
						
							|  |  |  | 			] = value; | 
					
						
							| 
									
										
										
										
											2020-05-14 21:50:35 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	); | 
					
						
							|  |  |  | 	return obj; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | exports.parseOptions = parseOptions; | 
					
						
							|  |  |  | exports.scope = scope; |