assign-gingerly 0.0.36 → 0.0.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "assign-gingerly",
3
- "version": "0.0.36",
3
+ "version": "0.0.37",
4
4
  "description": "This package provides a utility function for carefully merging one object into another.",
5
5
  "homepage": "https://github.com/bahrus/assign-gingerly#readme",
6
6
  "bugs": {
package/parseWithAttrs.js CHANGED
@@ -143,10 +143,15 @@ function hasDashOrNonASCII(str) {
143
143
  * Gets attribute value with smart enh- prefix handling
144
144
  * @param element - The element to read from
145
145
  * @param attrName - The attribute name (without enh- prefix)
146
- * @param allowUnprefixed - Pattern (string or RegExp) that element tag name must match to allow unprefixed attributes
146
+ * @param allowUnprefixed - Pattern (string or RegExp) that element tag name must match to allow unprefixed attributes,
147
+ * or `true` for custom element mode (read attributes directly, no enh- prefix)
147
148
  * @returns The attribute value or null
148
149
  */
149
150
  function getAttributeValue(element, attrName, allowUnprefixed) {
151
+ // Custom element mode - read attribute directly, no enh- prefix
152
+ if (allowUnprefixed === true) {
153
+ return element.getAttribute(attrName);
154
+ }
150
155
  const { localName } = element;
151
156
  const isCustomElement = localName.includes('-');
152
157
  const isSVGElement = typeof SVGElement !== 'undefined' && element instanceof SVGElement;
@@ -222,15 +227,18 @@ function getDefaultParser(instanceOf) {
222
227
  * Parses attributes from an element based on AttrPatterns configuration
223
228
  * @param element - The DOM element to read attributes from
224
229
  * @param attrPatterns - The attribute patterns configuration
225
- * @param allowUnprefixed - Pattern (string or RegExp) that element tag name must match to allow unprefixed attributes
230
+ * @param allowUnprefixed - Pattern (string or RegExp) that element tag name must match to allow unprefixed attributes,
231
+ * or `true` for custom element mode: reads attributes directly (no enh- prefix),
232
+ * skips base attribute dash validation, and skips properties already set on the element
226
233
  * @param spawnContext - Optional spawn context containing enhancement config and synthesizer element
227
234
  * @returns Object with parsed attribute values ready for initVals
228
235
  */
229
236
  export function parseWithAttrs(element, attrPatterns, allowUnprefixed, spawnContext) {
230
237
  // Extract synthesizerElement from spawnContext for backward compatibility
231
238
  const synthesizerElement = spawnContext?.synthesizerElement;
232
- // Validate base attribute if present
233
- if ('base' in attrPatterns) {
239
+ const isCustomElementMode = allowUnprefixed === true;
240
+ // Validate base attribute if present (skip in custom element mode)
241
+ if ('base' in attrPatterns && !isCustomElementMode) {
234
242
  const baseValue = attrPatterns.base;
235
243
  if (!hasDashOrNonASCII(baseValue)) {
236
244
  throw new Error(`Invalid base attribute "${baseValue}": must contain a dash (-) or non-ASCII character. ` +
@@ -284,6 +292,13 @@ export function parseWithAttrs(element, attrPatterns, allowUnprefixed, spawnCont
284
292
  }
285
293
  // Second pass: read attributes and parse values
286
294
  for (const [key, { attrName, config }] of resolvedAttrs) {
295
+ // In custom element mode, skip properties already set on the element
296
+ if (isCustomElementMode) {
297
+ const mapsTo = config.mapsTo ?? (key === 'base' ? '.' : key);
298
+ if (mapsTo !== '.' && element[mapsTo] !== undefined) {
299
+ continue;
300
+ }
301
+ }
287
302
  const attrValue = getAttributeValue(element, attrName, allowUnprefixed);
288
303
  // Create parser context
289
304
  const parserContext = {
package/parseWithAttrs.ts CHANGED
@@ -178,14 +178,20 @@ function hasDashOrNonASCII(str: string): boolean {
178
178
  * Gets attribute value with smart enh- prefix handling
179
179
  * @param element - The element to read from
180
180
  * @param attrName - The attribute name (without enh- prefix)
181
- * @param allowUnprefixed - Pattern (string or RegExp) that element tag name must match to allow unprefixed attributes
181
+ * @param allowUnprefixed - Pattern (string or RegExp) that element tag name must match to allow unprefixed attributes,
182
+ * or `true` for custom element mode (read attributes directly, no enh- prefix)
182
183
  * @returns The attribute value or null
183
184
  */
184
185
  function getAttributeValue(
185
186
  element: Element,
186
187
  attrName: string,
187
- allowUnprefixed?: string | RegExp
188
+ allowUnprefixed?: string | RegExp | true
188
189
  ): string | null {
190
+ // Custom element mode - read attribute directly, no enh- prefix
191
+ if (allowUnprefixed === true) {
192
+ return element.getAttribute(attrName);
193
+ }
194
+
189
195
  const { localName } = element;
190
196
  const isCustomElement = localName.includes('-');
191
197
  const isSVGElement = typeof SVGElement !== 'undefined' && element instanceof SVGElement;
@@ -261,21 +267,25 @@ function getDefaultParser(instanceOf?: string | Function): ParserFunction {
261
267
  * Parses attributes from an element based on AttrPatterns configuration
262
268
  * @param element - The DOM element to read attributes from
263
269
  * @param attrPatterns - The attribute patterns configuration
264
- * @param allowUnprefixed - Pattern (string or RegExp) that element tag name must match to allow unprefixed attributes
270
+ * @param allowUnprefixed - Pattern (string or RegExp) that element tag name must match to allow unprefixed attributes,
271
+ * or `true` for custom element mode: reads attributes directly (no enh- prefix),
272
+ * skips base attribute dash validation, and skips properties already set on the element
265
273
  * @param spawnContext - Optional spawn context containing enhancement config and synthesizer element
266
274
  * @returns Object with parsed attribute values ready for initVals
267
275
  */
268
276
  export function parseWithAttrs<T = any>(
269
277
  element: Element,
270
278
  attrPatterns: AttrPatterns<T>,
271
- allowUnprefixed?: string | RegExp,
279
+ allowUnprefixed?: string | RegExp | true,
272
280
  spawnContext?: SpawnContext<T>
273
281
  ): Partial<T> {
274
282
  // Extract synthesizerElement from spawnContext for backward compatibility
275
283
  const synthesizerElement = spawnContext?.synthesizerElement;
276
284
 
277
- // Validate base attribute if present
278
- if ('base' in attrPatterns) {
285
+ const isCustomElementMode = allowUnprefixed === true;
286
+
287
+ // Validate base attribute if present (skip in custom element mode)
288
+ if ('base' in attrPatterns && !isCustomElementMode) {
279
289
  const baseValue = attrPatterns.base as string;
280
290
  if (!hasDashOrNonASCII(baseValue)) {
281
291
  throw new Error(
@@ -341,6 +351,14 @@ export function parseWithAttrs<T = any>(
341
351
 
342
352
  // Second pass: read attributes and parse values
343
353
  for (const [key, { attrName, config }] of resolvedAttrs) {
354
+ // In custom element mode, skip properties already set on the element
355
+ if (isCustomElementMode) {
356
+ const mapsTo = config.mapsTo ?? (key === 'base' ? '.' : key);
357
+ if (mapsTo !== '.' && (element as any)[mapsTo as string] !== undefined) {
358
+ continue;
359
+ }
360
+ }
361
+
344
362
  const attrValue = getAttributeValue(element, attrName, allowUnprefixed);
345
363
 
346
364
  // Create parser context