@learnpack/learnpack 5.0.316 → 5.0.318
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/lib/commands/serve.js +77 -26
- package/lib/creatorDist/assets/{index-D4SYZg0r.css → index-CjddKHB_.css} +12 -0
- package/lib/creatorDist/assets/{index-DxgQXudf.js → index-XZDcEWl9.js} +38343 -34250
- package/lib/creatorDist/index.html +2 -2
- package/package.json +1 -1
- package/src/commands/serve.ts +3267 -3204
- package/src/creator/components.json +18 -0
- package/src/creator/package-lock.json +470 -1
- package/src/creator/package.json +3 -0
- package/src/creator/src/App.tsx +0 -1
- package/src/creator/src/assets/svgs.tsx +0 -1
- package/src/creator/src/components/FileCard.tsx +15 -3
- package/src/creator/src/components/FileUploader.tsx +41 -23
- package/src/creator/src/components/LanguageDetectionModal.tsx +1 -1
- package/src/creator/src/components/LessonItem.tsx +80 -49
- package/src/creator/src/components/LinkUploader.tsx +55 -8
- package/src/creator/src/components/Source.tsx +15 -6
- package/src/creator/src/components/syllabus/ContentIndex.tsx +19 -7
- package/src/creator/src/components/syllabus/Sidebar.tsx +56 -48
- package/src/creator/src/components/ui/tooltip.tsx +31 -0
- package/src/creator/src/lib/utils.ts +6 -0
- package/src/creator/src/locales/en.json +24 -1
- package/src/creator/src/locales/es.json +24 -1
- package/src/creator/src/main.tsx +11 -7
- package/src/creator/src/utils/rigo.ts +85 -85
- package/src/creator/tsconfig.app.json +6 -0
- package/src/creator/vite.config.ts +10 -4
- package/src/creatorDist/assets/{index-D4SYZg0r.css → index-CjddKHB_.css} +12 -0
- package/src/creatorDist/assets/{index-DxgQXudf.js → index-XZDcEWl9.js} +38343 -34250
- package/src/creatorDist/index.html +2 -2
- package/src/ui/_app/app.css +1 -1
- package/src/ui/_app/app.js +529 -529
- package/src/ui/_app/learnpack.svg +7 -7
- package/src/ui/_app/sw.js +59 -59
- package/src/ui/app.tar.gz +0 -0
package/lib/commands/serve.js
CHANGED
|
@@ -71,24 +71,37 @@ const PARAMS = {
|
|
|
71
71
|
max_rewrite_attempts: 2,
|
|
72
72
|
max_title_length: 50,
|
|
73
73
|
};
|
|
74
|
+
// Fetch YouTube transcript via TranscriptAPI
|
|
75
|
+
async function fetchYouTubeTranscript(videoUrl, apiKey) {
|
|
76
|
+
const trRes = await axios_1.default.get("https://transcriptapi.com/api/v2/youtube/transcript", {
|
|
77
|
+
params: {
|
|
78
|
+
video_url: videoUrl,
|
|
79
|
+
format: "text",
|
|
80
|
+
include_timestamp: false,
|
|
81
|
+
send_metadata: false,
|
|
82
|
+
},
|
|
83
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
84
|
+
});
|
|
85
|
+
return { transcript: trRes.data.transcript, language: trRes.data.language };
|
|
86
|
+
}
|
|
74
87
|
async function fetchComponentsYml() {
|
|
75
88
|
try {
|
|
76
89
|
const [assessmentResponse, explanatoryResponse] = await Promise.all([
|
|
77
90
|
axios_1.default.get("https://raw.githubusercontent.com/learnpack/ide/refs/heads/master/docs/assessment_components.yml"),
|
|
78
91
|
axios_1.default.get("https://raw.githubusercontent.com/learnpack/ide/refs/heads/master/docs/explanatory_components.yml"),
|
|
79
92
|
]);
|
|
80
|
-
const combinedContent = `
|
|
81
|
-
# ASSESSMENT COMPONENTS
|
|
82
|
-
These components are designed for evaluation and knowledge assessment:
|
|
83
|
-
|
|
84
|
-
${assessmentResponse.data}
|
|
85
|
-
|
|
86
|
-
---
|
|
87
|
-
|
|
88
|
-
# EXPLANATORY COMPONENTS
|
|
89
|
-
These components are designed for explanation and learning support:
|
|
90
|
-
|
|
91
|
-
${explanatoryResponse.data}
|
|
93
|
+
const combinedContent = `
|
|
94
|
+
# ASSESSMENT COMPONENTS
|
|
95
|
+
These components are designed for evaluation and knowledge assessment:
|
|
96
|
+
|
|
97
|
+
${assessmentResponse.data}
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
# EXPLANATORY COMPONENTS
|
|
102
|
+
These components are designed for explanation and learning support:
|
|
103
|
+
|
|
104
|
+
${explanatoryResponse.data}
|
|
92
105
|
`;
|
|
93
106
|
return combinedContent;
|
|
94
107
|
}
|
|
@@ -122,10 +135,10 @@ const createInitialSidebar = async (slugs, initialLanguage = "en") => {
|
|
|
122
135
|
return sidebar;
|
|
123
136
|
};
|
|
124
137
|
const uploadInitialReadme = async (bucket, exSlug, targetDir, packageContext) => {
|
|
125
|
-
const isGeneratingText = `
|
|
126
|
-
\`\`\`loader slug="${exSlug}"
|
|
127
|
-
:rigo
|
|
128
|
-
\`\`\`
|
|
138
|
+
const isGeneratingText = `
|
|
139
|
+
\`\`\`loader slug="${exSlug}"
|
|
140
|
+
:rigo
|
|
141
|
+
\`\`\`
|
|
129
142
|
`;
|
|
130
143
|
const readmeFilename = `README${(0, creatorUtilities_1.getReadmeExtension)(packageContext.language || "en")}`;
|
|
131
144
|
await uploadFileToBucket(bucket, isGeneratingText, `${targetDir}/${readmeFilename}`);
|
|
@@ -1880,6 +1893,7 @@ class ServeCommand extends SessionCommand_1.default {
|
|
|
1880
1893
|
});
|
|
1881
1894
|
const YT_REGEX = /(?:youtube\.com\/watch\?v=|youtu\.be\/)([\w-]{11})/;
|
|
1882
1895
|
app.get("/actions/fetch/:link", async (req, res) => {
|
|
1896
|
+
var _a, _b, _c;
|
|
1883
1897
|
const { link } = req.params;
|
|
1884
1898
|
console.log("[DEBUG] FETCHING LINK", link);
|
|
1885
1899
|
try {
|
|
@@ -1888,16 +1902,53 @@ class ServeCommand extends SessionCommand_1.default {
|
|
|
1888
1902
|
const ytMatch = decoded.match(YT_REGEX);
|
|
1889
1903
|
console.log("[DEBUG] YT MATCH", ytMatch);
|
|
1890
1904
|
if (ytMatch) {
|
|
1891
|
-
const
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
transcript,
|
|
1900
|
-
|
|
1905
|
+
const TRANSCRIPTAPI_KEY = process.env.TRANSCRIPTAPI_KEY;
|
|
1906
|
+
if (!TRANSCRIPTAPI_KEY) {
|
|
1907
|
+
console.error("TRANSCRIPTAPI_KEY not configured");
|
|
1908
|
+
return res
|
|
1909
|
+
.status(500)
|
|
1910
|
+
.json({ error: "Service configuration error" });
|
|
1911
|
+
}
|
|
1912
|
+
try {
|
|
1913
|
+
const { transcript, language } = await fetchYouTubeTranscript(decoded, TRANSCRIPTAPI_KEY);
|
|
1914
|
+
return res.json({ url: decoded, transcript, language });
|
|
1915
|
+
}
|
|
1916
|
+
catch (error) {
|
|
1917
|
+
if (error.response) {
|
|
1918
|
+
const status = error.response.status;
|
|
1919
|
+
const retryAfter = (_a = error.response.headers) === null || _a === void 0 ? void 0 : _a["retry-after"];
|
|
1920
|
+
if (status === 402) {
|
|
1921
|
+
return res.status(500).json({
|
|
1922
|
+
error: "Service temporarily unavailable. Please try again later.",
|
|
1923
|
+
});
|
|
1924
|
+
}
|
|
1925
|
+
if (status === 404) {
|
|
1926
|
+
return res.status(404).json({
|
|
1927
|
+
error: "Transcript not available for this video",
|
|
1928
|
+
code: "transcript_not_found",
|
|
1929
|
+
});
|
|
1930
|
+
}
|
|
1931
|
+
if (status === 429) {
|
|
1932
|
+
return res.status(429).json({
|
|
1933
|
+
error: "Too many requests. Please try again later.",
|
|
1934
|
+
retryAfter: retryAfter ? parseInt(retryAfter) : 60,
|
|
1935
|
+
});
|
|
1936
|
+
}
|
|
1937
|
+
if (status === 401) {
|
|
1938
|
+
console.error("Invalid TranscriptAPI key");
|
|
1939
|
+
return res
|
|
1940
|
+
.status(500)
|
|
1941
|
+
.json({ error: "Service configuration error" });
|
|
1942
|
+
}
|
|
1943
|
+
console.error("TranscriptAPI error:", error.response.data);
|
|
1944
|
+
return res.status(status).json({
|
|
1945
|
+
error: "Failed to fetch transcript",
|
|
1946
|
+
details: ((_b = error.response.data) === null || _b === void 0 ? void 0 : _b.detail) || ((_c = error.response.data) === null || _c === void 0 ? void 0 : _c.message),
|
|
1947
|
+
});
|
|
1948
|
+
}
|
|
1949
|
+
console.error("Error calling TranscriptAPI:", error);
|
|
1950
|
+
return res.status(500).json({ error: "Internal server error" });
|
|
1951
|
+
}
|
|
1901
1952
|
}
|
|
1902
1953
|
const response = await axios_1.default.get(decoded, { responseType: "text" });
|
|
1903
1954
|
const html = response.data;
|
|
@@ -538,6 +538,9 @@
|
|
|
538
538
|
.hidden {
|
|
539
539
|
display: none;
|
|
540
540
|
}
|
|
541
|
+
.inline-flex {
|
|
542
|
+
display: inline-flex;
|
|
543
|
+
}
|
|
541
544
|
.table {
|
|
542
545
|
display: table;
|
|
543
546
|
}
|
|
@@ -695,6 +698,9 @@
|
|
|
695
698
|
.resize {
|
|
696
699
|
resize: both;
|
|
697
700
|
}
|
|
701
|
+
.list-disc {
|
|
702
|
+
list-style-type: disc;
|
|
703
|
+
}
|
|
698
704
|
.flex-col {
|
|
699
705
|
flex-direction: column;
|
|
700
706
|
}
|
|
@@ -959,6 +965,9 @@
|
|
|
959
965
|
.py-1 {
|
|
960
966
|
padding-block: calc(var(--spacing) * 1);
|
|
961
967
|
}
|
|
968
|
+
.py-1\.5 {
|
|
969
|
+
padding-block: calc(var(--spacing) * 1.5);
|
|
970
|
+
}
|
|
962
971
|
.py-2 {
|
|
963
972
|
padding-block: calc(var(--spacing) * 2);
|
|
964
973
|
}
|
|
@@ -974,6 +983,9 @@
|
|
|
974
983
|
.pb-32 {
|
|
975
984
|
padding-bottom: calc(var(--spacing) * 32);
|
|
976
985
|
}
|
|
986
|
+
.pl-5 {
|
|
987
|
+
padding-left: calc(var(--spacing) * 5);
|
|
988
|
+
}
|
|
977
989
|
.text-center {
|
|
978
990
|
text-align: center;
|
|
979
991
|
}
|