@barbapapazes/content-creation 0.17.2 → 0.18.0

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/README.md CHANGED
@@ -14,6 +14,7 @@ A CLI tool to streamline multi-platform content creation by generating dated dir
14
14
  - List upcoming content from today onward with absolute file paths
15
15
  - Generate and upload a LinkedIn publication calendar for Google Calendar subscriptions
16
16
  - Link images to LinkedIn post frontmatter
17
+ - Mark a publication as ready by setting `ready: true` in frontmatter
17
18
  - Create resource directories (articles, videos, audio)
18
19
 
19
20
  ## Installation
@@ -205,6 +206,23 @@ CF_ACCESS_CLIENT_SECRET=your-client-secret-here
205
206
 
206
207
  See `.env.example` for a template.
207
208
 
209
+ ### Mark Publication as Ready
210
+
211
+ Mark a publication as ready by setting `ready: true` in the selected markdown file frontmatter:
212
+
213
+ ```bash
214
+ # Mark a publication as ready from the current directory
215
+ content-creation ready
216
+
217
+ # Mark a publication as ready from a specific content directory
218
+ content-creation ready --path /path/to/content
219
+ ```
220
+
221
+ This command will:
222
+ 1. Scan your `YYYY/MM/DD` directory structure for publication files
223
+ 2. Prompt you to select which publication to update
224
+ 3. Add `ready: true` to the selected file frontmatter
225
+
208
226
  ## Configuration
209
227
 
