@mulmocast/slide 0.1.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 +458 -0
- package/lib/actions/bundle.d.ts +3 -0
- package/lib/actions/bundle.d.ts.map +1 -0
- package/lib/actions/bundle.js +60 -0
- package/lib/actions/bundle.js.map +1 -0
- package/lib/actions/common.d.ts +21 -0
- package/lib/actions/common.d.ts.map +1 -0
- package/lib/actions/common.js +159 -0
- package/lib/actions/common.js.map +1 -0
- package/lib/actions/movie.d.ts +3 -0
- package/lib/actions/movie.d.ts.map +1 -0
- package/lib/actions/movie.js +58 -0
- package/lib/actions/movie.js.map +1 -0
- package/lib/actions/upload.d.ts +6 -0
- package/lib/actions/upload.d.ts.map +1 -0
- package/lib/actions/upload.js +172 -0
- package/lib/actions/upload.js.map +1 -0
- package/lib/cli.d.ts +3 -0
- package/lib/cli.d.ts.map +1 -0
- package/lib/cli.js +301 -0
- package/lib/cli.js.map +1 -0
- package/lib/convert/marp.d.ts +22 -0
- package/lib/convert/marp.d.ts.map +1 -0
- package/lib/convert/marp.js +375 -0
- package/lib/convert/marp.js.map +1 -0
- package/lib/convert/pdf.d.ts +14 -0
- package/lib/convert/pdf.d.ts.map +1 -0
- package/lib/convert/pdf.js +130 -0
- package/lib/convert/pdf.js.map +1 -0
- package/lib/convert/pptx.d.ts +13 -0
- package/lib/convert/pptx.d.ts.map +1 -0
- package/lib/convert/pptx.js +138 -0
- package/lib/convert/pptx.js.map +1 -0
- package/lib/utils/lang.d.ts +16 -0
- package/lib/utils/lang.d.ts.map +1 -0
- package/lib/utils/lang.js +37 -0
- package/lib/utils/lang.js.map +1 -0
- package/lib/utils/llm.d.ts +21 -0
- package/lib/utils/llm.d.ts.map +1 -0
- package/lib/utils/llm.js +200 -0
- package/lib/utils/llm.js.map +1 -0
- package/lib/utils/pdf.d.ts +37 -0
- package/lib/utils/pdf.d.ts.map +1 -0
- package/lib/utils/pdf.js +142 -0
- package/lib/utils/pdf.js.map +1 -0
- package/package.json +67 -0
- package/tools/keynote/extract.scpt +195 -0
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mulmocast/slide",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Convert presentations (Keynote, PowerPoint, PDF, Marp) to MulmoScript format",
|
|
5
|
+
"homepage": "https://github.com/receptron/MulmoCast-Slides#readme",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/receptron/MulmoCast-Slides/issues"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/receptron/MulmoCast-Slides.git"
|
|
12
|
+
},
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"author": "receptron",
|
|
15
|
+
"type": "commonjs",
|
|
16
|
+
"main": "lib/cli.js",
|
|
17
|
+
"bin": {
|
|
18
|
+
"mulmo-slide": "./lib/cli.js"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"lib",
|
|
22
|
+
"tools"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsc",
|
|
26
|
+
"test": "tsx --test ./tests/test_*.ts",
|
|
27
|
+
"lint": "eslint src/",
|
|
28
|
+
"lint:fix": "eslint src/ --fix",
|
|
29
|
+
"format": "prettier --write src/",
|
|
30
|
+
"cli": "tsx src/cli.ts",
|
|
31
|
+
"keynote": "tsx src/cli.ts keynote",
|
|
32
|
+
"pptx": "tsx src/cli.ts pptx",
|
|
33
|
+
"pdf": "tsx src/cli.ts pdf",
|
|
34
|
+
"marp": "tsx src/cli.ts marp",
|
|
35
|
+
"movie": "tsx src/cli.ts movie",
|
|
36
|
+
"bundle": "tsx src/cli.ts bundle",
|
|
37
|
+
"upload": "tsx src/cli.ts upload",
|
|
38
|
+
"test:keynote": "tsx src/cli.ts keynote samples/GraphAI.key",
|
|
39
|
+
"test:marp": "tsx src/cli.ts marp samples/sample.md",
|
|
40
|
+
"test:marp:theme": "tsx src/cli.ts marp samples/custom_theme_demo.md --theme samples/custom-ocean.css"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@marp-team/marp-cli": "^4.0.0",
|
|
44
|
+
"dotenv": "^17.2.3",
|
|
45
|
+
"mulmocast": "^2.1.16",
|
|
46
|
+
"node-pptx-parser": "^1.0.1",
|
|
47
|
+
"openai": "^6.15.0",
|
|
48
|
+
"pdf-parse": "^2.4.5",
|
|
49
|
+
"ppt-png": "^2.2.0",
|
|
50
|
+
"tsx": "^4.7.0",
|
|
51
|
+
"yargs": "^18.0.0"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@types/node": "^25.0.3",
|
|
55
|
+
"@types/yargs": "^17.0.35",
|
|
56
|
+
"@typescript-eslint/eslint-plugin": "^8.51.0",
|
|
57
|
+
"@typescript-eslint/parser": "^8.51.0",
|
|
58
|
+
"eslint": "^9.39.2",
|
|
59
|
+
"eslint-config-prettier": "^10.1.8",
|
|
60
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
61
|
+
"prettier": "^3.7.4",
|
|
62
|
+
"typescript": "^5.9.3"
|
|
63
|
+
},
|
|
64
|
+
"resolutions": {
|
|
65
|
+
"unicorn-magic": "0.2.0"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
-- Keynote Slides to MulmoScript Exporter
|
|
2
|
+
-- This script exports each slide of a Keynote presentation as an image
|
|
3
|
+
-- then, generate a MulmoScript using speaker note of each slide as text.
|
|
4
|
+
-- Usage: yarn keynote [path/to/presentation.key] [-l lang]
|
|
5
|
+
-- Supported languages: en, ja, fr, de (default: en)
|
|
6
|
+
-- Can also set MULMO_LANG environment variable
|
|
7
|
+
|
|
8
|
+
on run argv
|
|
9
|
+
-- Default language
|
|
10
|
+
set scriptLang to "en"
|
|
11
|
+
set inputPath to ""
|
|
12
|
+
|
|
13
|
+
-- Parse arguments
|
|
14
|
+
set i to 1
|
|
15
|
+
repeat while i ≤ (count of argv)
|
|
16
|
+
set currentArg to item i of argv
|
|
17
|
+
if currentArg is "-l" or currentArg is "--lang" then
|
|
18
|
+
if i + 1 ≤ (count of argv) then
|
|
19
|
+
set scriptLang to item (i + 1) of argv
|
|
20
|
+
set i to i + 2
|
|
21
|
+
else
|
|
22
|
+
set i to i + 1
|
|
23
|
+
end if
|
|
24
|
+
else if inputPath is "" then
|
|
25
|
+
set inputPath to currentArg
|
|
26
|
+
set i to i + 1
|
|
27
|
+
else
|
|
28
|
+
set i to i + 1
|
|
29
|
+
end if
|
|
30
|
+
end repeat
|
|
31
|
+
|
|
32
|
+
-- Check environment variable if lang not set via CLI
|
|
33
|
+
if scriptLang is "en" then
|
|
34
|
+
try
|
|
35
|
+
set envLang to do shell script "echo $MULMO_LANG"
|
|
36
|
+
if envLang is not "" then
|
|
37
|
+
set scriptLang to envLang
|
|
38
|
+
end if
|
|
39
|
+
end try
|
|
40
|
+
end if
|
|
41
|
+
|
|
42
|
+
-- Validate language
|
|
43
|
+
if scriptLang is not in {"en", "ja", "fr", "de"} then
|
|
44
|
+
display dialog "Invalid language: " & scriptLang & ". Using 'en' as default." buttons {"OK"} default button "OK"
|
|
45
|
+
set scriptLang to "en"
|
|
46
|
+
end if
|
|
47
|
+
|
|
48
|
+
-- Check if a file path was provided
|
|
49
|
+
if inputPath is not "" then
|
|
50
|
+
|
|
51
|
+
-- Convert relative path to absolute path using shell
|
|
52
|
+
set absolutePath to do shell script "cd \"$(dirname " & quoted form of inputPath & ")\"; echo \"$PWD/$(basename " & quoted form of inputPath & ")\""
|
|
53
|
+
|
|
54
|
+
-- Convert POSIX path to file reference
|
|
55
|
+
set keynoteFile to POSIX file absolutePath as alias
|
|
56
|
+
else
|
|
57
|
+
-- Ask user to select a Keynote file if no argument provided
|
|
58
|
+
set keynoteFile to choose file with prompt "Select a Keynote file:" of type {"com.apple.iwork.keynote.sffkey", "com.apple.iwork.keynote.key"}
|
|
59
|
+
end if
|
|
60
|
+
|
|
61
|
+
-- Get the file path and extract folder/filename info
|
|
62
|
+
set filePosixPath to POSIX path of keynoteFile
|
|
63
|
+
|
|
64
|
+
-- Extract basename (filename without extension)
|
|
65
|
+
set fileBasename to do shell script "basename " & quoted form of filePosixPath & " .key"
|
|
66
|
+
|
|
67
|
+
-- Get current working directory
|
|
68
|
+
set currentDirectory to do shell script "pwd"
|
|
69
|
+
|
|
70
|
+
-- Create output folder paths in scripts/<basename>/ directory
|
|
71
|
+
set outputFolder to currentDirectory & "/scripts/" & fileBasename
|
|
72
|
+
set outputImagesFolder to outputFolder & "/images"
|
|
73
|
+
set outputScriptFile to outputFolder & "/mulmo_script.json"
|
|
74
|
+
|
|
75
|
+
-- Create the output folders if they don't exist
|
|
76
|
+
do shell script "mkdir -p " & quoted form of outputImagesFolder
|
|
77
|
+
|
|
78
|
+
-- Remove all existing PNG files from the images folder
|
|
79
|
+
do shell script "rm -f " & quoted form of outputImagesFolder & "/*.png"
|
|
80
|
+
|
|
81
|
+
-- Open and export from Keynote
|
|
82
|
+
tell application "Keynote"
|
|
83
|
+
activate
|
|
84
|
+
|
|
85
|
+
-- Open the presentation
|
|
86
|
+
open keynoteFile
|
|
87
|
+
|
|
88
|
+
-- Wait for the document to open
|
|
89
|
+
delay 1
|
|
90
|
+
|
|
91
|
+
-- Get reference to the front document
|
|
92
|
+
set theDocument to front document
|
|
93
|
+
|
|
94
|
+
-- Get the number of slides
|
|
95
|
+
set slideCount to count of slides of theDocument
|
|
96
|
+
|
|
97
|
+
-- Collect speaker notes from all slides
|
|
98
|
+
set allNotes to {}
|
|
99
|
+
repeat with i from 1 to slideCount
|
|
100
|
+
set currentSlide to slide i of theDocument
|
|
101
|
+
set speakerNotes to presenter notes of currentSlide
|
|
102
|
+
set end of allNotes to speakerNotes
|
|
103
|
+
end repeat
|
|
104
|
+
|
|
105
|
+
-- Export all slides as images to the images folder
|
|
106
|
+
-- Keynote will create numbered image files automatically
|
|
107
|
+
export theDocument to POSIX file outputImagesFolder as slide images with properties {image format:PNG, compression factor:1.0}
|
|
108
|
+
|
|
109
|
+
-- Close the document without saving
|
|
110
|
+
close theDocument saving no
|
|
111
|
+
end tell
|
|
112
|
+
|
|
113
|
+
-- Clean up hidden characters from exported filenames and rename to match PPTX format
|
|
114
|
+
-- Remove carriage returns and Left-to-Right Mark (U+200E) characters
|
|
115
|
+
-- Also rename from images.001.png to <basename>-0.png format
|
|
116
|
+
-- Issue: https://discussions.apple.com/thread/255014422?sortBy=rank
|
|
117
|
+
do shell script "cd " & quoted form of outputImagesFolder & " && python3 << 'PYEOF'
|
|
118
|
+
import os
|
|
119
|
+
import re
|
|
120
|
+
|
|
121
|
+
basename = '" & fileBasename & "'
|
|
122
|
+
|
|
123
|
+
for filename in os.listdir('.'):
|
|
124
|
+
if os.path.isfile(filename) and filename.endswith('.png'):
|
|
125
|
+
# Clean hidden characters
|
|
126
|
+
clean_name = filename.replace('\\u200e', '').replace('\\r', '')
|
|
127
|
+
|
|
128
|
+
# Extract slide number from images.XXX.png format
|
|
129
|
+
match = re.match(r'.*\\.([0-9]+)\\.png$', clean_name)
|
|
130
|
+
if match:
|
|
131
|
+
slide_num = int(match.group(1)) - 1 # Convert to 0-indexed
|
|
132
|
+
new_name = f'{basename}-{slide_num}.png'
|
|
133
|
+
if filename != new_name:
|
|
134
|
+
os.rename(filename, new_name)
|
|
135
|
+
elif filename != clean_name:
|
|
136
|
+
os.rename(filename, clean_name)
|
|
137
|
+
PYEOF"
|
|
138
|
+
|
|
139
|
+
-- Create JSON file with beats
|
|
140
|
+
-- First, write notes to a temporary file
|
|
141
|
+
set tempFile to outputFolder & "/.temp_notes.txt"
|
|
142
|
+
set AppleScript's text item delimiters to (ASCII character 30) -- Use ASCII Record Separator as delimiter
|
|
143
|
+
set notesText to allNotes as text
|
|
144
|
+
set AppleScript's text item delimiters to ""
|
|
145
|
+
do shell script "printf '%s' " & quoted form of notesText & " > " & quoted form of tempFile
|
|
146
|
+
|
|
147
|
+
-- Then use Python to create JSON from the temp file with relative paths
|
|
148
|
+
do shell script "python3 << 'PYEOF'
|
|
149
|
+
import json
|
|
150
|
+
|
|
151
|
+
basename = '" & fileBasename & "'
|
|
152
|
+
|
|
153
|
+
# Read notes from temp file
|
|
154
|
+
with open('" & tempFile & "', 'r') as f:
|
|
155
|
+
content = f.read()
|
|
156
|
+
|
|
157
|
+
# Split by ASCII Record Separator (character 30)
|
|
158
|
+
notes = content.split(chr(30)) if content else []
|
|
159
|
+
|
|
160
|
+
# Create beats array with relative image paths (in images/ subdirectory)
|
|
161
|
+
beats = []
|
|
162
|
+
for i, note in enumerate(notes):
|
|
163
|
+
image_filename = f'./images/{basename}-{i}.png'
|
|
164
|
+
beats.append({
|
|
165
|
+
'text': note,
|
|
166
|
+
'image': {
|
|
167
|
+
'type': 'image',
|
|
168
|
+
'source': {
|
|
169
|
+
'kind': 'path',
|
|
170
|
+
'path': image_filename
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
# Create MulmoScript object with metadata
|
|
176
|
+
mulmocast = {
|
|
177
|
+
'$mulmocast': {
|
|
178
|
+
'version': '1.1',
|
|
179
|
+
'credit': 'closing'
|
|
180
|
+
},
|
|
181
|
+
'lang': '" & scriptLang & "',
|
|
182
|
+
'beats': beats
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
# Write JSON file
|
|
186
|
+
with open('" & outputScriptFile & "', 'w') as f:
|
|
187
|
+
json.dump(mulmocast, f, indent=2, ensure_ascii=False)
|
|
188
|
+
PYEOF"
|
|
189
|
+
|
|
190
|
+
-- Clean up temp file
|
|
191
|
+
do shell script "rm -f " & quoted form of tempFile
|
|
192
|
+
|
|
193
|
+
-- Export completed silently
|
|
194
|
+
|
|
195
|
+
end run
|