Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Individual Transcript Page #52

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 114 additions & 28 deletions contentlayer.config.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import path from "path";
import * as fs from "fs";
import { createSlug, SpeakerData, TopicsData, unsluggify } from "./src/utils";
import { defineDocumentType, defineNestedType, makeSource } from "contentlayer2/source-files";
import { Transcript as ContentTranscriptType, Source as ContentSourceType } from "./.contentlayer/generated/types";
import {
defineDocumentType,
defineNestedType,
makeSource,
} from "contentlayer2/source-files";
import {
Transcript as ContentTranscriptType,
Source as ContentSourceType,
} from "./.contentlayer/generated/types";
import { LanguageCodes } from "./src/config";

const Resources = defineNestedType(() => ({
name: "Resources",
Expand Down Expand Up @@ -94,7 +102,11 @@ function organizeTags(transcripts: ContentTranscriptType[]) {
});

// Process all tags at once
const allTags = new Set(transcripts.flatMap((transcript) => transcript.tags?.map((tag) => tag) || []));
const allTags = new Set(
transcripts.flatMap(
(transcript) => transcript.tags?.map((tag) => tag) || []
)
);

allTags.forEach((tag) => {
const catInfo = categoryMap.get(tag);
Expand All @@ -116,11 +128,13 @@ function organizeTags(transcripts: ContentTranscriptType[]) {

// Add "Miscellaneous" category with remaining uncategorized tags
if (tagsWithoutCategory.size > 0) {
tagsByCategory["Miscellaneous"] = Array.from(tagsWithoutCategory).map((tag) => ({
name: tag,
slug: tag,
count: tagCounts[tag] || 0,
}));
tagsByCategory["Miscellaneous"] = Array.from(tagsWithoutCategory).map(
(tag) => ({
name: tag,
slug: tag,
count: tagCounts[tag] || 0,
})
);
}

// Sort tags alphabetically within each category
Expand Down Expand Up @@ -190,7 +204,10 @@ function createSpeakers(transcripts: ContentTranscriptType[]) {
fs.writeFileSync("./public/speaker-data.json", JSON.stringify(speakerArray));
}

function generateSourcesCount(transcripts: ContentTranscriptType[], sources: ContentSourceType[]) {
function generateSourcesCount(
transcripts: ContentTranscriptType[],
sources: ContentSourceType[]
) {
const sourcesArray: TagInfo[] = [];
const slugSources: Record<string, number> = {};

Expand All @@ -204,7 +221,10 @@ function generateSourcesCount(transcripts: ContentTranscriptType[], sources: Con
slugSources[slug] = sourcesLength;

const getSourceName = (slug: string) =>
sources.find((source) => source.language === "en" && source.slugAsParams[0] === slug)?.title ?? unsluggify(slug);
sources.find(
(source) =>
source.language === "en" && source.slugAsParams[0] === slug
)?.title ?? unsluggify(slug);

sourcesArray[sourcesLength] = {
slug,
Expand All @@ -214,12 +234,21 @@ function generateSourcesCount(transcripts: ContentTranscriptType[], sources: Con
}
});

fs.writeFileSync("./public/source-count-data.json", JSON.stringify(sourcesArray));
fs.writeFileSync(
"./public/source-count-data.json",
JSON.stringify(sourcesArray)
);
return { sourcesArray, slugSources };
}

const createTypesCount = (transcripts: ContentTranscriptType[], sources: ContentSourceType[]) => {
const { sourcesArray, slugSources } = generateSourcesCount(transcripts, sources);
const createTypesCount = (
transcripts: ContentTranscriptType[],
sources: ContentSourceType[]
) => {
const { sourcesArray, slugSources } = generateSourcesCount(
transcripts,
sources
);
const nestedTypes: any = {};

sources.forEach((transcript) => {
Expand All @@ -234,7 +263,8 @@ const createTypesCount = (transcripts: ContentTranscriptType[], sources: Content
if (!nestedTypes[slugType]) {
nestedTypes[slugType] = [];
} else {
if (nestedTypes[slugType].includes(getSource) || getSource === null) return;
if (nestedTypes[slugType].includes(getSource) || getSource === null)
return;
nestedTypes[slugType].push(getSource);
}
});
Expand All @@ -244,11 +274,27 @@ const createTypesCount = (transcripts: ContentTranscriptType[], sources: Content
fs.writeFileSync("./public/types-data.json", JSON.stringify(nestedTypes));
};

function organizeContent(transcripts: ContentTranscriptType[], sources: ContentSourceType[]) {
function organizeContent(
transcripts: ContentTranscriptType[],
sources: ContentSourceType[]
) {
const tree: any = {};

sources.forEach((source) => {
const { _id, slugAsParams, language, _raw, weight, body, hosts, transcription_coverage, url, type, types, ...metaData } = source;
const {
_id,
slugAsParams,
language,
_raw,
weight,
body,
hosts,
transcription_coverage,
url,
type,
types,
...metaData
} = source;
const params = source.slugAsParams;
const topParam = params[0] as string;
const nestedSource = params.length > 1;
Expand All @@ -257,16 +303,21 @@ function organizeContent(transcripts: ContentTranscriptType[], sources: ContentS
tree[topParam] = {};
}
const allTranscriptsForSourceLanguage = transcripts.filter(
(transcript) => transcript._raw.sourceFileDir === source._raw.sourceFileDir && transcript.language === language
(transcript) =>
transcript._raw.sourceFileDir === source._raw.sourceFileDir &&
transcript.language === language
);

const allTranscriptsForSourceLanguageURLs = allTranscriptsForSourceLanguage.map((transcript) => transcript.url);
const allTranscriptsForSourceLanguageURLs =
allTranscriptsForSourceLanguage.map((transcript) => transcript.url);

if (!nestedSource) {
tree[topParam] = {
...tree[topParam],
[language]: {
data: allTranscriptsForSourceLanguageURLs.length ? allTranscriptsForSourceLanguageURLs : {},
data: allTranscriptsForSourceLanguageURLs.length
? allTranscriptsForSourceLanguageURLs
: {},
metadata: {
...metaData,
},
Expand All @@ -276,7 +327,9 @@ function organizeContent(transcripts: ContentTranscriptType[], sources: ContentS
tree[topParam][language].data = {
...tree[topParam][language].data,
[params[1]]: {
data: allTranscriptsForSourceLanguageURLs.length ? allTranscriptsForSourceLanguageURLs : {},
data: allTranscriptsForSourceLanguageURLs.length
? allTranscriptsForSourceLanguageURLs
: {},
metadata: {
...metaData,
},
Expand All @@ -288,6 +341,8 @@ function organizeContent(transcripts: ContentTranscriptType[], sources: ContentS
fs.writeFileSync("./public/sources-data.json", JSON.stringify(tree, null, 2));
}

const getLanCode = /[.]\w{2}$/gi // Removes the last two characters if there's a dot

export const Transcript = defineDocumentType(() => ({
name: "Transcript",
filePathPattern: `**/*.md`,
Expand Down Expand Up @@ -322,16 +377,45 @@ export const Transcript = defineDocumentType(() => ({
type: "string",
resolve: (doc) => `/${doc._raw.flattenedPath}`,
},
slugAsParams: {
type: "list",
resolve: (doc) => doc._raw.flattenedPath.split("/"),
},
language: {
type: "string",
resolve: (doc) => {
const transcript = doc._raw.flattenedPath.split("/").pop();
const lan = transcript?.split(".").length === 2 ? transcript?.split(".")[1] : "en";
return lan;
const lan = transcript?.match(getLanCode);
const languageCode = (lan?.[lan.length - 1] || "").replace(".", "");
const finalLanguage = LanguageCodes.includes(languageCode)
? languageCode
: "en";
return finalLanguage;
},
},
languageURL: {
type: "string",
resolve: (doc) => {
const transcript = doc._raw.flattenedPath.split("/").pop();
const fullPathWithoutDot = doc._raw.flattenedPath.replace(
getLanCode,
""
);

const lan = transcript?.match(getLanCode);
const languageCode = (lan?.[0] || "").replace(".", "")

if (LanguageCodes.includes(languageCode)) {
return `/${languageCode}/${fullPathWithoutDot}`;
}

return `/${fullPathWithoutDot}`;
},
},
slugAsParams: {
type: "list",
resolve: (doc) => {
const pathWithoutDot = doc._raw.flattenedPath.replace(
getLanCode,
""
);
return pathWithoutDot.split("/");
},
},
},
Expand All @@ -354,13 +438,15 @@ export const Source = defineDocumentType(() => ({
computedFields: {
url: {
type: "string",
resolve: (doc) => `/${doc._raw.flattenedPath.split("/").slice(0, -1).join("/")}`,
resolve: (doc) =>
`/${doc._raw.flattenedPath.split("/").slice(0, -1).join("/")}`,
},
language: {
type: "string",
resolve: (doc) => {
const index = doc._raw.flattenedPath.split("/").pop();
const lan = index?.split(".").length === 2 ? index?.split(".")[1] : "en";
const lan =
index?.split(".").length === 2 ? index?.split(".")[1] : "en";
return lan;
},
},
Expand Down
32 changes: 22 additions & 10 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,36 @@ const nextConfig = {
return {
fallback: [
{
source: "/:path*.:ext([^/]+)", // intercept all paths ending with a file extension
destination: "/gh-pages/:path*.:ext", // rewrite to gh-pages/[path_here].ext
source: "/:path*.:ext([a-zA-Z0-9_+]{1,4})", // Match extensions that are 1-4 AlphaNumeric characters long
destination: "/gh-pages/:path*.:ext", // Rewrite to gh-pages/[path_here].ext
},
{
source: "/transcripts",
destination: "/gh-pages/index.html",
source: "/tags/:path",
destination: "/gh-pages/tags/:path/index.html",
},
{
source: "/types",
destination: "/gh-pages/categories/index.html",
source: "/speakers/:path",
destination: "/gh-pages/speakers/:path/index.html",
},
{
source: "/:path*",
destination: "/gh-pages/:path*/index.html",
source: "/es",
destination: "/gh-pages/es/index.html",
},
{
source: "/zh",
destination: "/gh-pages/zh/index.html",
},
{
source: "/pt",
destination: "/gh-pages/pt/index.html",
},
{
source: "/:path((?!.*\\.[a-zA-Z0-9]{1,4}$).*)", // Matches paths without a valid file extension
destination: "/transcript/:path*", // Rewrite to /transcripts/[path...]
},
{
source: "/sources/:path((?!.*\\.[^/]+).*)", // Matches /source/[any path without a file extension]
destination: "/[...slug]/:path*", // Replace with your catch-all route
source: "/:path*",
destination: "/gh-pages/:path*/index.html",
},
],
};
Expand Down
Loading