Expose Studio cover rendering API and add three source-based layout tools
studio CI and deployment / verify-and-deploy (push) Successful in 3m51s
studio CI and deployment / verify-and-deploy (push) Successful in 3m51s
This commit is contained in:
@@ -1,19 +1,26 @@
|
||||
import {createElement} from 'react';
|
||||
import {renderToStaticMarkup} from 'react-dom/server';
|
||||
import {serveApiDocumentation} from '../../../lib/api-documentation';
|
||||
import type {NextApiRequest,NextApiResponse} from 'next';
|
||||
import {ideas,ideaMarkdown} from '../../../content/ideas';
|
||||
import {Ref17Cover} from '../../../components/Ref17Cover';
|
||||
import {selections} from '../../../components/SourceCover';
|
||||
import {renderCover} from '../../../lib/render-cover';
|
||||
import {tutorialPost} from '../../../content/tool-links';
|
||||
export default function handler(req:NextApiRequest,res:NextApiResponse){
|
||||
if(serveApiDocumentation(req,res,'/studio/api/export/{slug}'))return;
|
||||
if(req.method!=='GET')return res.status(405).end();
|
||||
const idea=ideas.find(i=>i.slug===req.query.slug);if(!idea)return res.status(404).end();
|
||||
if(req.query.format==='markdown'){res.setHeader('Content-Type','text/markdown; charset=utf-8');return res.send(ideaMarkdown(idea));}
|
||||
if(req.query.format==='svg'){
|
||||
const raw=req.query.slide??'0',index=typeof raw==='string'&&/^\d+$/.test(raw)?Number(raw):-1;
|
||||
if(!idea.template||!idea.slides[index])return res.status(400).json({error:'SVG requires a template and a valid zero-based slide index.'});
|
||||
res.setHeader('Content-Type','image/svg+xml; charset=utf-8');res.setHeader('Content-Disposition',`inline; filename="${idea.slug}-${index}.svg"`);
|
||||
return res.send(renderToStaticMarkup(createElement(Ref17Cover,{template:idea.template,slide:idea.slides[index]})));
|
||||
if(!['GET','POST'].includes(req.method||'')){res.setHeader('Allow','GET, POST');return res.status(405).end();}
|
||||
const slug=String(req.query.slug||''),idea=ideas.find(i=>i.slug===slug);if(!idea)return res.status(404).end();
|
||||
if(req.method==='POST'||req.query.format==='svg'){
|
||||
if(req.query.format!==undefined&&!['svg','json'].includes(String(req.query.format)))return res.status(400).json({error:'渲染格式必须为 svg 或 json'});
|
||||
try{
|
||||
const raw=req.query.slide??'0';if(req.method==='GET'&&(typeof raw!=='string'||!/^\d+$/.test(raw)))throw Error('无效 slide');
|
||||
const input=req.method==='POST'?req.body:idea.tool?{layoutId:req.query.layoutId??selections[0].id}:{slide:Number(raw)};
|
||||
const result=renderCover(slug,input);res.setHeader('Cache-Control','no-store');
|
||||
res.setHeader('Content-Disposition',`attachment; filename="${slug}.${req.query.format==='json'?'json':'svg'}"`);
|
||||
if(req.query.format==='json')return res.json(result.data);
|
||||
res.setHeader('Content-Type','image/svg+xml; charset=utf-8');return res.send(renderToStaticMarkup(result.node));
|
||||
}catch(error){return res.status(400).json({error:error instanceof Error?error.message:'无效参数'});}
|
||||
}
|
||||
res.setHeader('Content-Disposition',`attachment; filename="${idea.slug}.json"`);return res.json({version:idea.template?2:1,...idea});
|
||||
if(req.query.format==='markdown'){res.setHeader('Content-Type','text/markdown; charset=utf-8');return res.send(ideaMarkdown(idea)+'\n\n使用教程:'+tutorialPost+(idea.tool?'\n\n```json\n'+JSON.stringify(selections,null,2)+'\n```':''));}
|
||||
res.setHeader('Content-Disposition',`attachment; filename="${idea.slug}.json"`);return res.json({version:idea.tool?3:idea.template?2:1,...idea,...(idea.tool?{layouts:selections}:{}),tutorialPost});
|
||||
}
|
||||
export const config={api:{bodyParser:{sizeLimit:'32kb'}}};
|
||||
|
||||
Reference in New Issue
Block a user