meno-core 1.0.1 → 1.0.2

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.
@@ -995,11 +995,47 @@ async function renderNode(
995
995
  }
996
996
 
997
997
  // Render as <picture> element if AVIF is available
998
+ // Split classes: layout/sizing on <picture>, image-specific on <img>
998
999
  if (metadata?.avifSrcset) {
999
- return `<picture>${classAttr ? `\n` : ''}` +
1000
+ // Image-specific class prefixes that should stay on <img>
1001
+ // objf- (object-fit), objp- (object-position), flt- (filter), tm- (transform), bs- (box-shadow)
1002
+ // Border classes: br- (border-radius), bt- (border-top), bb- (border-bottom),
1003
+ // bl- (border-left), border-r- (border-right), bc- (border-color)
1004
+ // Note: 'b-' is border, but 'b' alone is display:block - need hyphen
1005
+ const imgClassPrefixes = [
1006
+ 'objf-', 'objp-', 'flt-', 'tm-', 'bs-',
1007
+ 'br-', 'bt-', 'bb-', 'bl-', 'border-r-', 'bc-', 'b-'
1008
+ ];
1009
+ // Opacity classes (o-NUMBER) go on img, but overflow (o-h, o-a, o-s, o-v) stays on picture
1010
+ const opacityPattern = /^o-\d/;
1011
+
1012
+ // Parse classes from classAttr
1013
+ const classMatch = classAttr.match(/class="([^"]*)"/);
1014
+ const allClasses = classMatch ? classMatch[1].split(/\s+/).filter(Boolean) : [];
1015
+
1016
+ // Split classes between picture and img
1017
+ const imgClasses: string[] = [];
1018
+ const pictureClasses: string[] = [];
1019
+
1020
+ for (const cls of allClasses) {
1021
+ if (imgClassPrefixes.some(prefix => cls.startsWith(prefix)) || opacityPattern.test(cls)) {
1022
+ imgClasses.push(cls);
1023
+ } else {
1024
+ pictureClasses.push(cls);
1025
+ }
1026
+ }
1027
+
1028
+ const pictureClassAttr = pictureClasses.length > 0
1029
+ ? ` class="${escapeHtml(pictureClasses.join(' '))}"`
1030
+ : '';
1031
+ const imgClassAttr = imgClasses.length > 0
1032
+ ? ` class="${escapeHtml(imgClasses.join(' '))}"`
1033
+ : '';
1034
+
1035
+ return `<picture${pictureClassAttr}>` +
1000
1036
  `<source type="image/avif" srcset="${escapeHtml(metadata.avifSrcset)}" sizes="${escapeHtml(sizesAttr)}" />` +
1001
1037
  `<source type="image/webp" srcset="${escapeHtml(metadata.srcset)}" sizes="${escapeHtml(sizesAttr)}" />` +
1002
- `<img${classAttr}${imgAttrs}${blurStyle}${attrs} />` +
1038
+ `<img${imgClassAttr}${imgAttrs}${blurStyle}${attrs} />` +
1003
1039
  `</picture>`;
1004
1040
  }
1005
1041
 
@@ -1024,7 +1060,7 @@ async function renderNode(
1024
1060
  function buildAttributes(props: Record<string, unknown>, exclude: string[] = []): string {
1025
1061
  const attrs: string[] = [];
1026
1062
  // Internal props that should never be rendered as HTML attributes
1027
- const internalProps = ['type', 'tag', 'component', 'props', 'children', 'src', 'alt', 'loading', 'width', 'height', 'sizes', 'srcset'];
1063
+ const internalProps = ['tag', 'component', 'props', 'children', 'src', 'alt', 'loading', 'width', 'height', 'sizes', 'srcset'];
1028
1064
  const defaultExclude = [...internalProps, ...exclude];
1029
1065
 
1030
1066
  // Regex to detect unresolved template strings like {{link.target}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "meno-core",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "meno": "./bin/cli.ts"