-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpublish.fsx
More file actions
153 lines (126 loc) · 5.83 KB
/
publish.fsx
File metadata and controls
153 lines (126 loc) · 5.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
open System
open System.IO
open System.Text.RegularExpressions
open System.Diagnostics
// --- Configuration ---
let vaultPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "source/repo/note")
let attachmentPath = Path.Combine(vaultPath, "attachments") // Adjust if your folder is named differently
let repoPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "source/repo/xqguo.github.io")
let postsDir = "posts"
let assetsDir = "assets" // Fornax public assets folder
// --- Helper: Run Shell Commands ---
let execute command (args: string) workingDir =
let startInfo: ProcessStartInfo = ProcessStartInfo(command, args)
startInfo.WorkingDirectory <- workingDir
startInfo.RedirectStandardOutput <- true
startInfo.UseShellExecute <- false
startInfo.CreateNoWindow <- true
match Process.Start(startInfo) with
| null -> -1
| proc ->
use p = proc
let out = p.StandardOutput.ReadToEnd()
p.WaitForExit()
if not (String.IsNullOrWhiteSpace out) then printfn "%s" out
p.ExitCode
// --- Logic to Process Images ---
let processImages (content: string) =
// Matches both ![[image.png]] and 
let pattern = @"!\[\[(.*?)\]\]|!\[.*?\]\((.*?)\)"
let mutable updatedContent = content
Regex.Matches(content, pattern)
|> Seq.cast<Match>
|> Seq.iter (fun m ->
// Extract filename from whichever group matched
let rawPath = if m.Groups.[1].Success then m.Groups.[1].Value else m.Groups.[2].Value
let fileName = Path.GetFileName(rawPath)
let sourceImg = Path.Combine(attachmentPath, fileName)
let destImg = Path.Combine(repoPath, assetsDir, fileName)
if File.Exists(sourceImg) then
if not (Directory.Exists(Path.GetDirectoryName(destImg))) then
Directory.CreateDirectory(Path.GetDirectoryName(destImg)) |> ignore
let finalDestImg =
if File.Exists(destImg) then
let guid = Guid.NewGuid().ToString().Substring(0, 8)
let name = Path.GetFileNameWithoutExtension(fileName)
let ext = Path.GetExtension(fileName)
Path.Combine(repoPath, assetsDir, $"{name}-{guid}{ext}")
else
destImg
File.Copy(sourceImg, finalDestImg, true)
printfn "📸 Copied Image: %s" (Path.GetFileName(finalDestImg))
// Replace the link in the text to point to /assets/filename
let newLink = $"})"
updatedContent <- updatedContent.Replace(m.Value, newLink)
// Replace the link in the text to point to /assets/filename
let newLink = $""
updatedContent <- updatedContent.Replace(m.Value, newLink)
else
printfn "⚠️ Warning: Image not found at %s" sourceImg
)
updatedContent
//need a function to add pre matters
let addheaders title content =
let tags =
let words =
Regex.Split(title + " " + content, @"[^\w]+")
|> Array.filter (fun w -> w.Length >= 2 && w.Length < 10 ) // Filter out very short and very long words
|> Array.distinctBy (fun w -> w.ToLower())
if words.Length = 0 then
""
else
words
|> Array.take (Math.Min(5, words.Length))
|> String.concat ", "
let date = DateTime.Now.ToString("yyyy-MM-dd")
let headers = $"""---
layout: post
title: {title}
author: xq
published: {date}
tags: {tags}
---
"""
headers + content
// --- Main Execution ---
let args = fsi.CommandLineArgs |> Array.skip 1
if args.Length = 0 then
printfn "Usage: dotnet fsi publish.fsx \"Note Name\""
else
let noteName = args.[0]
let sourceFile = Path.Combine(vaultPath, $"{noteName}.md")
let fn = noteName.Split(Path.DirectorySeparatorChar) |> Array.last
let webFileName = DateTime.Now.ToString("yyyy-MM-dd") + "-" + fn.Replace(" ", "-").ToLower() + ".md"
let destFile = Path.Combine(repoPath, postsDir, webFileName)
if not (File.Exists(sourceFile)) then
printfn "❌ Note not found: %s" sourceFile
else
printfn "🚀 Publishing: %s" noteName
// Read, Process Images, and Write
let originalContent = File.ReadAllText(sourceFile)
let paddedContent = originalContent |> addheaders fn
let finalContent = processImages paddedContent
File.WriteAllText(destFile, finalContent)
//clear the old dir docs and _publish
let docsDir = Path.Combine(repoPath, "docs")
let publishDir = Path.Combine(repoPath, "_public")
// Clear old directories
if Directory.Exists(docsDir) then Directory.Delete(docsDir, true)
if Directory.Exists(publishDir) then Directory.Delete(publishDir, true)
// Build with Fornax
if execute "fornax" "build" repoPath = 0 then
// Move _publish to docs
if Directory.Exists(publishDir) then
Directory.Move(publishDir, docsDir)
printfn "✨ Build complete and published to docs/"
else
printfn "⚠️ Warning: _publish directory not found after build"
else
printfn "❌ Fornax build failed"
// // Build and Deploy
if execute "fornax" "build" repoPath = 0 then
execute "git" "add ." repoPath |> ignore
execute "git" ($"commit -m \"Publish: {noteName}\"") repoPath |> ignore
//do a manual push for now, control the impact local in case of any issue.
// execute "git" "push origin main" repoPath |> ignore
printfn "✨ Done!"