aiplang 2.7.2 → 2.7.3
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/bin/aiplang.js +18 -15
- package/package.json +1 -1
- package/server/server.js +1 -1
package/bin/aiplang.js
CHANGED
|
@@ -5,7 +5,7 @@ const fs = require('fs')
|
|
|
5
5
|
const path = require('path')
|
|
6
6
|
const http = require('http')
|
|
7
7
|
|
|
8
|
-
const VERSION = '2.7.
|
|
8
|
+
const VERSION = '2.7.3'
|
|
9
9
|
const RUNTIME_DIR = path.join(__dirname, '..', 'runtime')
|
|
10
10
|
const cmd = process.argv[2]
|
|
11
11
|
const args = process.argv.slice(3)
|
|
@@ -615,13 +615,15 @@ function parseBlock(line) {
|
|
|
615
615
|
}
|
|
616
616
|
|
|
617
617
|
// ── table ───────────────────────────────────────────────────
|
|
618
|
-
if(line.startsWith('table ')) {
|
|
618
|
+
if(line.startsWith('table ') || line.startsWith('table{')) {
|
|
619
619
|
const idx=line.indexOf('{');if(idx===-1) return null
|
|
620
|
-
const
|
|
620
|
+
const start=line.startsWith('table{')?6:6
|
|
621
|
+
const binding=line.slice(start,idx).trim().replace(/^@/,'@')
|
|
621
622
|
const content=line.slice(idx+1,line.lastIndexOf('}')).trim()
|
|
622
623
|
const em=content.match(/edit\s+(PUT|PATCH)\s+(\S+)/), dm=content.match(/delete\s+(?:DELETE\s+)?(\S+)/)
|
|
623
624
|
const clean=content.replace(/edit\s+(PUT|PATCH)\s+\S+/g,'').replace(/delete\s+(?:DELETE\s+)?\S+/g,'')
|
|
624
|
-
|
|
625
|
+
const cols=parseCols(clean)
|
|
626
|
+
return{kind:'table',binding,cols:Array.isArray(cols)?cols:[],empty:parseEmpty(clean),editPath:em?.[2]||null,editMethod:em?.[1]||'PUT',deletePath:dm?.[1]||null,deleteKey:'id',extraClass,animate}
|
|
625
627
|
}
|
|
626
628
|
|
|
627
629
|
// ── form ────────────────────────────────────────────────────
|
|
@@ -727,7 +729,7 @@ function applyMods(html, b) {
|
|
|
727
729
|
|
|
728
730
|
function renderPage(page, allPages) {
|
|
729
731
|
const needsJS=page.queries.length>0||page.blocks.some(b=>['table','list','form','if','btn','select','faq'].includes(b.kind))
|
|
730
|
-
const body=page.blocks.map(b=>applyMods(renderBlock(b,page),b)).join('')
|
|
732
|
+
const body=page.blocks.map(b=>{try{return applyMods(renderBlock(b,page),b)}catch(e){console.error('[aiplang] Block render error:',b.kind,e.message);return ''}}).join('')
|
|
731
733
|
const config=needsJS?JSON.stringify({id:page.id,theme:page.theme,routes:allPages.map(p=>p.route),state:page.state,queries:page.queries}):''
|
|
732
734
|
const hydrate=needsJS?`\n<script>window.__AIPLANG_PAGE__=${config};</script>\n<script src="./aiplang-hydrate.js" defer></script>`:''
|
|
733
735
|
const customVars=page.customTheme?genCustomThemeVars(page.customTheme):''
|
|
@@ -800,7 +802,7 @@ function rStats(b) {
|
|
|
800
802
|
}
|
|
801
803
|
|
|
802
804
|
function rRow(b) {
|
|
803
|
-
const cards=b.items.map(item=>{
|
|
805
|
+
const cards=(b.items||[]).map(item=>{
|
|
804
806
|
const inner=item.map((f,fi)=>{
|
|
805
807
|
if(f.isImg) return`<img src="${esc(f.src)}" class="fx-card-img" alt="" loading="lazy">`
|
|
806
808
|
if(f.isLink) return`<a href="${esc(f.path)}" class="fx-card-link">${esc(f.label)} →</a>`
|
|
@@ -825,7 +827,7 @@ function rSect(b) {
|
|
|
825
827
|
|
|
826
828
|
function rFoot(b) {
|
|
827
829
|
let inner=''
|
|
828
|
-
for(const item of b.items) for(const f of item){
|
|
830
|
+
for(const item of (b.items||[])) for(const f of item){
|
|
829
831
|
if(f.isLink) inner+=`<a href="${esc(f.path)}" class="fx-footer-link">${esc(f.label)}</a>`
|
|
830
832
|
else inner+=`<p class="fx-footer-text">${esc(f.text)}</p>`
|
|
831
833
|
}
|
|
@@ -833,13 +835,14 @@ function rFoot(b) {
|
|
|
833
835
|
}
|
|
834
836
|
|
|
835
837
|
function rTable(b) {
|
|
836
|
-
const
|
|
837
|
-
const
|
|
838
|
-
const
|
|
838
|
+
const cols=Array.isArray(b.cols)?b.cols:[]
|
|
839
|
+
const ths=cols.map(c=>`<th class="fx-th">${esc(c.label)}</th>`).join('')
|
|
840
|
+
const keys=JSON.stringify(cols.map(c=>c.key))
|
|
841
|
+
const cm=JSON.stringify(cols.map(c=>({label:c.label,key:c.key})))
|
|
839
842
|
const ea=b.editPath?` data-fx-edit="${esc(b.editPath)}" data-fx-edit-method="${esc(b.editMethod)}"`:''
|
|
840
843
|
const da=b.deletePath?` data-fx-delete="${esc(b.deletePath)}"`:''
|
|
841
844
|
const at=(b.editPath||b.deletePath)?'<th class="fx-th fx-th-actions">Actions</th>':''
|
|
842
|
-
const span=
|
|
845
|
+
const span=cols.length+((b.editPath||b.deletePath)?1:0)
|
|
843
846
|
return `<div class="fx-table-wrap"><table class="fx-table" data-fx-table="${esc(b.binding)}" data-fx-cols='${keys}' data-fx-col-map='${cm}'${ea}${da}><thead><tr>${ths}${at}</tr></thead><tbody class="fx-tbody"><tr><td colspan="${span}" class="fx-td-empty">${esc(b.empty)}</td></tr></tbody></table></div>\n`
|
|
844
847
|
}
|
|
845
848
|
|
|
@@ -862,12 +865,12 @@ function rBtn(b) {
|
|
|
862
865
|
}
|
|
863
866
|
|
|
864
867
|
function rSelectBlock(b) {
|
|
865
|
-
const opts=b.options.map(o=>`<option value="${esc(o)}">${esc(o)}</option>`).join('')
|
|
868
|
+
const opts=(b.options||[]).map(o=>`<option value="${esc(o)}">${esc(o)}</option>`).join('')
|
|
866
869
|
return `<div class="fx-select-wrap"><select class="fx-input fx-select-block" data-fx-model="${esc(b.binding)}">${opts}</select></div>\n`
|
|
867
870
|
}
|
|
868
871
|
|
|
869
872
|
function rPricing(b) {
|
|
870
|
-
const cards=b.plans.map((p,i)=>{
|
|
873
|
+
const cards=(b.plans||[]).map((p,i)=>{
|
|
871
874
|
let lh='#',ll='Get started'
|
|
872
875
|
if(p.linkRaw){const m=p.linkRaw.match(/\/([^:]+):(.+)/);if(m){lh='/'+m[1];ll=m[2]}}
|
|
873
876
|
const f=i===1?' fx-pricing-featured':''
|
|
@@ -878,7 +881,7 @@ function rPricing(b) {
|
|
|
878
881
|
}
|
|
879
882
|
|
|
880
883
|
function rFaq(b) {
|
|
881
|
-
const items=b.items.map(i=>`<div class="fx-faq-item" onclick="this.classList.toggle('open')"><div class="fx-faq-q">${esc(i.q)}<span class="fx-faq-arrow">▸</span></div><div class="fx-faq-a">${esc(i.a)}</div></div>`).join('')
|
|
884
|
+
const items=(b.items||[]).map(i=>`<div class="fx-faq-item" onclick="this.classList.toggle('open')"><div class="fx-faq-q">${esc(i.q)}<span class="fx-faq-arrow">▸</span></div><div class="fx-faq-a">${esc(i.a)}</div></div>`).join('')
|
|
882
885
|
return `<section class="fx-sect"><div class="fx-faq">${items}</div></section>\n`
|
|
883
886
|
}
|
|
884
887
|
|
|
@@ -888,7 +891,7 @@ function rTestimonial(b) {
|
|
|
888
891
|
}
|
|
889
892
|
|
|
890
893
|
function rGallery(b) {
|
|
891
|
-
const imgs=b.imgs.map(src=>`<div class="fx-gallery-item"><img src="${esc(src)}" alt="" loading="lazy"></div>`).join('')
|
|
894
|
+
const imgs=(b.imgs||[]).map(src=>`<div class="fx-gallery-item"><img src="${esc(src)}" alt="" loading="lazy"></div>`).join('')
|
|
892
895
|
return `<div class="fx-gallery">${imgs}</div>\n`
|
|
893
896
|
}
|
|
894
897
|
|
package/package.json
CHANGED
package/server/server.js
CHANGED
|
@@ -1435,7 +1435,7 @@ async function startServer(aipFile, port = 3000) {
|
|
|
1435
1435
|
|
|
1436
1436
|
// Health
|
|
1437
1437
|
srv.addRoute('GET', '/health', (req, res) => res.json(200, {
|
|
1438
|
-
status:'ok', version:'2.7.
|
|
1438
|
+
status:'ok', version:'2.7.3',
|
|
1439
1439
|
models: app.models.map(m=>m.name),
|
|
1440
1440
|
routes: app.apis.length, pages: app.pages.length,
|
|
1441
1441
|
admin: app.admin?.prefix || null,
|