@@ -48,28 +48,31 @@ class OpenFDDContainer {
4848 const context = { ...this . vcData , ...this . mutableData } ;
4949 let html = this . template . innerHTML ;
5050
51+ const getVal = ( obj , path ) => {
52+ try { return path . split ( '.' ) . reduce ( ( o , i ) => o [ i ] , obj ) ?? '' ; } catch { return '' ; }
53+ } ;
54+
5155 html = html . replace ( / \{ \{ # e a c h \s + ( .* ?) \} \} ( [ \s \S ] * ?) \{ \{ \/ e a c h \} \} / g, ( match , param , body ) => {
52- const key = param . trim ( ) ;
53- const arr = context [ key ] ;
56+ const arr = getVal ( context , param . trim ( ) ) ;
5457 if ( ! arr || ! Array . isArray ( arr ) ) return '' ;
5558 let out = "" ;
5659 for ( let i = 0 ; i < arr . length ; i ++ ) {
57- let itemBody = body ;
58- itemBody = itemBody . replace ( / \{ \{ \s * @ i n d e x \s * \} \} / g, i ) ;
59- Object . keys ( arr [ i ] ) . forEach ( k => {
60- const val = arr [ i ] [ k ] !== null && arr [ i ] [ k ] !== undefined ? arr [ i ] [ k ] : '' ;
61- itemBody = itemBody . replace ( new RegExp ( `\\{\\{\\s*${ k } \\s*\\}\\}` , 'g' ) , val ) ;
60+ let itemBody = body . replace ( / \{ \{ \s * @ i n d e x \s * \} \} / g, i ) ;
61+ const matches = itemBody . match ( / \{ \{ \s * ( .* ?) \s * \} \} / g) || [ ] ;
62+ matches . forEach ( m => {
63+ const path = m . replace ( / [ \{ \} \s ] / g, '' ) ;
64+ if ( path === '@index' ) return ;
65+ itemBody = itemBody . replace ( m , getVal ( arr [ i ] , path ) ) ;
6266 } ) ;
6367 out += itemBody ;
6468 }
6569 return out ;
6670 } ) ;
6771
68- Object . keys ( context ) . forEach ( k => {
69- if ( typeof context [ k ] !== 'object' ) {
70- const val = context [ k ] !== null && context [ k ] !== undefined ? context [ k ] : '' ;
71- html = html . replace ( new RegExp ( `\\{\\{\\s*${ k } \\s*\\}\\}` , 'g' ) , val ) ;
72- }
72+ const topMatches = html . match ( / \{ \{ \s * ( .* ?) \s * \} \} / g) || [ ] ;
73+ topMatches . forEach ( m => {
74+ const path = m . replace ( / [ \{ \} \s ] / g, '' ) ;
75+ html = html . replace ( m , getVal ( context , path ) ) ;
7376 } ) ;
7477 html = html . replace ( / \{ \{ ( .* ?) \} \} / g, '' ) ;
7578
@@ -92,8 +95,12 @@ class OpenFDDContainer {
9295 */
9396 async resolveIssuer ( issuerUri , verificationMethodId ) {
9497 try {
95- const domain = issuerUri . replace ( 'did:web:' , '' ) . replace ( / : / g, '/' ) ;
96- const didUrl = `https://${ domain } /.well-known/did.json` ;
98+ const parts = issuerUri . replace ( 'did:web:' , '' ) . split ( ':' ) ;
99+ const domain = parts [ 0 ] ;
100+ const path = parts . slice ( 1 ) . join ( '/' ) ;
101+ const didUrl = path
102+ ? `https://${ domain } /${ path } /did.json`
103+ : `https://${ domain } /.well-known/did.json` ;
97104 const res = await fetch ( didUrl ) ;
98105 if ( ! res . ok ) throw new Error ( `HTTP ${ res . status } ` ) ;
99106 const didDoc = await res . json ( ) ;
@@ -139,11 +146,11 @@ class OpenFDDContainer {
139146 }
140147
141148 try {
142- // Reconstruct the exact payload that was signed server-side
149+ // Reconstruct deterministic payload (trim template to match library standard)
143150 const vcWithoutProof = JSON . parse ( JSON . stringify ( this . vcRaw ) ) ;
144151 delete vcWithoutProof . proof ;
145152
146- const templateContent = this . template ?. innerHTML || '' ;
153+ const templateContent = ( this . template ?. innerHTML || '' ) . trim ( ) ;
147154 const payloadStr = JSON . stringify ( vcWithoutProof ) + '\n---template---\n' + templateContent ;
148155 const payloadBuffer = new TextEncoder ( ) . encode ( payloadStr ) ;
149156
0 commit comments