210
228
  You can configure the tool using a configuration file. Create one of the following files:
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import e from"node:process";import{intro as t,isCancel as n,log as r,multiselect as i,outro as a,select as o,text as s}from"@clack/prompts";import{cac as c}from"cac";import{addDays as l,format as u,parse as d,setHours as ee,setMinutes as te,setSeconds as ne}from"date-fns";import{existsSync as f,mkdirSync as p,readFileSync as m,readdirSync as h,statSync as g,writeFileSync as _}from"node:fs";import{dirname as v,isAbsolute as re,join as y,resolve as b}from"node:path";import x from"gray-matter";import{loadConfig as S}from"c12";import{execFileSync as C}from"node:child_process";import{createHash as w}from"node:crypto";import{fileURLToPath as T}from"node:url";var E=`0.17.2`;const D={linkedin:{mainFile:`linkedin.md`,additionalFiles:[`linkedin-script.md`]},x:{mainFile:`x.md`},youtube:{mainFile:`youtube-script.md`,additionalFiles:[`youtube-description.md`]},instagram:{mainFile:`instagram-script.md`,additionalFiles:[`instagram-description.md`]}},ie={thematic:[],templatesDir:void 0,templates:{},scheduling:{},calendar:{}};function ae(t,n){return t?re(t)?t:b(n?v(n):e.cwd(),t):n?v(n):e.cwd()}function oe(e,t){let n={};if(e?.footerPath){let r=b(t,e.footerPath);f(r)&&(n.footerPath=r)}return n}function O(e,t){let n={};if(e?.templatePath){let r=b(t,e.templatePath);f(r)&&(n.templatePath=r)}return n}async function k(){let{config:t,configFile:n}=await S({name:`content-creation`,defaults:ie,globalRc:!0,dotenv:!0}),r=ae(t.templatesDir,n),i={linkedin:oe(t.templates?.linkedin,r),youtube:O(t.templates?.youtube,r),instagram:O(t.templates?.instagram,r)},a={automationEndpoint:t.scheduling?.automationEndpoint||e.env.AUTOMATION_ENDPOINT,cfAccessClientId:t.scheduling?.cfAccessClientId||e.env.CF_ACCESS_CLIENT_ID,cfAccessClientSecret:t.scheduling?.cfAccessClientSecret||e.env.CF_ACCESS_CLIENT_SECRET},o={publicUrl:t.calendar?.publicUrl||e.env.CALENDAR_PUBLIC_URL,token:t.calendar?.token||e.env.CALENDAR_TOKEN};return{thematic:t.thematic||[],templatesDir:t.templatesDir||``,templates:i,scheduling:a,calendar:o}}function A(e){return f(e)?m(e,`utf-8`):``}function se(t,n,i,a,o=e.cwd()){let s=b(y(o,u(t,`yyyy`),u(t,`MM`),u(t,`dd`)));f(s)||(p(s,{recursive:!0}),r.success(`Created directory: ${s}`));for(let e of n)ce(e,s,i,a);return s}function ce(e,t,n,i){let a=D[e],o=y(t,a.mainFile);if(f(o)?r.info(`${a.mainFile} already exists, skipping`):j(e,o,n,i),a.additionalFiles)for(let o of a.additionalFiles){let a=y(t,o);N(o,e,n)&&(f(a)?r.info(`${o} already exists, skipping`):M(e,a,o,i))}}function j(e,t,n,i){let a={title:n.title};e===`linkedin`&&(n.theme&&(a.theme=n.theme),n.hasVideo&&(a.video=!0),n.hasImages&&(a.images=[null]));let o=``;if(e===`linkedin`){let e=i.templates.linkedin?.footerPath;o=e?A(e):``}_(t,x.stringify(o,a),`utf-8`),r.success(`Created ${t}`)}function M(e,t,n,i){let a=``;if(n.endsWith(`-description.md`)){let t=i.templates[e]?.templatePath;t&&(a=A(t))}_(t,a,`utf-8`),r.success(`Created ${t}`)}function N(e,t,n){return t===`linkedin`&&e===`linkedin-script.md`?n.hasVideo||!1:!0}const P=[`linkedin`,`x`,`youtube`,`instagram`],F={linkedin:`LinkedIn`,x:`X`,youtube:`YouTube`,instagram:`Instagram`};function I(e,t){let n=[],i=D[t].mainFile;try{let t=h(e).filter(t=>g(y(e,t)).isDirectory()&&/^\d{4}$/.test(t));for(let a of t){let t=y(e,a),o=h(t).filter(e=>g(y(t,e)).isDirectory()&&/^\d{2}$/.test(e));for(let e of o){let o=y(t,e),s=h(o).filter(e=>g(y(o,e)).isDirectory()&&/^\d{2}$/.test(e));for(let t of s){let s=b(y(o,t),i);if(!f(s))continue;let c=`${a}-${e}-${t}`,l=new Date(Number(a),Number(e)-1,Number(t));try{let{data:r}=x(m(s,`utf-8`)),o=r.title||`Untitled (${c})`;n.push({path:s,date:l,title:o,relativePath:`${a}/${e}/${t}/${i}`})}catch(e){r.warn(`Error reading ${s}: ${e}`)}}}}}catch(e){return r.error(`Error reading directories: ${e}`),[]}return n.sort((e,t)=>t.date.getTime()-e.date.getTime())}function L(e){switch(e){case`linkedin`:return`linkedin-posts.md`;case`x`:return`x-posts.md`;case`youtube`:return`youtube-videos.md`;case`instagram`:return`instagram-posts.md`}}function R(e){switch(e){case`linkedin`:return`LinkedIn Posts`;case`x`:return`X Posts`;case`youtube`:return`YouTube Videos`;case`instagram`:return`Instagram Posts`}}function z(e,t){let n=I(e,t);if(n.length===0){r.info(`No ${t} posts found`);return}let i=R(t),a=L(t),o=`# ${i}\n\n`;o+=`_Generated on ${new Date().toLocaleDateString()}_\n\n`,o+=`Total posts: ${n.length}\n\n`;for(let e of n){let t=e.date.toLocaleDateString(`en-US`,{year:`numeric`,month:`long`,day:`numeric`});o+=`- [${e.title}](${e.relativePath}) - _${t}_\n`}_(y(e,a),o,`utf-8`),r.success(`Created ${a} with ${n.length} posts`)}function B(t=e.cwd(),n){let r=n||[...P];for(let e of r)z(t,e)}function V(e){return e.toLowerCase().trim().normalize(`NFD`).replace(/[\u0300-\u036F]/g,``).replace(/[^a-z0-9\s-]/g,``).replace(/\s+/g,`-`).replace(/-+/g,`-`).replace(/^-+|-+$/g,``)||`untitled`}function H(t,n,i=e.cwd()){let a=V(t),o=y(b(y(i,`resources`)),a),s=`${n}.md`,c=y(o,s);if(f(c))return r.info(`${s} already exists at: ${c}`),o;p(o,{recursive:!0}),r.success(`Created directory: ${o}`);let l={title:t,url:``,date:``};return _(c,x.stringify(``,l),`utf-8`),r.success(`Created ${s} at: ${c}`),o}function U(t=e.cwd()){let n=[];try{let e=h(t).filter(e=>g(y(t,e)).isDirectory()&&/^\d{4}$/.test(e));for(let r of e){let e=y(t,r),i=h(e).filter(t=>g(y(e,t)).isDirectory()&&/^\d{2}$/.test(t));for(let t of i){let i=y(e,t),a=h(i).filter(e=>g(y(i,e)).isDirectory()&&/^\d{2}$/.test(e));for(let e of a){let a=y(i,e);if(f(y(a,`linkedin.md`))){let i=`${r}-${t}-${e}`;n.push({path:a,date:new Date(i),displayPath:`${r}/${t}/${e}`})}}}}}catch(e){return r.error(`Error reading directories: ${e}`),[]}return n.sort((e,t)=>t.date.getTime()-e.date.getTime()).slice(0,8)}function W(e){let t=[`.jpg`,`.jpeg`,`.png`],n=[];try{let r=h(e);for(let i of r)if(g(y(e,i)).isFile()){let e=i.toLowerCase().substring(i.lastIndexOf(`.`));t.includes(e)&&n.push(i)}}catch(e){r.error(`Error reading directory: ${e}`)}return n.sort()}function G(e,t){try{let{data:n,content:i}=x(m(e,`utf-8`));n.images=t.length>0?t:[null],_(e,x.stringify(i,n),`utf-8`),r.success(`Updated ${e} with ${t.length} image(s)`)}catch(e){r.error(`Error updating frontmatter: ${e}`)}}async function le(t){if(t.length===0)return r.warn(`No dated folders with linkedin.md found`),null;let i=await o({message:`Select a folder to link images:`,options:t.map(e=>({label:e.displayPath,value:e.path,hint:`Link images in ${e.displayPath}`}))});return n(i)&&(r.error(`Operation cancelled.`),e.exit(0)),t.find(e=>e.path===i)||null}async function ue(t=e.cwd()){let n=U(t);if(n.length===0){r.warn(`No dated folders with linkedin.md found`);return}let i=await le(n);if(!i)return;let a=W(i.path);if(a.length===0){r.info(`No images found in ${i.displayPath}`),G(y(i.path,`linkedin.md`),[]);return}r.info(`Found ${a.length} image(s): ${a.join(`, `)}`),G(y(i.path,`linkedin.md`),a)}function de(e){let t=new Date;t.setHours(0,0,0,0);let n=P.flatMap(t=>I(e,t).map(e=>({...e,contentType:t}))).filter(e=>e.date.getTime()>=t.getTime()).sort((e,t)=>{let n=e.date.getTime()-t.date.getTime();return n===0?P.indexOf(e.contentType)-P.indexOf(t.contentType):n});if(n.length===0){r.info(`No upcoming content found from today onward.`);return}r.info(`Found ${n.length} upcoming content item${n.length===1?``:`s`}:`),console.log(``);for(let e of n){let t=u(e.date,`EEEE, MMMM d, yyyy`),n=u(e.date,`yyyy-MM-dd`);console.log(`${t} (${n}) · ${F[e.contentType]} · ${e.title}`),console.log(e.path),console.log(``)}}const K=T(new URL(`../../`,import.meta.url)),q=`content-creation.ics`;function J(e){return e.replace(/\\/g,`\\\\`).replace(/\r\n|\r|\n/g,`\\n`).replace(/;/g,`\\;`).replace(/,/g,`\\,`)}function fe(e){if(e.length<=75)return e;let t=[],n=e;for(;n.length>75;)t.push(n.slice(0,75)),n=` ${n.slice(75)}`;return t.push(n),t.join(`\r
3
- `)}function pe(e){return e.toISOString().replace(/[-:]/g,``).replace(/\.\d{3}Z$/,`Z`)}function Y(e){return u(e,`yyyyMMdd`)}function X(e){return e.split(`/`).map(e=>encodeURIComponent(e)).join(`/`)}function me(e){return`https://github.com/barbapapazes/content-creation/blob/main/${X(e)}`}function he(e){let t=X(e);return`vscode://file${t.startsWith(`/`)?``:`/`}${t}`}function ge(e){let t=[`GitHub: ${me(e.relativePath)}`,`VS Code: ${he(e.path)}`];return e.theme&&t.push(`Theme: ${e.theme}`),typeof e.video==`boolean`&&t.push(`Video planned: ${e.video?`yes`:`no`}`),e.imageCount>0&&t.push(`Images planned: ${e.imageCount}`),t.join(`
4
- `)}function _e(e){return`linkedin-${w(`sha1`).update(e).digest(`hex`)}@barbapapazes`}function ve(e){let t=[`BEGIN:VCALENDAR`,`VERSION:2.0`,`PRODID:-//Barbapapazes//Content Creation LinkedIn Calendar//EN`,`CALSCALE:GREGORIAN`,`METHOD:PUBLISH`,`X-WR-CALNAME:${J(`content-creation.ics`)}`];for(let n of e){let e=pe(new Date(Date.UTC(n.date.getFullYear(),n.date.getMonth(),n.date.getDate()))),r=l(n.date,1);t.push(`BEGIN:VEVENT`,`UID:${_e(n.relativePath)}`,`DTSTAMP:${e}`,`SUMMARY:${J(`${n.title} · ${F.linkedin}`)}`,`DTSTART;VALUE=DATE:${Y(n.date)}`,`DTEND;VALUE=DATE:${Y(r)}`,`TRANSP:TRANSPARENT`,`DESCRIPTION:${J(ge(n))}`,`END:VEVENT`)}return t.push(`END:VCALENDAR`),`${t.map(fe).join(`\r
5
- `)}\r\n`}function ye(){let t=y(K,`node_modules`,`.bin`,e.platform===`win32`?`wrangler.cmd`:`wrangler`);return f(t)?t:`wrangler`}function be(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(q,n);return i.searchParams.set(`token`,t.calendar.token),i.toString()}function xe(e){return I(e,`linkedin`).map(e=>{let t={title:e.title};try{t=x(m(e.path,`utf-8`)).data}catch(t){r.warn(`Failed to read LinkedIn metadata from ${e.path}: ${t}`)}return{...e,title:t.title||e.title,theme:t.theme,video:t.video,imageCount:t.images?.filter(Boolean).length??0}}).sort((e,t)=>e.date.getTime()-t.date.getTime())}function Se(t){let n=ye();try{C(n,[`r2`,`object`,`put`,`content-creation/${q}`,`--pipe`,`--content-type`,`text/calendar; charset=utf-8`,`--remote`],{cwd:K,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 Z(e,t){let n=xe(e);if(n.length===0)return r.info(`No LinkedIn publications found. Skipping calendar upload.`),null;let i=be(t);return Se(ve(n)),r.success(`✓ LinkedIn calendar uploaded to R2 as ${q}`),r.info(`Subscription URL: ${i}`),i}async function Ce(t,n){let i=y(t,`x.md`),{data:a,content:o}=x(m(i,`utf-8`));a.scheduled===!0&&(r.warn(`This content is already scheduled. Skipping.`),e.exit(0)),(!n.scheduling.automationEndpoint||!n.scheduling.cfAccessClientId||!n.scheduling.cfAccessClientSecret)&&(r.error(`Scheduling configuration is missing. Please set AUTOMATION_ENDPOINT, CF_ACCESS_CLIENT_ID, and CF_ACCESS_CLIENT_SECRET in your .env file or config.`),e.exit(1));let s=t.split(`/`),c=s[s.length-1],l=s[s.length-2],f=d(`${s[s.length-3]}-${l}-${c}`,`yyyy-MM-dd`,new Date);f=ee(f,11),f=te(f,0),f=ne(f,0);let p=f.getTime(),h={content:o.trim(),scheduleAt:p};try{let t=await fetch(n.scheduling.automationEndpoint,{method:`POST`,headers:{"Content-Type":`application/json`,Accept:`application/json`,"CF-Access-Client-Id":n.scheduling.cfAccessClientId,"CF-Access-Client-Secret":n.scheduling.cfAccessClientSecret},body:JSON.stringify(h)});if(!t.ok){let n=await t.text();r.error(`Failed to schedule reminder: ${t.status} ${t.statusText}\n${n}`),e.exit(1)}let s=await t.json(),c={...a,scheduled:!0};_(i,x.stringify(o,c),`utf-8`);let l=new Date(s.scheduledAt);r.success(`✓ Reminder scheduled successfully!`),r.info(`Scheduled for: ${u(l,`yyyy-MM-dd HH:mm:ss`)} UTC`)}catch(t){r.error(`Failed to schedule reminder: ${t instanceof Error?t.message:String(t)}`),e.exit(1)}}async function we(){let t=new Date,i=[];for(let e=0;e<7;e++){let n=l(t,e),r=u(n,`yyyy-MM-dd`),a=u(n,`EEEE`),o=r,s=`Create content for ${a}, ${r}`;e===0?(o=`Today - ${a} (${r})`,s=`Create content for today (${a})`):e===1?(o=`Tomorrow - ${a} (${r})`,s=`Create content for tomorrow (${a})`):(o=`In ${e} days - ${a} (${r})`,s=`Create content for ${a}, ${r}`),i.push({label:o,value:`day-${e}`,hint:s})}i.push({label:`Custom date`,value:`custom`,hint:`Enter a specific date`});let a=await o({message:`When do you want to create content?`,options:i});if(n(a)&&(r.error(`Operation cancelled.`),e.exit(0)),a!==`custom`)return l(t,Number.parseInt(a.split(`-`)[1]));let c=await s({message:`Enter date (YYYY-MM-DD):`,placeholder:u(t,`yyyy-MM-dd`),validate:e=>{if(!e)return`Date is required`;if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return`Invalid date format. Please use YYYY-MM-DD`;try{let t=d(e,`yyyy-MM-dd`,new Date);if(Number.isNaN(t.getTime()))return`Invalid date`}catch{return`Invalid date`}}});return n(c)&&(r.error(`Operation cancelled.`),e.exit(0)),d(c,`yyyy-MM-dd`,new Date)}async function Q(){let t=await s({message:`What is the title of your content?`,placeholder:`Enter content title`,validate:e=>{if(!e||e.trim().length===0)return`Title is required`}});return n(t)&&(r.error(`Operation cancelled.`),e.exit(0)),t.trim()}async function Te(){let t=await o({message:`Is a LinkedIn video planned?`,options:[{label:`Yes`,value:!0,hint:`Add video: true to frontmatter`},{label:`No`,value:!1,hint:`No video metadata`}]});return n(t)&&(r.error(`Operation cancelled.`),e.exit(0)),t}async function Ee(){let t=await o({message:`Are there images?`,options:[{label:`Yes`,value:!0,hint:`Add images section to frontmatter`},{label:`No`,value:!1,hint:`No images metadata`}]});return n(t)&&(r.error(`Operation cancelled.`),e.exit(0)),t}async function De(t){if(t.length===0)return;let i=await o({message:`What is the content theme? (optional)`,options:[{label:`No theme`,value:``,hint:`Leave theme empty`},...t.map(e=>({label:e,value:e,hint:`Use theme: ${e}`}))]});n(i)&&(r.error(`Operation cancelled.`),e.exit(0));let a=i;return a.length>0?a:void 0}async function Oe(){let t=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 n(t)&&(r.error(`Operation cancelled.`),e.exit(0)),t}async function ke(){let t=await i({message:`Which content types do you want to create?`,options:[{label:`LinkedIn`,value:`linkedin`,hint:`Create LinkedIn post and optional script`},{label:`X (Twitter)`,value:`x`,hint:`Create X post`},{label:`YouTube`,value:`youtube`,hint:`Create YouTube script and description`},{label:`Instagram`,value:`instagram`,hint:`Create Instagram script and description`}],required:!0});return n(t)&&(r.error(`Operation cancelled.`),e.exit(0)),t}async function Ae(t){let i=[];f(t)||(r.error(`Base path does not exist: ${t}`),e.exit(1));let a=h(t).filter(e=>g(y(t,e)).isDirectory()&&/^\d{4}$/.test(e));for(let e of a){let n=y(t,e),r=h(n).filter(e=>g(y(n,e)).isDirectory()&&/^\d{2}$/.test(e));for(let t of r){let r=y(n,t),a=h(r).filter(e=>g(y(r,e)).isDirectory()&&/^\d{2}$/.test(e));for(let n of a){let a=y(r,n);if(f(y(a,`x.md`))){let r=`${e}-${t}-${n}`;i.push({path:a,date:r,title:``})}}}}i.length===0&&(r.error(`No x.md files found in dated folders`),e.exit(1)),i.sort((e,t)=>t.date.localeCompare(e.date));let s=await o({message:`Which content do you want to schedule a reminder for?`,options:i.map(e=>({label:e.date,value:e.path,hint:`Schedule reminder for ${e.date}`}))});return n(s)&&(r.error(`Operation cancelled.`),e.exit(0)),s}const $=c(`content-creation`);$.command(`[path]`,`Create a dated content directory with content files`).option(`--path <path>`,`Base path for content directory (defaults to current directory)`).action(async(n,r)=>{t(`Content Creation - Create dated content directory`);let i=await k(),o=await Q(),s=await ke(),c={title:o};s.includes(`linkedin`)&&(c.hasVideo=await Te(),c.hasImages=await Ee(),i.thematic.length>0&&(c.theme=await De(i.thematic)));let l=await we();se(l,s,c,i,n||r?.path||e.cwd());let d=s.join(`, `);a(`✓ Content directory created: ${u(l,`yyyy/MM/dd`)} (${d})`)}),$.command(`link-images [path]`,`Link images to LinkedIn frontmatter in recent folders`).option(`--path <path>`,`Base path for content directory (defaults to current directory)`).action(async(n,r)=>{t(`Content Creation - Link Images to LinkedIn`),await ue(n||r?.path||e.cwd()),a(`✓ Images linked successfully`)}),$.command(`resource [path]`,`Create a resource with article/video/audio markdown file`).option(`--path <path>`,`Base path for resource directory (defaults to current directory)`).action(async(n,r)=>{t(`Content Creation - Create Resource`);let i=await Q(),o=await Oe();H(i,o,n||r?.path||e.cwd()),a(`✓ Resource created: resources/${V(i)}/${o}.md`)}),$.command(`create-index [path]`,`Create index files for each content type`).option(`--path <path>`,`Base path for content directory (defaults to current directory)`).action(async(n,r)=>{t(`Content Creation - Create Index Files`),B(n||r?.path||e.cwd()),a(`✓ Index files generated successfully`)}),$.command(`list-upcoming [path]`,`List content scheduled for today or later`).option(`--path <path>`,`Base path for content directory (defaults to current directory)`).action(async(n,r)=>{t(`Content Creation - List Upcoming Content`),de(n||r?.path||e.cwd()),a(`✓ Upcoming content listed successfully`)}),$.command(`publish-linkedin-calendar [path]`,`Create and upload a LinkedIn publication calendar`).option(`--path <path>`,`Base path for content directory (defaults to current directory)`).action(async(n,r)=>{t(`Content Creation - Publish LinkedIn Calendar`);let i=await k();if(await Z(n||r?.path||e.cwd(),i)){a(`✓ LinkedIn calendar published successfully`);return}a(`✓ No LinkedIn content found, calendar was not updated`)}),$.command(`schedule-reminder [path]`,`Schedule a reminder for X content`).option(`--path <path>`,`Base path for content directory (defaults to current directory)`).action(async(n,r)=>{t(`Content Creation - Schedule X Reminder`);let i=await k();await Ce(await Ae(n||r?.path||e.cwd()),i),a(`✓ Reminder scheduled successfully`)}),$.help(),$.version(E),$.parse();export{};
2
+ import e from"node:process";import{intro as t,isCancel as n,log as r,multiselect as i,outro as a,select as o,text as s}from"@clack/prompts";import{cac as c}from"cac";import{addDays as l,format as u,parse as d,setHours as ee,setMinutes as te,setSeconds as ne}from"date-fns";import{existsSync as f,mkdirSync as p,readFileSync as m,readdirSync as h,statSync as g,writeFileSync as _}from"node:fs";import{dirname as v,isAbsolute as re,join as y,resolve as b}from"node:path";import x from"gray-matter";import{loadConfig as S}from"c12";import{execFileSync as C}from"node:child_process";import{createHash as w}from"node:crypto";import{fileURLToPath as T}from"node:url";var E=`0.18.0`;const D={linkedin:{mainFile:`linkedin.md`,additionalFiles:[`linkedin-script.md`]},x:{mainFile:`x.md`},youtube:{mainFile:`youtube-script.md`,additionalFiles:[`youtube-description.md`]},instagram:{mainFile:`instagram-script.md`,additionalFiles:[`instagram-description.md`]}},ie={thematic:[],templatesDir:void 0,templates:{},scheduling:{},calendar:{}};function ae(t,n){return t?re(t)?t:b(n?v(n):e.cwd(),t):n?v(n):e.cwd()}function oe(e,t){let n={};if(e?.footerPath){let r=b(t,e.footerPath);f(r)&&(n.footerPath=r)}return n}function O(e,t){let n={};if(e?.templatePath){let r=b(t,e.templatePath);f(r)&&(n.templatePath=r)}return n}async function k(){let{config:t,configFile:n}=await S({name:`content-creation`,defaults:ie,globalRc:!0,dotenv:!0}),r=ae(t.templatesDir,n),i={linkedin:oe(t.templates?.linkedin,r),youtube:O(t.templates?.youtube,r),instagram:O(t.templates?.instagram,r)},a={automationEndpoint:t.scheduling?.automationEndpoint||e.env.AUTOMATION_ENDPOINT,cfAccessClientId:t.scheduling?.cfAccessClientId||e.env.CF_ACCESS_CLIENT_ID,cfAccessClientSecret:t.scheduling?.cfAccessClientSecret||e.env.CF_ACCESS_CLIENT_SECRET},o={publicUrl:t.calendar?.publicUrl||e.env.CALENDAR_PUBLIC_URL,token:t.calendar?.token||e.env.CALENDAR_TOKEN};return{thematic:t.thematic||[],templatesDir:t.templatesDir||``,templates:i,scheduling:a,calendar:o}}function A(e){return f(e)?m(e,`utf-8`):``}function se(t,n,i,a,o=e.cwd()){let s=b(y(o,u(t,`yyyy`),u(t,`MM`),u(t,`dd`)));f(s)||(p(s,{recursive:!0}),r.success(`Created directory: ${s}`));for(let e of n)ce(e,s,i,a);return s}function ce(e,t,n,i){let a=D[e],o=y(t,a.mainFile);if(f(o)?r.info(`${a.mainFile} already exists, skipping`):j(e,o,n,i),a.additionalFiles)for(let o of a.additionalFiles){let a=y(t,o);N(o,e,n)&&(f(a)?r.info(`${o} already exists, skipping`):M(e,a,o,i))}}function j(e,t,n,i){let a={title:n.title};e===`linkedin`&&(n.theme&&(a.theme=n.theme),n.hasVideo&&(a.video=!0),n.hasImages&&(a.images=[null]));let o=``;if(e===`linkedin`){let e=i.templates.linkedin?.footerPath;o=e?A(e):``}_(t,x.stringify(o,a),`utf-8`),r.success(`Created ${t}`)}function M(e,t,n,i){let a=``;if(n.endsWith(`-description.md`)){let t=i.templates[e]?.templatePath;t&&(a=A(t))}_(t,a,`utf-8`),r.success(`Created ${t}`)}function N(e,t,n){return t===`linkedin`&&e===`linkedin-script.md`?n.hasVideo||!1:!0}const P=[`linkedin`,`x`,`youtube`,`instagram`],F={linkedin:`LinkedIn`,x:`X`,youtube:`YouTube`,instagram:`Instagram`};function I(e,t){let n=[],i=D[t].mainFile;try{let t=h(e).filter(t=>g(y(e,t)).isDirectory()&&/^\d{4}$/.test(t));for(let a of t){let t=y(e,a),o=h(t).filter(e=>g(y(t,e)).isDirectory()&&/^\d{2}$/.test(e));for(let e of o){let o=y(t,e),s=h(o).filter(e=>g(y(o,e)).isDirectory()&&/^\d{2}$/.test(e));for(let t of s){let s=b(y(o,t),i);if(!f(s))continue;let c=`${a}-${e}-${t}`,l=new Date(Number(a),Number(e)-1,Number(t));try{let{data:r}=x(m(s,`utf-8`)),o=r.title||`Untitled (${c})`;n.push({path:s,date:l,title:o,relativePath:`${a}/${e}/${t}/${i}`})}catch(e){r.warn(`Error reading ${s}: ${e}`)}}}}}catch(e){return r.error(`Error reading directories: ${e}`),[]}return n.sort((e,t)=>t.date.getTime()-e.date.getTime())}function L(e){switch(e){case`linkedin`:return`linkedin-posts.md`;case`x`:return`x-posts.md`;case`youtube`:return`youtube-videos.md`;case`instagram`:return`instagram-posts.md`}}function R(e){switch(e){case`linkedin`:return`LinkedIn Posts`;case`x`:return`X Posts`;case`youtube`:return`YouTube Videos`;case`instagram`:return`Instagram Posts`}}function z(e,t){let n=I(e,t);if(n.length===0){r.info(`No ${t} posts found`);return}let i=R(t),a=L(t),o=`# ${i}\n\n`;o+=`_Generated on ${new Date().toLocaleDateString()}_\n\n`,o+=`Total posts: ${n.length}\n\n`;for(let e of n){let t=e.date.toLocaleDateString(`en-US`,{year:`numeric`,month:`long`,day:`numeric`});o+=`- [${e.title}](${e.relativePath}) - _${t}_\n`}_(y(e,a),o,`utf-8`),r.success(`Created ${a} with ${n.length} posts`)}function B(t=e.cwd(),n){let r=n||[...P];for(let e of r)z(t,e)}function V(e){return e.toLowerCase().trim().normalize(`NFD`).replace(/[\u0300-\u036F]/g,``).replace(/[^a-z0-9\s-]/g,``).replace(/\s+/g,`-`).replace(/-+/g,`-`).replace(/^-+|-+$/g,``)||`untitled`}function H(t,n,i=e.cwd()){let a=V(t),o=y(b(y(i,`resources`)),a),s=`${n}.md`,c=y(o,s);if(f(c))return r.info(`${s} already exists at: ${c}`),o;p(o,{recursive:!0}),r.success(`Created directory: ${o}`);let l={title:t,url:``,date:``};return _(c,x.stringify(``,l),`utf-8`),r.success(`Created ${s} at: ${c}`),o}function U(t=e.cwd()){let n=[];try{let e=h(t).filter(e=>g(y(t,e)).isDirectory()&&/^\d{4}$/.test(e));for(let r of e){let e=y(t,r),i=h(e).filter(t=>g(y(e,t)).isDirectory()&&/^\d{2}$/.test(t));for(let t of i){let i=y(e,t),a=h(i).filter(e=>g(y(i,e)).isDirectory()&&/^\d{2}$/.test(e));for(let e of a){let a=y(i,e);if(f(y(a,`linkedin.md`))){let i=`${r}-${t}-${e}`;n.push({path:a,date:new Date(i),displayPath:`${r}/${t}/${e}`})}}}}}catch(e){return r.error(`Error reading directories: ${e}`),[]}return n.sort((e,t)=>t.date.getTime()-e.date.getTime()).slice(0,8)}function W(e){let t=[`.jpg`,`.jpeg`,`.png`],n=[];try{let r=h(e);for(let i of r)if(g(y(e,i)).isFile()){let e=i.toLowerCase().substring(i.lastIndexOf(`.`));t.includes(e)&&n.push(i)}}catch(e){r.error(`Error reading directory: ${e}`)}return n.sort()}function G(e,t){try{let{data:n,content:i}=x(m(e,`utf-8`));n.images=t.length>0?t:[null],_(e,x.stringify(i,n),`utf-8`),r.success(`Updated ${e} with ${t.length} image(s)`)}catch(e){r.error(`Error updating frontmatter: ${e}`)}}async function le(t){if(t.length===0)return r.warn(`No dated folders with linkedin.md found`),null;let i=await o({message:`Select a folder to link images:`,options:t.map(e=>({label:e.displayPath,value:e.path,hint:`Link images in ${e.displayPath}`}))});return n(i)&&(r.error(`Operation cancelled.`),e.exit(0)),t.find(e=>e.path===i)||null}async function ue(t=e.cwd()){let n=U(t);if(n.length===0){r.warn(`No dated folders with linkedin.md found`);return}let i=await le(n);if(!i)return;let a=W(i.path);if(a.length===0){r.info(`No images found in ${i.displayPath}`),G(y(i.path,`linkedin.md`),[]);return}r.info(`Found ${a.length} image(s): ${a.join(`, `)}`),G(y(i.path,`linkedin.md`),a)}function de(e){let t=new Date;t.setHours(0,0,0,0);let n=P.flatMap(t=>I(e,t).map(e=>({...e,contentType:t}))).filter(e=>e.date.getTime()>=t.getTime()).sort((e,t)=>{let n=e.date.getTime()-t.date.getTime();return n===0?P.indexOf(e.contentType)-P.indexOf(t.contentType):n});if(n.length===0){r.info(`No upcoming content found from today onward.`);return}r.info(`Found ${n.length} upcoming content item${n.length===1?``:`s`}:`),console.log(``);for(let e of n){let t=u(e.date,`EEEE, MMMM d, yyyy`),n=u(e.date,`yyyy-MM-dd`);console.log(`${t} (${n}) · ${F[e.contentType]} · ${e.title}`),console.log(e.path),console.log(``)}}function fe(t){try{let{data:e,content:n}=x(m(t,`utf-8`));if(e.ready===!0){r.warn(`This publication is already marked as ready.`);return}let i={...e,ready:!0};_(t,x.stringify(n,i),`utf-8`),r.success(`Marked publication as ready: ${t}`)}catch(t){r.error(`Failed to mark publication as ready: ${t instanceof Error?t.message:String(t)}`),e.exit(1)}}const K=T(new URL(`../../`,import.meta.url)),q=`content-creation.ics`;function J(e){return e.replace(/\\/g,`\\\\`).replace(/\r\n|\r|\n/g,`\\n`).replace(/;/g,`\\;`).replace(/,/g,`\\,`)}function pe(e){if(e.length<=75)return e;let t=[],n=e;for(;n.length>75;)t.push(n.slice(0,75)),n=` ${n.slice(75)}`;return t.push(n),t.join(`\r
3
+ `)}function me(e){return e.toISOString().replace(/[-:]/g,``).replace(/\.\d{3}Z$/,`Z`)}function Y(e){return u(e,`yyyyMMdd`)}function X(e){return e.split(`/`).map(e=>encodeURIComponent(e)).join(`/`)}function he(e){return`https://github.com/barbapapazes/content-creation/blob/main/${X(e)}`}function ge(e){let t=X(e);return`vscode://file${t.startsWith(`/`)?``:`/`}${t}`}function _e(e){let t=[`GitHub: ${he(e.relativePath)}`,`VS Code: ${ge(e.path)}`,`Status: ${e.ready?`ready`:`not ready`}`];return e.theme&&t.push(`Theme: ${e.theme}`),typeof e.video==`boolean`&&t.push(`Video planned: ${e.video?`yes`:`no`}`),e.imageCount>0&&t.push(`Images planned: ${e.imageCount}`),t.join(`
4
+ `)}function ve(e){return`${e.ready?`Ready`:`Not ready`} · ${e.title} · ${F.linkedin}`}function ye(e){return`linkedin-${w(`sha1`).update(e).digest(`hex`)}@barbapapazes`}function be(e){let t=[`BEGIN:VCALENDAR`,`VERSION:2.0`,`PRODID:-//Barbapapazes//Content Creation LinkedIn Calendar//EN`,`CALSCALE:GREGORIAN`,`METHOD:PUBLISH`,`X-WR-CALNAME:${J(`content-creation.ics`)}`];for(let n of e){let e=me(new Date(Date.UTC(n.date.getFullYear(),n.date.getMonth(),n.date.getDate()))),r=l(n.date,1);t.push(`BEGIN:VEVENT`,`UID:${ye(n.relativePath)}`,`DTSTAMP:${e}`,`SUMMARY:${J(ve(n))}`,`DTSTART;VALUE=DATE:${Y(n.date)}`,`DTEND;VALUE=DATE:${Y(r)}`,`TRANSP:TRANSPARENT`,`DESCRIPTION:${J(_e(n))}`,`END:VEVENT`)}return t.push(`END:VCALENDAR`),`${t.map(pe).join(`\r
5
+ `)}\r\n`}function xe(){let t=y(K,`node_modules`,`.bin`,e.platform===`win32`?`wrangler.cmd`:`wrangler`);return f(t)?t:`wrangler`}function Se(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(q,n);return i.searchParams.set(`token`,t.calendar.token),i.toString()}function Ce(e){return I(e,`linkedin`).map(e=>{let t={title:e.title};try{t=x(m(e.path,`utf-8`)).data}catch(t){r.warn(`Failed to read LinkedIn metadata from ${e.path}: ${t}`)}return{...e,title:t.title||e.title,ready:t.ready===!0,theme:t.theme,video:t.video,imageCount:t.images?.filter(Boolean).length??0}}).sort((e,t)=>e.date.getTime()-t.date.getTime())}function we(t){let n=xe();try{C(n,[`r2`,`object`,`put`,`content-creation/${q}`,`--pipe`,`--content-type`,`text/calendar; charset=utf-8`,`--remote`],{cwd:K,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 Te(e,t){let n=Ce(e);if(n.length===0)return r.info(`No LinkedIn publications found. Skipping calendar upload.`),null;let i=Se(t);return we(be(n)),r.success(`✓ LinkedIn calendar uploaded to R2 as ${q}`),r.info(`Subscription URL: ${i}`),i}async function Ee(t,n){let i=y(t,`x.md`),{data:a,content:o}=x(m(i,`utf-8`));a.scheduled===!0&&(r.warn(`This content is already scheduled. Skipping.`),e.exit(0)),(!n.scheduling.automationEndpoint||!n.scheduling.cfAccessClientId||!n.scheduling.cfAccessClientSecret)&&(r.error(`Scheduling configuration is missing. Please set AUTOMATION_ENDPOINT, CF_ACCESS_CLIENT_ID, and CF_ACCESS_CLIENT_SECRET in your .env file or config.`),e.exit(1));let s=t.split(`/`),c=s[s.length-1],l=s[s.length-2],f=d(`${s[s.length-3]}-${l}-${c}`,`yyyy-MM-dd`,new Date);f=ee(f,11),f=te(f,0),f=ne(f,0);let p=f.getTime(),h={content:o.trim(),scheduleAt:p};try{let t=await fetch(n.scheduling.automationEndpoint,{method:`POST`,headers:{"Content-Type":`application/json`,Accept:`application/json`,"CF-Access-Client-Id":n.scheduling.cfAccessClientId,"CF-Access-Client-Secret":n.scheduling.cfAccessClientSecret},body:JSON.stringify(h)});if(!t.ok){let n=await t.text();r.error(`Failed to schedule reminder: ${t.status} ${t.statusText}\n${n}`),e.exit(1)}let s=await t.json(),c={...a,scheduled:!0};_(i,x.stringify(o,c),`utf-8`);let l=new Date(s.scheduledAt);r.success(`✓ Reminder scheduled successfully!`),r.info(`Scheduled for: ${u(l,`yyyy-MM-dd HH:mm:ss`)} UTC`)}catch(t){r.error(`Failed to schedule reminder: ${t instanceof Error?t.message:String(t)}`),e.exit(1)}}async function De(){let t=new Date,i=[];for(let e=0;e<7;e++){let n=l(t,e),r=u(n,`yyyy-MM-dd`),a=u(n,`EEEE`),o=r,s=`Create content for ${a}, ${r}`;e===0?(o=`Today - ${a} (${r})`,s=`Create content for today (${a})`):e===1?(o=`Tomorrow - ${a} (${r})`,s=`Create content for tomorrow (${a})`):(o=`In ${e} days - ${a} (${r})`,s=`Create content for ${a}, ${r}`),i.push({label:o,value:`day-${e}`,hint:s})}i.push({label:`Custom date`,value:`custom`,hint:`Enter a specific date`});let a=await o({message:`When do you want to create content?`,options:i});if(n(a)&&(r.error(`Operation cancelled.`),e.exit(0)),a!==`custom`)return l(t,Number.parseInt(a.split(`-`)[1]));let c=await s({message:`Enter date (YYYY-MM-DD):`,placeholder:u(t,`yyyy-MM-dd`),validate:e=>{if(!e)return`Date is required`;if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return`Invalid date format. Please use YYYY-MM-DD`;try{let t=d(e,`yyyy-MM-dd`,new Date);if(Number.isNaN(t.getTime()))return`Invalid date`}catch{return`Invalid date`}}});return n(c)&&(r.error(`Operation cancelled.`),e.exit(0)),d(c,`yyyy-MM-dd`,new Date)}async function Z(){let t=await s({message:`What is the title of your content?`,placeholder:`Enter content title`,validate:e=>{if(!e||e.trim().length===0)return`Title is required`}});return n(t)&&(r.error(`Operation cancelled.`),e.exit(0)),t.trim()}async function Oe(){let t=await o({message:`Is a LinkedIn video planned?`,options:[{label:`Yes`,value:!0,hint:`Add video: true to frontmatter`},{label:`No`,value:!1,hint:`No video metadata`}]});return n(t)&&(r.error(`Operation cancelled.`),e.exit(0)),t}async function Q(){let t=await o({message:`Are there images?`,options:[{label:`Yes`,value:!0,hint:`Add images section to frontmatter`},{label:`No`,value:!1,hint:`No images metadata`}]});return n(t)&&(r.error(`Operation cancelled.`),e.exit(0)),t}async function ke(t){if(t.length===0)return;let i=await o({message:`What is the content theme? (optional)`,options:[{label:`No theme`,value:``,hint:`Leave theme empty`},...t.map(e=>({label:e,value:e,hint:`Use theme: ${e}`}))]});n(i)&&(r.error(`Operation cancelled.`),e.exit(0));let a=i;return a.length>0?a:void 0}async function Ae(){let t=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 n(t)&&(r.error(`Operation cancelled.`),e.exit(0)),t}async function je(){let t=await i({message:`Which content types do you want to create?`,options:[{label:`LinkedIn`,value:`linkedin`,hint:`Create LinkedIn post and optional script`},{label:`X (Twitter)`,value:`x`,hint:`Create X post`},{label:`YouTube`,value:`youtube`,hint:`Create YouTube script and description`},{label:`Instagram`,value:`instagram`,hint:`Create Instagram script and description`}],required:!0});return n(t)&&(r.error(`Operation cancelled.`),e.exit(0)),t}async function Me(t){let i=[];f(t)||(r.error(`Base path does not exist: ${t}`),e.exit(1));let a=h(t).filter(e=>g(y(t,e)).isDirectory()&&/^\d{4}$/.test(e));for(let e of a){let n=y(t,e),r=h(n).filter(e=>g(y(n,e)).isDirectory()&&/^\d{2}$/.test(e));for(let t of r){let r=y(n,t),a=h(r).filter(e=>g(y(r,e)).isDirectory()&&/^\d{2}$/.test(e));for(let n of a){let a=y(r,n);if(f(y(a,`x.md`))){let r=`${e}-${t}-${n}`;i.push({path:a,date:r,title:``})}}}}i.length===0&&(r.error(`No x.md files found in dated folders`),e.exit(1)),i.sort((e,t)=>t.date.localeCompare(e.date));let s=await o({message:`Which content do you want to schedule a reminder for?`,options:i.map(e=>({label:e.date,value:e.path,hint:`Schedule reminder for ${e.date}`}))});return n(s)&&(r.error(`Operation cancelled.`),e.exit(0)),s}async function Ne(t){let i=P.flatMap(e=>I(t,e).map(t=>({...t,contentType:e}))).sort((e,t)=>{let n=t.date.getTime()-e.date.getTime();return n===0?P.indexOf(e.contentType)-P.indexOf(t.contentType):n});i.length===0&&(r.error(`No publications found in dated folders`),e.exit(1));let a=await o({message:`Which publication do you want to mark as ready?`,options:i.map(e=>Pe(e))});return n(a)&&(r.error(`Operation cancelled.`),e.exit(0)),a}function Pe(e){return{label:`${u(e.date,`yyyy-MM-dd`)} · ${F[e.contentType]} · ${e.title}`,value:e.path,hint:e.relativePath}}const $=c(`content-creation`);$.command(`[path]`,`Create a dated content directory with content files`).option(`--path <path>`,`Base path for content directory (defaults to current directory)`).action(async(n,r)=>{t(`Content Creation - Create dated content directory`);let i=await k(),o=await Z(),s=await je(),c={title:o};s.includes(`linkedin`)&&(c.hasVideo=await Oe(),c.hasImages=await Q(),i.thematic.length>0&&(c.theme=await ke(i.thematic)));let l=await De();se(l,s,c,i,n||r?.path||e.cwd());let d=s.join(`, `);a(`✓ Content directory created: ${u(l,`yyyy/MM/dd`)} (${d})`)}),$.command(`link-images [path]`,`Link images to LinkedIn frontmatter in recent folders`).option(`--path <path>`,`Base path for content directory (defaults to current directory)`).action(async(n,r)=>{t(`Content Creation - Link Images to LinkedIn`),await ue(n||r?.path||e.cwd()),a(`✓ Images linked successfully`)}),$.command(`resource [path]`,`Create a resource with article/video/audio markdown file`).option(`--path <path>`,`Base path for resource directory (defaults to current directory)`).action(async(n,r)=>{t(`Content Creation - Create Resource`);let i=await Z(),o=await Ae();H(i,o,n||r?.path||e.cwd()),a(`✓ Resource created: resources/${V(i)}/${o}.md`)}),$.command(`create-index [path]`,`Create index files for each content type`).option(`--path <path>`,`Base path for content directory (defaults to current directory)`).action(async(n,r)=>{t(`Content Creation - Create Index Files`),B(n||r?.path||e.cwd()),a(`✓ Index files generated successfully`)}),$.command(`list-upcoming [path]`,`List content scheduled for today or later`).option(`--path <path>`,`Base path for content directory (defaults to current directory)`).action(async(n,r)=>{t(`Content Creation - List Upcoming Content`),de(n||r?.path||e.cwd()),a(`✓ Upcoming content listed successfully`)}),$.command(`publish-linkedin-calendar [path]`,`Create and upload a LinkedIn publication calendar`).option(`--path <path>`,`Base path for content directory (defaults to current directory)`).action(async(n,r)=>{t(`Content Creation - Publish LinkedIn Calendar`);let i=await k();if(await Te(n||r?.path||e.cwd(),i)){a(`✓ LinkedIn calendar published successfully`);return}a(`✓ No LinkedIn content found, calendar was not updated`)}),$.command(`schedule-reminder [path]`,`Schedule a reminder for X content`).option(`--path <path>`,`Base path for content directory (defaults to current directory)`).action(async(n,r)=>{t(`Content Creation - Schedule X Reminder`);let i=await k();await Ee(await Me(n||r?.path||e.cwd()),i),a(`✓ Reminder scheduled successfully`)}),$.command(`ready [path]`,`Mark a publication as ready`).option(`--path <path>`,`Base path for content directory (defaults to current directory)`).action(async(n,r)=>{t(`Content Creation - Mark Publication as Ready`),fe(await Ne(n||r?.path||e.cwd())),a(`✓ Publication marked as ready`)}),$.help(),$.version(E),$.parse();export{};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@barbapapazes/content-creation",
3
3
  "type": "module",
4
- "version": "0.17.2",
4
+ "version": "0.18.0",
5
5
  "author": "Estéban Soubiran <esteban@soubiran.dev>",
6
6
  "license": "MIT",
7
7
  "funding": "https://github.com/sponsors/Barbapapazes",