@barbapapazes/content-creation 0.20.1 → 0.20.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.
- package/dist/cli.mjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{x-DuV_hNhq.mjs → x-Du8143e1.mjs} +9 -9
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{C as e,S as t,a as n,g as r,i,o as a,r as o,s,t as c,v as l,w as u,y as d}from"./x-
|
|
2
|
+
import{C as e,S as t,a as n,g as r,i,o as a,r as o,s,t as c,v as l,w as u,y as d}from"./x-Du8143e1.mjs";import f from"node:process";import{log as p}from"@clack/prompts";import{Command as m}from"commander";var h=`@barbapapazes/content-creation`,g=`0.20.2`,_=`CLI tool for content creation and management`;const v=new m;v.name(h).description(_).version(g).showHelpAfterError();const y=v.command(`content`);y.description(`Manage dated content`),y.command(`new`).description(`Create a dated content directory`).action(()=>u(f.cwd())),y.command(`upcoming`).description(`List upcoming publications`).action(()=>e(f.cwd())),y.command(`rebuild-indexes`).description(`Rebuild all content index files`).action(()=>t(f.cwd()));const b=v.command(`series`);b.description(`Manage article series`),b.command(`new`).description(`Create a new series`).action(()=>a(f.cwd())),b.command(`video`).description(`Manage series videos`).command(`process`).description(`Process a video from a series directory`).action(()=>i(f.cwd()));const x=b.command(`article`).description(`Manage series articles`);x.command(`new`).description(`Create a new article in a series`).action(()=>n(f.cwd())),x.command(`ready`).description(`Mark a series article as ready`).action(()=>o(f.cwd())),x.command(`estimate-time`).description(`Estimate the reading time of a series article`).action(()=>s(f.cwd()));const S=v.command(`linkedin`);S.description(`Manage LinkedIn publications`),S.command(`ready`).description(`Proofread a LinkedIn publication, create a checkpoint commit, and mark it as ready`).action(()=>l(f.cwd())),S.command(`publish-calendar`).description(`Publish the LinkedIn calendar`).action(()=>d(f.cwd()));const C=v.command(`x`);C.description(`Manage X publications`),C.command(`schedule-reminder`).description(`Schedule an X publication reminder`).action(()=>c(f.cwd()));const w=v.command(`resource`);w.description(`Manage resources`),w.command(`new`).description(`Create a new resource`).action(()=>r(f.cwd())),v.parseAsync().catch(e=>{p.error(e instanceof Error?e.message:String(e)),f.exit(1)});export{};
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{A as e,C as t,D as n,E as r,F as i,I as a,L as o,M as s,N as c,O as l,P as u,S as d,T as f,_ as p,a as m,b as h,c as g,d as _,f as v,g as y,h as b,i as x,j as S,k as C,l as w,m as T,n as E,o as D,p as O,r as k,s as A,t as j,u as M,v as N,w as P,x as F,y as I}from"./x-
|
|
1
|
+
import{A as e,C as t,D as n,E as r,F as i,I as a,L as o,M as s,N as c,O as l,P as u,S as d,T as f,_ as p,a as m,b as h,c as g,d as _,f as v,g as y,h as b,i as x,j as S,k as C,l as w,m as T,n as E,o as D,p as O,r as k,s as A,t as j,u as M,v as N,w as P,x as F,y as I}from"./x-Du8143e1.mjs";function L(e){return e}export{n as capitalize,P as contentNewWorkflow,t as contentUpcomingWorkflow,a as createContentDirectory,p as createResourceDirectory,_ as createSeriesArticle,M as createSeriesDirectory,v as createSeriesIndex,L as defineConfig,l as escapeRegExp,e as estimateReadingMinutesFromMarkdown,w as estimateSeriesArticleTime,O as getSeriesArticles,T as getSeriesDirectories,b as getSeriesRootPath,C as humanizeSlug,I as linkedinPublishCalendarWorkflow,N as linkedinReadyWorkflow,i as listUpcomingContent,o as loadContentCreationConfig,r as markEntryAsReady,g as markSeriesArticleReady,S as promptForRequiredText,F as publishLinkedInCalendar,s as readMarkdownDocument,h as readyLinkedInPublication,u as rebuildContentIndexes,d as rebuildContentIndexesWorkflow,y as resourceNewWorkflow,E as scheduleReminder,A as seriesArticleEstimateTimeWorkflow,m as seriesArticleNewWorkflow,k as seriesArticleReadyWorkflow,D as seriesNewWorkflow,x as seriesVideoProcessWorkflow,f as slugify,c as writeMarkdownDocument,j as xScheduleReminderWorkflow};
|
|
@@ -5,13 +5,13 @@ import e from"node:process";import{intro as t,isCancel as n,log as r,multiselect
|
|
|
5
5
|
`)}function ot(e){return`${e.ready?`Ready`:`Not ready`} · ${e.title} · ${O.linkedin}`}function st(e){return`linkedin-${le(`sha1`).update(e).digest(`hex`)}@barbapapazes`}function ct(e){let t=[`BEGIN:VCALENDAR`,`VERSION:2.0`,`PRODID:-//Barbapapazes//Content Creation LinkedIn Calendar//EN`,`CALSCALE:GREGORIAN`,`METHOD:PUBLISH`,`X-WR-CALNAME:${W(`content-creation.ics`)}`];for(let n of e){let e=tt(new Date(Date.UTC(n.date.getFullYear(),n.date.getMonth(),n.date.getDate()))),r=x(n.date,1);t.push(`BEGIN:VEVENT`,`UID:${st(n.relativePath)}`,`DTSTAMP:${e}`,`SUMMARY:${W(ot(n))}`,`DTSTART;VALUE=DATE:${nt(n.date)}`,`DTEND;VALUE=DATE:${nt(r)}`,`TRANSP:TRANSPARENT`,`DESCRIPTION:${W(at(n))}`,`END:VEVENT`)}return t.push(`END:VCALENDAR`),`${t.map(et).join(`\r
|
|
6
6
|
`)}\r\n`}function lt(){let t=v($e,`node_modules`,`.bin`,e.platform===`win32`?`wrangler.cmd`:`wrangler`);return c(t)?t:`wrangler`}function ut(t){(!t.calendar.publicUrl||!t.calendar.token)&&(r.error(`Calendar publishing configuration is missing. Please set CALENDAR_PUBLIC_URL and CALENDAR_TOKEN in your .env file or config.`),e.exit(1));let n=t.calendar.publicUrl.endsWith(`/`)?t.calendar.publicUrl:`${t.calendar.publicUrl}/`,i=new URL(U,n);return i.searchParams.set(`token`,t.calendar.token),i.toString()}function dt(e){return N(e,{contentTypes:[`linkedin`],sort:`date-asc`}).map(e=>{let t=e.frontmatter;return{...e,title:t.title||e.title,ready:t.ready===!0,theme:t.theme,video:t.video,imageCount:t.images?.filter(Boolean).length??0}})}function ft(t){let n=lt();try{ce(n,[`r2`,`object`,`put`,`content-creation/${U}`,`--pipe`,`--content-type`,`text/calendar; charset=utf-8`,`--remote`],{cwd:$e,stdio:[`pipe`,`inherit`,`inherit`],env:e.env,input:t})}catch(t){r.error(`Failed to upload LinkedIn calendar: ${t instanceof Error?t.message:String(t)}`),e.exit(1)}}async function pt(e,t){let n=dt(e);if(n.length===0)return r.info(`No LinkedIn publications found. Skipping calendar upload.`),null;let i=ut(t);return ft(ct(n)),r.success(`✓ LinkedIn calendar uploaded to R2 as ${U}`),r.info(`Subscription URL: ${i}`),i}function mt(e){let t=[];try{let n=f(e);for(let r of n){if(!p(v(e,r)).isFile())continue;let n=r.toLowerCase().substring(r.lastIndexOf(`.`));Ee.includes(n)&&t.push(r)}}catch(e){P(`Error reading directory: ${e instanceof Error?e.message:String(e)}`)}return t.sort()}function ht(e,t){try{let{content:n,frontmatter:i}=I(e.path);L(e.path,{content:n,frontmatter:{...i,images:t.length>0?t:[null]}}),r.success(`LinkedIn publication updated: ${e.relativePath} (${t.length} image(s))`)}catch(e){P(`Failed to update LinkedIn publication: ${e instanceof Error?e.message:String(e)}`)}}function gt(e){let t=mt(e.folderPath);t.length===0?r.info(`No images found for LinkedIn publication: ${e.relativePath}`):r.info(`Found ${t.length} image(s) for ${e.relativePath}: ${t.join(`, `)}`),ht(e,t),V({path:e.path,relativePath:e.relativePath},`linkedin publication`);let n=v(e.folderPath,`linkedin-script.md`),i=e.relativePath.slice(0,e.relativePath.lastIndexOf(`/`)),a=c(n);return a&&V({path:n,relativePath:`${i}/linkedin-script.md`},`linkedin script`),{imageCount:t.length,scriptMarked:a}}async function _t(e){if(t(`Content Creation - Publish LinkedIn Calendar`),await pt(e,await T())){a(`✓ LinkedIn calendar published successfully`);return}a(`✓ No LinkedIn publications found, calendar was not updated`)}function vt(e){let t=k.linkedin,n=e.relativePath.slice(0,e.relativePath.lastIndexOf(`/`)),r=[{kind:`publication`,path:e.path,relativePath:e.relativePath,isMain:!0}];for(let i of t.additionalFiles??[]){let t=v(e.folderPath,i);c(t)&&r.push({kind:i===`linkedin-script.md`?`script`:`publication`,path:t,relativePath:`${n}/${i}`,isMain:!1})}return r}async function yt(e){return Re({basePath:e,contentTypes:[`linkedin`],message:`Which LinkedIn publication do you want to polish and mark as ready?`,emptyMessage:`No LinkedIn publications found in dated folders`,sort:`date-desc`})}function K(t,n,r={}){return fe(`git`,n,{throwOnError:!0,nodeOptions:{cwd:t,env:{...e.env,...r}}}).stdout.trim()}function bt(e,t,n){let r=u(v(de(),`content-creation-linkedin-ready-`)),i={GIT_INDEX_FILE:v(r,`index`)};try{K(e,[`rev-parse`,`--is-inside-work-tree`]),K(e,[`read-tree`,`HEAD`],i);let r=n.map(t=>y(e,t.path));if(r.length===0)return{created:!1,message:`No related LinkedIn files found to checkpoint.`};K(e,[`add`,`--`,...r],i);try{return K(e,[`diff`,`--cached`,`--quiet`,`--exit-code`],i),{created:!1,message:`No changes detected in the LinkedIn publication files. Skipping checkpoint commit.`}}catch{let n=`chore(linkedin): checkpoint ${t} before ready polish`;return K(e,[`commit`,`--no-gpg-sign`,`-m`,n],i),{created:!0,commitHash:K(e,[`rev-parse`,`HEAD`]),message:n}}}catch(e){throw Error(`Failed to create LinkedIn checkpoint commit: ${Le(e)}`)}finally{te(r,{recursive:!0,force:!0})}}const xt=`linkedin-ready-editor`;function St(e){let t=e.trim();if(!t.startsWith("```")||!t.endsWith("```"))return t;let n=t.split(`
|
|
7
7
|
`);return n.length<3?t:n.slice(1,-1).join(`
|
|
8
|
-
`).trim()}function Ct(e,t,n){let r=b(e,t);return c(r)||P(`Missing ${n}: ${r}`),r}function wt(e,t){let n=
|
|
9
|
-
`)?n:`${n}\n`}function
|
|
10
|
-
`)?n:`${n}\n`}function
|
|
8
|
+
`).trim()}function Ct(e,t,n){let r=b(e,t);return c(r)||P(`Missing ${n}: ${r}`),r}function wt(e,t){let n=St(e),r=C(n);return(typeof r.data.title!=`string`||r.data.title.trim().length===0)&&P(`Invalid Copilot response for ${t}: missing frontmatter title.`),n.endsWith(`
|
|
9
|
+
`)?n:`${n}\n`}function Tt(e,t){let n=St(e);return n.length===0&&P(`Invalid Copilot response for ${t}: empty content.`),n.endsWith(`
|
|
10
|
+
`)?n:`${n}\n`}function Et(){return[`You are polishing LinkedIn publication files before they are published to LinkedIn.`,`Return only the corrected file content. Never add explanations, summaries, or Markdown code fences around the file content.`].join(`
|
|
11
11
|
|
|
12
|
-
`)}function
|
|
13
|
-
`)}function
|
|
14
|
-
`)}async function
|
|
15
|
-
`)}function
|
|
16
|
-
`).map(e=>e.trim()).find(e=>e.startsWith(`# `));if(e)return e.slice(2).trim()}return z(t)}function
|
|
17
|
-
- `)}`)}async function
|
|
12
|
+
`)}function Dt(e,t){let n=t.filter(e=>!e.isMain).map(e=>e.relativePath),r=n.length>0?`Related files in this publication folder: ${n.join(`, `)}.`:`There are no related Markdown files in this publication folder.`;return[`Prepare the attached LinkedIn publication file for social publishing: ${e.relativePath}.`,r,`Use the LinkedIn correction skill and the provided guidance to fix typos, grammar, punctuation, spacing, and minor formatting issues.`,`Make the post social-network ready without rewriting its meaning or personality.`,`You may improve the frontmatter title, but keep all other frontmatter keys intact unless correcting an obvious formatting issue.`,`Modify the file content as needed, but don't explain your changes.`].join(`
|
|
13
|
+
`)}function Ot(e){return[`Proofread the attached Markdown file: ${e.relativePath}.`,`Fix typos, grammar, punctuation, spacing, and light formatting issues only.`,`Preserve the original meaning, structure, tone, and voice.`,`Modify the file content as needed, but don't explain your changes.`].join(`
|
|
14
|
+
`)}async function kt(e,t,n,r){let i=Ct(e,`.github/skills`,`Copilot skills directory`),a=new pe;await a.start();let o;try{o=await a.createSession({...r.model?{model:r.model}:{},...r.reasoningEffort?{reasoningEffort:r.reasoningEffort}:{},workingDirectory:e,skillDirectories:[i],customAgents:[{name:xt,displayName:`LinkedIn Ready Editor`,description:`Proofreads and polishes LinkedIn publication files before they are marked as ready.`,prompt:Et()}],agent:xt,onPermissionRequest:me});let s=n.find(e=>e.isMain);s||P(`Unable to find the main LinkedIn publication file to polish.`);let c=(await o.sendAndWait({prompt:Dt(t,n),attachments:[{type:`file`,path:s.path,displayName:h(s.path)}]}))?.data.content;typeof c!=`string`&&P(`Copilot did not return corrected content for ${s.relativePath}.`),m(s.path,wt(c,s.relativePath),`utf-8`);for(let e of n.filter(e=>!e.isMain)){let t=(await o.sendAndWait({prompt:Ot(e),attachments:[{type:`file`,path:e.path,displayName:h(e.path)}]}))?.data.content;typeof t!=`string`&&P(`Copilot did not return corrected content for ${e.relativePath}.`),m(e.path,Tt(t,e.relativePath),`utf-8`)}}catch(e){P(`Failed to polish the LinkedIn publication with Copilot: ${e instanceof Error?e.message:String(e)}`)}finally{await o?.disconnect(),await a.stop()}}async function At(e){t(`Content Creation - Polish and Mark LinkedIn Publication Ready`);let n=await T(),i=await yt(e),o=vt(i),s=y(e,i.folderPath);r.info(`Preparing ${i.relativePath} with ${o.length} Markdown file(s).`);let c=bt(e,s,o);c.created?r.success(`Checkpoint commit created: ${c.commitHash}`):r.warn(c.message),await kt(e,i,o,n.linkedin.ready.copilot);let l=gt(i),u=l.scriptMarked?`script marked ready`:`no script found`,d=c.created?`checkpoint ${c.commitHash} created`:`no checkpoint commit created`;a(`✓ LinkedIn publication ready: ${i.relativePath} (${o.length} file(s) reviewed, ${l.imageCount} image(s), ${u}, ${d}; final changes left uncommitted)`)}function jt(e,t,n){let i=H(e),a=v(b(v(n,`resources`)),i),o=`${t}.md`,s=v(a,o);if(c(s))return r.info(`${o} already exists at: ${s}`),a;l(a,{recursive:!0}),r.success(`Created directory: ${a}`);let u={title:e,url:``,date:``};return m(s,C.stringify(``,u),`utf-8`),r.success(`Created ${o} at: ${s}`),a}async function Mt(){let e=F(await o({message:`What type of resource is this?`,options:[{label:`Article`,value:`article`,hint:`Create article.md`},{label:`Video`,value:`video`,hint:`Create video.md`},{label:`Audio`,value:`audio`,hint:`Create audio.md`},{label:`Tweet`,value:`tweet`,hint:`Create tweet.md`}]}));return[`article`,`video`,`audio`,`tweet`].includes(String(e))||P(`Unable to resolve resource type: ${String(e)}`),e}async function Nt(){return R({message:`What is the title of your content?`,placeholder:`Enter content title`,requiredMessage:`Title is required`})}async function Pt(e){t(`Content Creation - Create Resource`);let n=await Nt(),r=await Mt();jt(n,r,e),a(`✓ Resource created: resources/${H(n)}/${r}.md`)}const Ft=`## Index`,q=`<!-- content-creation:series-index:start -->`,J=`<!-- content-creation:series-index:end -->`,It=/^(\d+)\.([^.]+(?:\.[^.]+)*)\.md$/;function Y(e){return b(v(e,`series`))}function Lt(e){let t=Y(e);return c(t)?f(t).filter(e=>Vt(v(t,e))).map(e=>Ht(t,e)).sort((e,t)=>e.title.localeCompare(t.title,`fr`)):[]}function X(e){return f(e).map(Kt).filter(e=>e!==null).map(t=>Ut(e,t)).sort((e,t)=>e.index-t.index)}function Z(e){let t=X(e),n=v(e,`README.md`);m(n,Rt(c(n)?d(n,`utf-8`):``,t,e),`utf-8`),r.success(`Generated series index: ${n}`)}function Rt(e,t,n){let r=zt(t);if(e.includes(q)&&e.includes(J))return e.replace(Bt(),r);let i=e.trimEnd();return i.length>0?`${i}\n\n${r}\n`:`# ${z(n.split(`/`).pop()||`series`)}\n\n${r}\n`}function zt(e){let t=[Ft,``,q];if(e.length===0)t.push(``,`_No articles yet._`);else{t.push(``);for(let n of e)t.push(`${n.index}. [${n.title}](./${n.fileName})`)}return t.push(``,J),t.join(`
|
|
15
|
+
`)}function Bt(){return RegExp(`${B(Ft)}\n\n${B(q)}[\\s\\S]*?${B(J)}`)}function Vt(e){return p(e).isDirectory()}function Ht(e,t){let n=v(e,t);return{name:t,path:n,title:Wt(n,t)}}function Ut(e,t){let n=v(e,t.fileName);return{...t,path:n,title:Gt(n,t.slug)}}function Wt(e,t){let n=v(e,`README.md`);if(c(n)){let e=d(n,`utf-8`).split(`
|
|
16
|
+
`).map(e=>e.trim()).find(e=>e.startsWith(`# `));if(e)return e.slice(2).trim()}return z(t)}function Gt(e,t){try{let{data:t}=C(d(e,`utf-8`)),n=typeof t.title==`string`?t.title.trim():``;if(n.length>0)return n}catch(t){r.warn(`Unable to read article title from ${e}: ${t}`)}return z(t)}function Kt(e){let t=e.match(It);return t?{index:Number(t[1]),slug:t[2],fileName:e}:null}function qt(e,t,n){let i=X(e),a=Yt(n,i.length),o=v(e,`${a}.${H(t)}.md`);if(c(o))throw Error(`Article already exists at ${o}`);return Jt(e,i,a),m(o,C.stringify(``,{title:t}),`utf-8`),r.success(`Created article: ${o}`),Z(e),o}function Jt(e,t,n){let i=t.filter(e=>e.index>=n).sort((e,t)=>t.index-e.index);for(let t of i){let n=`${t.index+1}.${t.slug}.md`,i=v(e,n);ee(t.path,i),r.info(`Renamed ${t.fileName} → ${n}`)}}function Yt(e,t){if(!Number.isInteger(e))throw TypeError(`Article index must be an integer`);if(e<1||e>t+1)throw RangeError(`Article index must be between 1 and ${t+1}`);return e}function Xt(e,t){let n=t.trim();if(n.length===0)throw Error(`Series title is required`);let i=H(n),a=Y(e),o=v(a,i);if(l(a,{recursive:!0}),c(o))throw Error(`Series already exists: series/${i}`);return l(o),m(v(o,`README.md`),`# ${n}\n`,`utf-8`),Z(o),r.success(`Created series: ${o}`),{name:i,path:o,title:n}}function Q(e,t){let{content:n,frontmatter:i}=I(e),a=Ke(n,t);return L(e,{content:n,frontmatter:{...i,time:a}}),r.success(`Estimated time set to ${a} min: ${e}`),a}function Zt(e){V({path:e.path,relativePath:e.fileName},`series article`)}async function Qt(e){let t=X(e);if(t.length===0&&P(`No series articles found`),t.length===1)return t[0];let n=F(await o({message:`Which series article do you want to update?`,options:t.map(e=>({label:`#${e.index} · ${e.title}`,value:e.path,hint:e.fileName}))}));typeof n!=`string`&&P(`Unable to resolve selected series article: ${String(n)}`);let r=t.find(e=>e.path===n);return r||P(`Unable to resolve selected series article: ${n}`),r}async function $t(){return R({message:`What is the title of your article?`,placeholder:`Enter article title`,requiredMessage:`Title is required`})}async function $(e){let t=Lt(e);if(t.length===0&&P(`No series directories found`),t.length===1)return t[0];let n=F(await o({message:`Which series do you want to work on?`,options:t.map(e=>({label:e.title,value:e.path,hint:`series/${e.name}`}))}));typeof n!=`string`&&P(`Unable to resolve selected series: ${String(n)}`);let r=t.find(e=>e.path===n);return r||P(`Unable to resolve selected series: ${n}`),r}async function en(e){let t=X(e),n=t.map(e=>({label:`Insert at #${e.index} · before ${e.title}`,value:String(e.index),hint:e.fileName}));n.push({label:`Append as #${t.length+1}`,value:String(t.length+1),hint:`Add the new article at the end of the series`});let r=F(await o({message:`Where should the new article be inserted?`,options:n}));return typeof r!=`string`&&P(`Unable to resolve selected insert position: ${String(r)}`),Number(r)}async function tn(){return R({message:`What is the title of your series?`,placeholder:`Enter series title`,requiredMessage:`Title is required`})}function nn(e){return rn(e,e).sort((e,t)=>e.relativePath.localeCompare(t.relativePath))}function rn(e,t){let n=f(t,{withFileTypes:!0}),r=[];for(let i of n){let n=v(t,i.name);if(i.isDirectory()){r.push(...rn(e,n));continue}!i.isFile()||_(i.name).toLowerCase()!==`.mp4`||r.push({name:i.name,path:n,relativePath:y(e,n)})}return r}async function an(e){let t=nn(e);if(t.length===0&&P(`No .mp4 files found in series directory: ${e}`),t.length===1)return t[0];let n=F(await o({message:`Which series video do you want to process?`,options:t.map(e=>({label:e.relativePath,value:e.path,hint:e.name}))}));typeof n!=`string`&&P(`Unable to resolve selected series video: ${String(n)}`);let r=t.find(e=>e.path===n);return r||P(`Unable to resolve selected series video: ${n}`),r}async function on(){let e=await s({message:`Enter text for the thumbnail (or press Enter to skip):`,placeholder:`Optional thumbnail text`});if(typeof e!=`symbol`)return e.trim()||void 0}async function sn(e){let t=cn(e);if(t.length===0){r.error(`No templates found in ${e||`the configured templates directory`}`),r.info(`Please add SVG templates before generating thumbnails.`);return}let n=await o({message:`Choose a template:`,options:t.map(e=>({label:e,value:e}))});if(typeof n!=`symbol`)return n}function cn(e){if(!e||!c(e))return[];try{return f(e,{withFileTypes:!0}).filter(e=>e.isFile()&&_(e.name).toLowerCase()===`.svg`).map(e=>e.name.replace(/\.svg$/i,``)).sort((e,t)=>e.localeCompare(t))}catch{return[]}}async function ln(e){t(`Content Creation - Estimate Series Article Time`);let n=await T(),r=await $(e),i=await Qt(r.path),o=Q(i.path,n.reading.wordsPerMinute);a(`✓ Estimated time updated for ${r.name}/${i.fileName}: ${o} min`)}async function un(e){t(`Content Creation - Create Series`),a(`✓ Series created: series/${Xt(e,await tn()).name}`)}async function dn(e){t(`Content Creation - Create Series Article`);let n=await $(e),r=await $t(),i=await en(n.path),o=qt(n.path,r,i);a(`✓ Series article created: ${n.name}/${h(o)}`)}async function fn(e){let n=await T();n.videoProcessing.openaiApiKey||P(`OpenAI API key is required. Set OPENAI_API_KEY in .env or configure videoProcessing.openaiApiKey in content-creation.config.{ts,js,mjs,json}.`);let i=await $(e),o=await an(i.path);t(`Content Creation - Process Series Video: ${h(o.path)}`);let{videoPath:s,audioPath:c}=await ge(o.path),{srtPath:l}=await ve(s,c,{openaiApiKey:n.videoProcessing.openaiApiKey,language:n.videoProcessing.language,model:n.videoProcessing.model,templatesDir:n.templatesDir});he(c,`audio file`);let u=await on();if(!u){a(`✓ Transcription saved to: ${l}`);return}let d=await sn(n.templatesDir);if(!d){r.warn(`No template selected. Skipping thumbnail generation.`),a(`✓ Transcription saved to: ${l}`);return}let{thumbnailPaths:f}=await _e(s,u,d,n.templatesDir);a(`✓ Series video processed: series/${i.name}/${o.relativePath}\n✓ Transcription saved to: ${l}\n✓ Thumbnails saved:\n - ${f.join(`
|
|
17
|
+
- `)}`)}async function pn(e){t(`Content Creation - Mark Series Article Ready`);let n=await T(),r=await $(e),i=await Qt(r.path);Zt(i);let o=Q(i.path,n.reading.wordsPerMinute);a(`✓ Series article updated for ${r.name}/${i.fileName}: ready + ${o} min`)}async function mn(e,t){let n=e.path,{content:i,frontmatter:a}=I(n);if(a.scheduled===!0)return r.warn(`This X publication is already scheduled. Skipping.`),!1;(!t.scheduling.automationEndpoint||!t.scheduling.cfAccessClientId||!t.scheduling.cfAccessClientSecret)&&P(`Scheduling configuration is missing. Please set AUTOMATION_ENDPOINT, CF_ACCESS_CLIENT_ID, and CF_ACCESS_CLIENT_SECRET in your .env file or config.`);let o=new Date(e.date);o=ie(o,j.hours),o=ae(o,j.minutes),o=oe(o,j.seconds);let s={content:i.trim(),scheduleAt:o.getTime()};try{let e=await fetch(t.scheduling.automationEndpoint,{method:`POST`,headers:{"Content-Type":`application/json`,Accept:`application/json`,"CF-Access-Client-Id":t.scheduling.cfAccessClientId,"CF-Access-Client-Secret":t.scheduling.cfAccessClientSecret},body:JSON.stringify(s)});if(!e.ok){let t=await e.text();P(`Failed to schedule reminder: ${e.status} ${e.statusText}\n${t}`)}let o=await e.json();L(n,{content:i,frontmatter:{...a,scheduled:!0}});let c=new Date(o.scheduledAt);return r.success(`✓ X publication reminder scheduled`),r.info(`Reminder scheduled for: ${S(c,`yyyy-MM-dd HH:mm:ss`)} UTC`),!0}catch(e){P(`Failed to schedule X publication reminder: ${e instanceof Error?e.message:String(e)}`)}}async function hn(e){return Re({basePath:e,contentTypes:[`x`],message:`Which X publication do you want to schedule a reminder for?`,emptyMessage:`No X publications found in dated folders`,sort:`date-desc`})}async function gn(e){t(`Content Creation - Schedule X Publication Reminder`);let n=await T();a(await mn(await hn(e),n)?`✓ X publication reminder scheduled`:`✓ X publication was already scheduled`)}export{Ke as A,Ze as C,qe as D,V as E,Ne as F,M as I,T as L,I as M,L as N,B as O,Fe as P,Qe as S,H as T,jt as _,dn as a,gt as b,Zt as c,qt as d,Z as f,Pt as g,Y as h,fn as i,R as j,z as k,Q as l,Lt as m,mn as n,un as o,X as p,pn as r,ln as s,gn as t,Xt as u,At as v,Xe as w,pt as x,_t as y};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barbapapazes/content-creation",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.20.
|
|
4
|
+
"version": "0.20.2",
|
|
5
5
|
"description": "CLI tool for content creation and management",
|
|
6
6
|
"author": "Estéban Soubiran <esteban@soubiran.dev>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"gray-matter": "^4.0.3",
|
|
40
40
|
"tinyexec": "1.1.2",
|
|
41
41
|
"wrangler": "^4.61.1",
|
|
42
|
-
"@barbapapazes/video-toolkit": "0.20.
|
|
42
|
+
"@barbapapazes/video-toolkit": "0.20.2"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@tsconfig/node24": "^24.0.4",
|