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

Access lesson URL from collection entry #410

Open
eric-burel opened this issue Nov 8, 2024 · 1 comment
Open

Access lesson URL from collection entry #410

eric-burel opened this issue Nov 8, 2024 · 1 comment
Labels
enhancement New feature or request pending triage

Comments

@eric-burel
Copy link
Contributor

Is your feature request related to a problem?

Collection entries are the way you can access to a single lesson using tutorialkit:store or Astro built-in API.

However collection are tad barebone in the fields they provide. A lot of additional logic exists in the getTutorial method used in the main [...slug] route.

The biggest missing point is accessing the lesson URL based on slugs.

Describe the solution you'd like.

Have a way to access the lesson complete URL more easily, using collections.

Describe alternatives you've considered.

Here is some logic I've crafted while building an RSS feed:

/**
 * Dictionary of lesson id to actual slug
 * Not super efficient but will be statically rendered anyway so don't bother
 * { "1_patterns/2_chapter/3_lesson/content.mdx": "part-slug/chapter-slug/lesson-slug" }
 * The key is "lesson.id" in the collection
 * The value is the slug used as URL in the [...slug] page of tutorial kit
 * @returns
 */
async function getSlugs() {
  const chapters = await getCollection(
    "tutorial",
    ({ data }) => data.type === "chapter"
  );
  const parts = await getCollection(
    "tutorial",
    ({ data }) => data.type === "part"
  );
  const lessons = await getCollection(
    "tutorial",
    ({ data }) => data.type === "lesson"
  );
  // p/1_foobar/2_baz/3_qux
  // => we want to turn that into tutorial-slug/part-slug/chapter-slug/lesson-slug
  let ids: Array<string> = lessons.map((l) => l.id);
  const idsToSlugs = new Map<string, string>(ids.map((id) => [id, id]));
  idsToSlugs.forEach((slug, id) => {
    idsToSlugs.set(id, slug.replace("1-patterns", "p"));
    // remove the dangling "/content.mdx"
    idsToSlugs.set(id, slug.replace("/content.mdx", ""));
  });
  parts.forEach((pt) => {
    // id is the actual filename, we want the slug
    // 1_patterns/meta.md => 1_patterns
    const partId = pt.id.split("/")[0];
    idsToSlugs.forEach((slug, id) => {
      // 3_part => part-3-slug
      idsToSlugs.set(id, slug.replace(partId, pt.slug));
    });
  });
  chapters.forEach((ch) => {
    // 1_patterns/2_chapter/meta.md => 2_chapter
    const chapterId = ch.id.split("/")[1];
    idsToSlugs.forEach((slug, id, m) => {
      // 2_chapter => chapter-2-slug
      idsToSlugs.set(id, slug.replace(chapterId, ch.slug));
    });
  });
  lessons.forEach((l) => {
    // 1_patterns/2_chapter/meta.md => 2_chapter
    const lessonId = l.id.split("/")[2];
    idsToSlugs.forEach((slug, id, m) => {
      // 2_chapter => chapter-2-slug
      idsToSlugs.set(id, slug.replace(lessonId, l.slug));
    });
  });
  return Object.fromEntries(idsToSlugs.entries());
}

Not super efficient but does the job: now idsToSlug[lesson.id] gives you the final URL slug of that lesson.

Additional context

I don't know how we can compute derived fields in an Astro entry, if it's possible, nor how we can handle a hierarchy of content, if it's possible.
It might not be possible to rely only on Astro collection system, in which case it could be interesting to expose the getTutorial method or part of it.

@AriPerkkio
Copy link
Member

As far as I know, Astro's getContent returns the data that's on file system only. Is there a way for us to define some virtual collection where we could add these URLs when parsing the markdown files?

If not, what would be the ideal way to access these URLs?

@AriPerkkio AriPerkkio added enhancement New feature or request pending triage labels Nov 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request pending triage
Projects
None yet
Development

No branches or pull requests

2 participants