Download src/artifacts.js from ProCreations/minicpm5-2b-webgpu: direct link, hf CLI and curl.
- Browser
- Download file 7.89 kB
-
https://huggingface.co/spaces/ProCreations/minicpm5-2b-webgpu/resolve/main/src/artifacts.js
- Command line
-
hf download hf://spaces/ProCreations/minicpm5-2b-webgpu/src/artifacts.js
-
curl -L -o artifacts.js https://huggingface.co/spaces/ProCreations/minicpm5-2b-webgpu/resolve/main/src/artifacts.js
7.89 kB
| import { marked } from 'marked'; | |
| import DOMPurify from 'dompurify'; | |
| import {safeFilename, validateArtifact, escapeHTML, sandboxHTML} from './core.js'; | |
| export const renderMarkdown = text => DOMPurify.sanitize(marked.parse(text||'',{breaks:true}),{ADD_ATTR:['target'],FORBID_TAGS:['style','iframe','form','input','button','img','video','audio','source','object','embed'],FORBID_ATTR:['style']}); | |
| function plainInline(s) {return s.replace(/\[([^\]]+)\]\([^)]*\)/g,'$1').replace(/[*`_]/g,'');} | |
| function blocks(markdown) { | |
| return marked.lexer(markdown).filter(t=>t.type!=='space'); | |
| } | |
| export async function createArtifact(name,args) { | |
| validateArtifact(name,args); | |
| const type=name.slice(7),filename=safeFilename(args.title); | |
| let blob; | |
| if(type==='html') blob=new Blob([args.html],{type:'text/html;charset=utf-8'}); | |
| if(type==='document') { | |
| const {Document,Packer,Paragraph,TextRun,HeadingLevel,Table,TableRow,TableCell,WidthType,BorderStyle}=await import('docx'); | |
| const runs=s=>marked.lexer(s).flatMap(t=>t.tokens||[{type:'text',text:s}]).map(t=>new TextRun({text:t.text||t.raw||'',bold:t.type==='strong',italics:t.type==='em',font:t.type==='codespan'?'Consolas':'Calibri'})); | |
| const children=[new Paragraph({text:args.title,heading:HeadingLevel.TITLE,spacing:{after:320}})]; | |
| for(const t of blocks(args.markdown)) { | |
| if(t.type==='heading')children.push(new Paragraph({children:runs(t.text),heading:HeadingLevel[`HEADING_${Math.min(t.depth,3)}`],spacing:{before:220,after:140}})); | |
| else if(t.type==='list')t.items.forEach((item,i)=>children.push(new Paragraph({children:runs(t.ordered?`${i+1}. ${item.text}`:item.text),...(!t.ordered?{bullet:{level:0}}:{}),spacing:{after:120}}))); | |
| else if(t.type==='table')children.push(new Table({width:{size:100,type:WidthType.PERCENTAGE},rows:[t.header,...t.rows].map((row,i)=>new TableRow({children:row.map(c=>new TableCell({shading:i===0?{fill:'E8EAFE'}:undefined,children:[new Paragraph({children:[new TextRun({text:plainInline(c.text),bold:i===0})]})]}))}))})); | |
| else children.push(new Paragraph({children:t.type==='code'?[new TextRun({text:t.text,font:'Consolas',size:19})]:runs(t.text||t.raw),spacing:{after:160,line:290}})); | |
| } | |
| const document=new Document({creator:'MiniCPM5 · ProCreations',title:args.title,styles:{default:{document:{run:{font:'Calibri',size:22,color:'182039'}}},paragraphStyles:[{id:'Title',name:'Title',basedOn:'Normal',run:{size:52,bold:true,color:'343FB2'}},{id:'Heading1',name:'Heading 1',basedOn:'Normal',run:{size:32,bold:true,color:'343FB2'}},{id:'Heading2',name:'Heading 2',basedOn:'Normal',run:{size:27,bold:true,color:'343FB2'}}]},sections:[{properties:{page:{margin:{top:1100,bottom:1100,left:1100,right:1100}}},children}]}); | |
| blob=await Packer.toBlob(document); | |
| } | |
| if(type==='spreadsheet') { | |
| const mod=await import('exceljs');const ExcelJS=mod.default; | |
| const book=new ExcelJS.Workbook();book.creator='MiniCPM5 · ProCreations';book.calcProperties.fullCalcOnLoad=true; | |
| const names=new Set(); | |
| args.sheets.forEach((s,index)=>{ | |
| let n=String(s.name||`Sheet ${index+1}`).replace(/[\\/*?:\[\]]/g,' ').slice(0,27)||`Sheet ${index+1}`; | |
| if(names.has(n.toLowerCase()))n+=` ${index+1}`;names.add(n.toLowerCase()); | |
| const sheet=book.addWorksheet(n,{views:[{state:'frozen',ySplit:1}],properties:{tabColor:{argb:'FF6268F1'}}}); | |
| sheet.columns=s.columns.map((c,i)=>({header:String(c),key:String(i),width:Math.min(48,Math.max(17,String(c).length+4))})); | |
| s.rows.forEach(r=>sheet.addRow(r.map(v=>typeof v==='string'&&v.startsWith('=')?{formula:v.slice(1)}:v))); | |
| sheet.getRow(1).height=30;sheet.getRow(1).eachCell(c=>{c.fill={type:'pattern',pattern:'solid',fgColor:{argb:'FF424BC6'}};c.font={bold:true,color:{argb:'FFFFFFFF'}};c.alignment={vertical:'middle'};}); | |
| sheet.eachRow((r,idx)=>{if(idx===1)return;r.height=25;r.eachCell(c=>{c.font={name:'Calibri',size:11,color:{argb:'FF243047'}};c.alignment={vertical:'middle',wrapText:true};if(idx%2===0)c.fill={type:'pattern',pattern:'solid',fgColor:{argb:'FFF1F3FC'}};});}); | |
| sheet.autoFilter={from:{row:1,column:1},to:{row:Math.max(1,s.rows.length+1),column:s.columns.length}}; | |
| }); | |
| blob=new Blob([await book.xlsx.writeBuffer()],{type:'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'}); | |
| } | |
| if(type==='pdf') { | |
| const {jsPDF}=await import('jspdf'); | |
| const pdf=new jsPDF({unit:'mm',format:'a4',compress:true}); | |
| // Embed a real Unicode font (loaded only when a PDF is requested). | |
| const fontName=/[\u2e80-\u9fff]/.test(args.title+args.markdown)?'NotoSansSC-Regular.ttf':'NotoSans-Regular.ttf'; | |
| const font=await fetch('/fonts/'+fontName); | |
| if(!font.ok)throw new Error('PDF font could not load. Please try again.'); | |
| const bytes=new Uint8Array(await font.arrayBuffer());let binary='';for(let i=0;i<bytes.length;i+=8192)binary+=String.fromCharCode(...bytes.subarray(i,i+8192)); | |
| pdf.addFileToVFS('NotoSans.ttf',btoa(binary));pdf.addFont('NotoSans.ttf','NotoSans','normal');pdf.setFont('NotoSans'); | |
| let y=24; | |
| const write=(text,size=11,color='#25324b',gap=5)=>{ | |
| pdf.setFontSize(size);pdf.setTextColor(color); | |
| const lines=pdf.splitTextToSize(plainInline(text),166); | |
| const height=size*0.47; | |
| for(const line of lines){if(y+height>274){pdf.addPage();y=24;}pdf.text(line,22,y);y+=height;}y+=gap; | |
| }; | |
| write(args.title,25,'#444cc4',10); | |
| for(const t of blocks(args.markdown)) { | |
| if(t.type==='heading')write(t.text,t.depth===1?18:14,'#444cc4',5); | |
| else if(t.type==='list') t.items.forEach((item,i)=>write(`${t.ordered?`${i+1}.`:'•'} ${item.text}`,11,'#25324b',3)); | |
| else if(t.type==='table') {write(t.header.map(c=>c.text).join(' | '),10,'#444cc4',3);t.rows.forEach(r=>write(r.map(c=>c.text).join(' | '),10,'#25324b',3));} | |
| else write(t.text||t.raw,11); | |
| } | |
| const pages=pdf.getNumberOfPages();for(let i=1;i<=pages;i++){pdf.setPage(i);pdf.setDrawColor('#e0e4ed');pdf.line(22,282,188,282);pdf.setFontSize(8);pdf.setTextColor('#7c879b');pdf.text('MiniCPM5 · Created on your device',22,288);pdf.text(`${i} / ${pages}`,188,288,{align:'right'});} | |
| pdf.setProperties({title:args.title,creator:'MiniCPM5 · ProCreations'});blob=pdf.output('blob'); | |
| } | |
| const ext={html:'html',document:'docx',spreadsheet:'xlsx',pdf:'pdf'}[type]; | |
| return {id:crypto.randomUUID(),type,title:args.title,filename:`${filename}.${ext}`,args,blob,url:URL.createObjectURL(blob),createdAt:Date.now()}; | |
| } | |
| export function previewMarkup(artifact) { | |
| if(artifact.type==='html')return `<iframe title="${escapeHTML(artifact.title)} preview" sandbox="allow-scripts" referrerpolicy="no-referrer" srcdoc="${escapeHTML(sandboxHTML(artifact.args.html))}"></iframe>`; | |
| if(artifact.type==='pdf')return `<iframe title="${escapeHTML(artifact.title)} PDF preview" src="${artifact.url}#toolbar=0&view=FitH"></iframe>`; | |
| if(artifact.type==='document')return `<div class="paper"><div class="paper-brand">MINICPM5 / DOCUMENT</div><h1>${escapeHTML(artifact.title)}</h1>${renderMarkdown(artifact.args.markdown)}</div>`; | |
| return `<div class="workbook">${artifact.args.sheets.map((s,i)=>`<section class="worksheet"><div class="sheet-label"><span class="sheet-dot"></span>${escapeHTML(s.name||`Sheet ${i+1}`)}<small>${s.rows.length} rows</small></div><div class="table-scroll"><table><thead><tr><th></th>${s.columns.map(c=>`<th>${escapeHTML(c)}</th>`).join('')}</tr></thead><tbody>${s.rows.slice(0,200).map((r,ri)=>`<tr><th>${ri+1}</th>${s.columns.map((_,ci)=>`<td class="${typeof r[ci]==='number'?'numeric':''}">${escapeHTML(r[ci]??'')}</td>`).join('')}</tr>`).join('')}</tbody></table></div>${s.rows.length>200?'<p>Preview shows the first 200 rows. Download contains all rows.</p>':''}</section>`).join('')}<p class="sheet-note">Formula cells are shown as formulas here and recalculate in Excel.</p></div>`; | |
| } | |
| export function downloadArtifact(a) {const link=document.createElement('a');link.href=a.url;link.download=a.filename;link.click();} | |