(.*?)<\/inferenceSnippet>/msg
56 | * @param {string} tag - The name of the tag to match content within.
57 | * @param {boolean} [global=false] - Whether to create a global pattern that matches all occurrences.
58 | * @returns {RegExp} - The generated RegExp pattern.
59 | */
60 | export function generateTagRegexWithId(tag, global = false) {
61 | const flags = global ? "msg" : "ms";
62 | const pattern = new RegExp(`<${tag}\\s+id=["'](.+?)["']\\s*>(.*?)<\\/${tag}>`, flags);
63 | return pattern;
64 | }
65 |
--------------------------------------------------------------------------------
/kit/src/app.d.ts:
--------------------------------------------------------------------------------
1 | // See https://kit.svelte.dev/docs/types#app
2 | // for information about these interfaces
3 | declare global {
4 | namespace App {
5 | // interface Error {}
6 | // interface Locals {}
7 | // interface PageData {}
8 | // interface Platform {}
9 | }
10 | }
11 |
12 | export {};
13 |
--------------------------------------------------------------------------------
/kit/src/app.html:
--------------------------------------------------------------------------------
1 | %sveltekit.head% %sveltekit.body%
2 |
--------------------------------------------------------------------------------
/kit/src/lib/Added.svelte:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 | Added in {version}
9 |
10 |
11 |
--------------------------------------------------------------------------------
/kit/src/lib/Changed.svelte:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 | Changed in {version}
9 |
10 |
11 |
--------------------------------------------------------------------------------
/kit/src/lib/CodeBlock.svelte:
--------------------------------------------------------------------------------
1 |
16 |
17 |
24 |
25 |
30 |
31 |
{@html highlighted}
32 |
33 |
--------------------------------------------------------------------------------
/kit/src/lib/CodeBlockFw.svelte:
--------------------------------------------------------------------------------
1 |
23 |
24 |
31 | {#if $group === "group1"}
32 |
33 |
38 |
39 |
{@html group1.highlighted}
42 | {:else}
43 |
44 |
49 |
50 |
{@html group2.highlighted}
53 | {/if}
54 |
55 |
--------------------------------------------------------------------------------
/kit/src/lib/ColabDropdown.svelte:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
21 |
22 |
23 | {#each options as { label, value }}
24 | onClick(value)}
29 | useDeprecatedJS={false}
30 | />
31 | {/each}
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/kit/src/lib/CopyButton.svelte:
--------------------------------------------------------------------------------
1 |
34 |
35 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/kit/src/lib/CourseFloatingBanner.svelte:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/kit/src/lib/Deprecated.svelte:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 | Deprecated in {version}
9 |
10 |
11 |
--------------------------------------------------------------------------------
/kit/src/lib/DocNotebookDropdown.svelte:
--------------------------------------------------------------------------------
1 |
49 |
50 |
51 |
52 |
53 |
54 | {#if googleColabOptions.length === 1}
55 |
56 |
61 |
62 | {:else if googleColabOptions.length > 1}
63 |
64 |
65 |
70 |
71 |
72 | {#each googleColabOptions as { label, value }}
73 | onClick(value)}
78 | useDeprecatedJS={false}
79 | />
80 | {/each}
81 |
82 |
83 | {/if}
84 | {#if awsStudioOptions.length === 1}
85 |
86 |
91 |
92 | {:else if awsStudioOptions.length > 1}
93 |
94 |
95 |
100 |
101 |
102 | {#each awsStudioOptions as { label, value }}
103 | onClick(value)}
108 | useDeprecatedJS={false}
109 | />
110 | {/each}
111 |
112 |
113 | {/if}
114 |
115 |
--------------------------------------------------------------------------------
/kit/src/lib/Dropdown.svelte:
--------------------------------------------------------------------------------
1 |
30 |
31 |
32 |
33 | (isOpen = !isOpen)}
39 | type="button"
40 | >
41 |
42 | {#if $$slots.button}
43 |
44 | {:else}
45 | {#if btnIcon}
46 |
47 | {/if}
48 | {btnLabel}
49 | {#if withBtnCaret}
50 |
51 | {/if}
52 | {/if}
53 |
54 |
55 |
56 | {#if isOpen || useDeprecatedJS}
57 |
63 |
64 |
65 | {/if}
66 |
67 |
68 |
--------------------------------------------------------------------------------
/kit/src/lib/DropdownEntry.svelte:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
33 |
34 | {#if $$slots.default}
35 |
36 | {:else}
37 | {#if icon}
38 |
39 | {/if}
40 | {label}
41 | {/if}
42 |
43 |
44 |
--------------------------------------------------------------------------------
/kit/src/lib/DropdownMenu.svelte:
--------------------------------------------------------------------------------
1 |
41 |
42 |
53 |
--------------------------------------------------------------------------------
/kit/src/lib/EditOnGithub.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
10 | <
11 | >
12 | Update on GitHub
13 |
14 |
--------------------------------------------------------------------------------
/kit/src/lib/ExampleCodeBlock.svelte:
--------------------------------------------------------------------------------
1 |
27 |
28 |
29 |
30 |
31 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/kit/src/lib/FrameworkContent.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 | {#if pytorch}
10 |
11 |
12 |
13 | {/if}
14 | {#if tensorflow}
15 |
16 |
17 |
18 | {/if}
19 | {#if jax}
20 |
21 |
22 |
23 | {/if}
24 |
25 |
--------------------------------------------------------------------------------
/kit/src/lib/FrameworkContentBlock.svelte:
--------------------------------------------------------------------------------
1 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | {label}
74 |
75 | {#if !isClosed}
76 |
80 |
81 | Hide {label} content
82 |
83 | {/if}
84 |
85 | {#if isClosed}
86 |
90 |
91 | Show {label} content
92 |
93 | {:else}
94 |
95 |
96 |
97 | {/if}
98 |
99 |
--------------------------------------------------------------------------------
/kit/src/lib/FrameworkSwitch.svelte:
--------------------------------------------------------------------------------
1 |
44 |
45 |
46 |
49 | {#each GROUPS.filter((g) => ids.includes(g.id)) as g, i}
50 |
changeGroup(g.group)}
55 | >
56 | {#if g.icon}
57 |
58 | {/if}
59 |
60 | {g.name}
61 |
62 |
63 | {/each}
64 |
65 |
66 |
--------------------------------------------------------------------------------
/kit/src/lib/FrameworkSwitchCourse.svelte:
--------------------------------------------------------------------------------
1 |
24 |
25 |
26 | {#each FRAMEWORKS as f, i}
27 |
33 |
34 | {f.name}
35 |
36 | {/each}
37 |
38 |
--------------------------------------------------------------------------------
/kit/src/lib/Heading.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 |
13 |
14 | {#if headingTag === "h1"}
15 |
16 | {title}
21 |
22 | {:else if headingTag === "h2"}
23 |
24 | {title}
29 |
30 | {:else if headingTag === "h3"}
31 |
32 | {title}
37 |
38 | {:else if headingTag === "h4"}
39 |
40 | {title}
45 |
46 | {:else if headingTag === "h5"}
47 |
48 | {title}
53 |
54 | {:else}
55 |
56 | {title}
61 |
62 | {/if}
63 |
--------------------------------------------------------------------------------
/kit/src/lib/HfOption.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 | {#if $selectedHfOptions[id] === option}
9 |
10 | {/if}
11 |
--------------------------------------------------------------------------------
/kit/src/lib/HfOptions.svelte:
--------------------------------------------------------------------------------
1 |
23 |
24 |
25 | {#each options as option}
26 |
updateSelectedOption(option)}
32 | >
33 | {option}
34 |
35 | {/each}
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/kit/src/lib/IconCaretDown.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/kit/src/lib/IconCopy.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
21 |
26 |
27 |
--------------------------------------------------------------------------------
/kit/src/lib/IconCopyLink.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
20 |
--------------------------------------------------------------------------------
/kit/src/lib/IconCurl.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
18 |
22 |
23 |
--------------------------------------------------------------------------------
/kit/src/lib/IconEyeHide.svelte:
--------------------------------------------------------------------------------
1 |
5 |
6 |
14 |
18 |
19 |
--------------------------------------------------------------------------------
/kit/src/lib/IconEyeShow.svelte:
--------------------------------------------------------------------------------
1 |
5 |
6 |
14 |
18 |
19 |
--------------------------------------------------------------------------------
/kit/src/lib/IconJax.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
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 |
57 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/kit/src/lib/IconJs.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
18 |
21 |
22 |
--------------------------------------------------------------------------------
/kit/src/lib/IconNode.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
20 |
--------------------------------------------------------------------------------
/kit/src/lib/IconPython.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
21 |
25 |
26 |
--------------------------------------------------------------------------------
/kit/src/lib/IconPytorch.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/kit/src/lib/IconRust.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
21 |
22 |
--------------------------------------------------------------------------------
/kit/src/lib/IconTensorflow.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
21 |
25 |
29 |
30 |
--------------------------------------------------------------------------------
/kit/src/lib/InferenceApi.svelte:
--------------------------------------------------------------------------------
1 |
52 |
53 |
54 | {#each LANGUAGES_CONFIG.filter((c) => snippetExists[c.id]) as language}
55 |
updateSelectedOption(language.id)}
61 | >
62 |
63 | {language.label}
64 |
65 | {/each}
66 |
67 |
68 | {#if python && $selectedInferenceLang === "python"}
69 |
70 | {/if}
71 | {#if js && $selectedInferenceLang === "js"}
72 |
73 | {/if}
74 | {#if curl && $selectedInferenceLang === "curl"}
75 |
76 | {/if}
77 |
78 |
--------------------------------------------------------------------------------
/kit/src/lib/InferenceSnippet/IconInferenceBlackForest.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/kit/src/lib/InferenceSnippet/IconInferenceCerebras.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
18 |
24 |
25 |
--------------------------------------------------------------------------------
/kit/src/lib/InferenceSnippet/IconInferenceCohere.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
18 |
24 |
30 |
34 |
35 |
--------------------------------------------------------------------------------
/kit/src/lib/InferenceSnippet/IconInferenceFal.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
23 |
24 |
--------------------------------------------------------------------------------
/kit/src/lib/InferenceSnippet/IconInferenceFeatherless.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
18 |
19 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/kit/src/lib/InferenceSnippet/IconInferenceFireworks.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
21 |
27 |
28 |
--------------------------------------------------------------------------------
/kit/src/lib/InferenceSnippet/IconInferenceGroq.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
18 |
22 |
23 |
--------------------------------------------------------------------------------
/kit/src/lib/InferenceSnippet/IconInferenceHf.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
27 |
33 |
34 |
--------------------------------------------------------------------------------
/kit/src/lib/InferenceSnippet/IconInferenceHyperbolic.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
21 |
25 |
29 |
33 |
37 |
38 |
--------------------------------------------------------------------------------
/kit/src/lib/InferenceSnippet/IconInferenceNebius.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
18 |
24 |
25 |
--------------------------------------------------------------------------------
/kit/src/lib/InferenceSnippet/IconInferenceNovita.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
18 |
19 |
23 |
24 |
--------------------------------------------------------------------------------
/kit/src/lib/InferenceSnippet/IconInferenceNscale.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
18 |
22 |
27 |
32 |
33 |
--------------------------------------------------------------------------------
/kit/src/lib/InferenceSnippet/IconInferenceReplicate.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
25 |
31 |
32 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/kit/src/lib/InferenceSnippet/IconInferenceSambaNova.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
21 |
25 |
29 |
30 |
--------------------------------------------------------------------------------
/kit/src/lib/InferenceSnippet/IconInferenceTogetherAI.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
18 |
22 |
28 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/kit/src/lib/InferenceSnippet/IconLinkExternal.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
18 |
24 |
31 |
32 |
--------------------------------------------------------------------------------
/kit/src/lib/InferenceSnippet/IconSettings.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
21 |
22 |
--------------------------------------------------------------------------------
/kit/src/lib/Markdown.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcon.svelte:
--------------------------------------------------------------------------------
1 |
79 |
80 |
84 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconAudioClassification.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
21 |
22 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconAudioToAudio.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
23 |
24 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconAutomaticSpeechRecognition.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
23 |
24 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconConversational.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
18 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconDocumentQuestionAnswering.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
14 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconFeatureExtraction.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
18 |
21 |
22 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconFillMask.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
18 |
21 |
24 |
27 |
28 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconImageClassification.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
18 |
19 |
20 |
23 |
24 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconImageSegmentation.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
18 |
21 |
24 |
25 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconImageToImage.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
18 |
25 |
26 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconImageToText.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
17 |
21 |
25 |
29 |
30 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconObjectDetection.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
18 |
21 |
24 |
27 |
28 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconQuestionAnswering.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
14 |
15 |
16 |
17 |
21 |
22 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconReinforcementLearning.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
18 |
19 |
23 |
24 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconRobotics.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
18 |
22 |
23 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconSentenceSimilarity.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
18 |
19 |
20 |
23 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconSummarization.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
18 |
21 |
24 |
25 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconTableQuestionAnswering.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
18 |
21 |
22 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconTabularClassification.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
18 |
22 |
23 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconTabularRegression.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
16 |
20 |
21 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconText2textGeneration.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
18 |
21 |
24 |
27 |
28 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconTextClassification.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconTextGeneration.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
18 |
21 |
22 |
25 |
26 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconTextToImage.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
18 |
25 |
26 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconTextToSpeech.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
23 |
24 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconTokenClassification.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
18 |
19 |
20 |
21 |
24 |
27 |
30 |
33 |
34 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconTranslation.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
18 |
21 |
24 |
25 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconUnconditionalImageGeneration.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
18 |
25 |
26 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconVoiceActivityDetection.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
17 |
23 |
24 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineIcons/IconZeroShotClassification.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
18 |
21 |
24 |
27 |
30 |
33 |
36 |
39 |
42 |
45 |
48 |
51 |
52 |
--------------------------------------------------------------------------------
/kit/src/lib/PipelineTag.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 | {PIPELINE_DATA[pipeline].name ?? pipeline}
13 |
14 |
15 |
--------------------------------------------------------------------------------
/kit/src/lib/Question.svelte:
--------------------------------------------------------------------------------
1 |
55 |
56 |
102 |
--------------------------------------------------------------------------------
/kit/src/lib/Tip.svelte:
--------------------------------------------------------------------------------
1 |
5 |
6 |
10 |
11 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/kit/src/lib/TokenizersLanguageContent.svelte:
--------------------------------------------------------------------------------
1 |
50 |
51 |
52 | {#each LANGUAGES_CONFIG as language}
53 |
updateSelectedOption(language.id)}
59 | >
60 |
61 | {language.label}
62 |
63 | {/each}
64 |
65 |
66 | {#if python && $selectedTokenizersLang === "python"}
67 |
68 | {/if}
69 | {#if rust && $selectedTokenizersLang === "rust"}
70 |
71 | {/if}
72 | {#if node && $selectedTokenizersLang === "node"}
73 |
74 | {/if}
75 |
76 |
--------------------------------------------------------------------------------
/kit/src/lib/Tooltip.svelte:
--------------------------------------------------------------------------------
1 |
6 |
7 |
23 |
--------------------------------------------------------------------------------
/kit/src/lib/TooltipFromAction.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 | {#if txt}
9 |
19 | {@html txt}
20 |
21 | {/if}
22 |
--------------------------------------------------------------------------------
/kit/src/lib/Youtube.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
13 |
--------------------------------------------------------------------------------
/kit/src/lib/copyToClipboard.ts:
--------------------------------------------------------------------------------
1 | export function copyToClipboard(value: string): void {
2 | const textArea = document.createElement("textarea");
3 | document.body.appendChild(textArea);
4 | textArea.value = value;
5 | textArea.select();
6 | document.execCommand("copy");
7 | document.body.removeChild(textArea);
8 | }
9 |
--------------------------------------------------------------------------------
/kit/src/lib/stores.ts:
--------------------------------------------------------------------------------
1 | import type { Writable } from "svelte/store";
2 | import { writable } from "svelte/store";
3 | import type { Group, Framework, InferenceSnippetLang, TokenizersLanguage } from "./types";
4 |
5 | // used for CodeBlockFw.svelte
6 | const groups: Record> = {};
7 | export function getGroupStore(key: string): Writable {
8 | if (!groups[key]) {
9 | groups[key] = writable("group1");
10 | }
11 | return groups[key];
12 | }
13 |
14 | // used for FrameworkContent.svelte
15 | export enum AccordianState {
16 | OPEN = "OPEN",
17 | CLOSED = "CLOSED",
18 | HASHASHLINK = "HASHASHLINK",
19 | }
20 | const frameworks: Partial>> = {};
21 | export function getFrameworkStore(key: Framework): Writable {
22 | return (frameworks[key] = frameworks[key] || writable(AccordianState.OPEN));
23 | }
24 |
25 | // used for Question.svelte
26 | export const answers = writable<{ [key: string]: { correct: boolean } }>({});
27 |
28 | // used for InferenceApi.svelte
29 | export const selectedInferenceLang = writable("python");
30 |
31 | // used for TokenizersLanguageContent.svelte
32 | export const selectedTokenizersLang = writable("python");
33 |
34 | // used for HfOptions.svelte
35 | export const selectedHfOptions = writable>({});
36 |
--------------------------------------------------------------------------------
/kit/src/lib/tooltip.ts:
--------------------------------------------------------------------------------
1 | import Tooltip from "./TooltipFromAction.svelte";
2 |
3 | const id = "docstring-tooltip";
4 |
5 | export function tooltip(element: HTMLElement, txt: string): any {
6 | let tooltipComponent: any;
7 | function mouseOver(event: MouseEvent) {
8 | cleanPrevious();
9 | tooltipComponent = new Tooltip({
10 | props: {
11 | txt,
12 | x: event.pageX,
13 | y: event.pageY,
14 | id,
15 | },
16 | target: document.body,
17 | });
18 | }
19 | function mouseMove(event: MouseEvent) {
20 | tooltipComponent.$set({
21 | x: event.pageX,
22 | y: event.pageY,
23 | });
24 | }
25 | function mouseLeave() {
26 | tooltipComponent.$destroy();
27 | }
28 |
29 | function cleanPrevious() {
30 | const tooltipComponent = document.getElementById(id);
31 | if (tooltipComponent) {
32 | tooltipComponent.parentNode?.removeChild(tooltipComponent);
33 | }
34 | }
35 |
36 | element.addEventListener("mouseover", mouseOver);
37 | element.addEventListener("mouseleave", mouseLeave);
38 | element.addEventListener("mousemove", mouseMove);
39 |
40 | return {
41 | destroy() {
42 | element.removeEventListener("mouseover", mouseOver);
43 | element.removeEventListener("mouseleave", mouseLeave);
44 | element.removeEventListener("mousemove", mouseMove);
45 | },
46 | };
47 | }
48 |
--------------------------------------------------------------------------------
/kit/src/lib/types.ts:
--------------------------------------------------------------------------------
1 | export type Group = "group1" | "group2";
2 |
3 | export type Framework = "pytorch" | "tensorflow" | "jax";
4 |
5 | export type TokenizersLanguage = "python" | "rust" | "node";
6 |
7 | export type CourseFramework = "pt" | "tf";
8 |
9 | export type InferenceSnippetLang = "python" | "js" | "curl";
10 |
11 | export interface Pipeline {
12 | name: string;
13 | subtasks?: { type: string; name: string }[];
14 | modality: string;
15 | color: string;
16 | hideInModels?: boolean;
17 | hideInDatasets?: boolean;
18 | }
19 |
--------------------------------------------------------------------------------
/kit/src/lib/utils.ts:
--------------------------------------------------------------------------------
1 | export function updateQueryParamAndReplaceHistory(key: string, value: string) {
2 | // 1. Parse the current URL.
3 | const currentUrl = new URL(window.location.href);
4 | // 2. Use URLSearchParams to manipulate the query parameters.
5 | const searchParams = new URLSearchParams(currentUrl.search);
6 | // 3. Update the specific query parameter.
7 | searchParams.set(key, value);
8 | // 4. Construct the new URL.
9 | currentUrl.search = searchParams.toString();
10 | // 5. Push the new URL to browser's history.
11 | history.replaceState(null, "", currentUrl.toString());
12 | }
13 |
14 | export function getQueryParamValue(key: string) {
15 | // 1. Parse the current URL.
16 | const currentUrl = new URL(window.location.href);
17 | // 2. Use URLSearchParams to get the value of the specified query parameter.
18 | const searchParams = new URLSearchParams(currentUrl.search);
19 | return searchParams.get(key); // This will return the value or null if the key is not found.
20 | }
21 |
--------------------------------------------------------------------------------
/kit/src/routes/+layout.svelte:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 | {#if !import.meta.env.DEV}
12 |
13 | {:else}
14 |
21 |
24 |
25 |
26 | {#each toc as section}
27 | {#if section.local}
28 | {section.title}
33 | {:else}
34 | {section.title}
38 | {/if}
39 | {/each}
40 |
41 |
42 |
47 |
48 | Sub side menu
49 |
50 |
51 | {/if}
52 |
--------------------------------------------------------------------------------
/kit/src/routes/+layout.ts:
--------------------------------------------------------------------------------
1 | import { base } from "$app/paths";
2 |
3 | // This can be false if you're using a fallback (i.e. SPA mode)
4 | export const prerender = true;
5 |
6 | /** @type {import('./$types').PageLoad} */
7 | export async function load({ fetch }) {
8 | if (!import.meta.env.DEV) {
9 | return {};
10 | }
11 | const toc = await fetch(base + "/endpoints/toc");
12 | return {
13 | toc: await toc.json()
14 | };
15 | }
--------------------------------------------------------------------------------
/kit/src/routes/endpoints/toc/+server.ts:
--------------------------------------------------------------------------------
1 | import path from "path";
2 | import fs from "fs";
3 | import yaml from "js-yaml";
4 | import { fileURLToPath } from "url";
5 | import { json } from '@sveltejs/kit';
6 |
7 | export interface RawChapter {
8 | title: string;
9 | local?: string;
10 | new?: boolean;
11 | local_fw?: { pt: string; tf: string; };
12 | quiz?: string;
13 | sections?: RawChapter[];
14 | }
15 |
16 | const flattener = (_flatChapters: RawChapter[], chapter: RawChapter): RawChapter[] => {
17 | const sections = chapter?.sections as RawChapter[];
18 | _flatChapters.push(chapter);
19 | if (sections) {
20 | for (const section of sections) {
21 | flattener(_flatChapters, section);
22 | }
23 | }
24 | return _flatChapters;
25 | };
26 |
27 | export async function GET() {
28 | const filepath = path.join(fileURLToPath(import.meta.url), '../../..', '_toctree.yml');
29 | const content = (await fs.promises.readFile(filepath)).toString("utf-8");
30 |
31 | const chapters: RawChapter[] = yaml.load(content) as RawChapter[];
32 | const chaptersFlat: RawChapter[] = chapters.reduce(flattener, []);
33 |
34 | return json(chaptersFlat);
35 | }
36 |
--------------------------------------------------------------------------------
/kit/static/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huggingface/doc-builder/0967fa8065bbe9b5b1c7599f8109014064e3b6e6/kit/static/favicon.png
--------------------------------------------------------------------------------
/kit/svelte.config.js:
--------------------------------------------------------------------------------
1 | import adapter from "@sveltejs/adapter-static";
2 | import { vitePreprocess } from "@sveltejs/kit/vite";
3 |
4 | import {
5 | docstringPreprocess,
6 | frameworkcontentPreprocess,
7 | mdsvexPreprocess,
8 | inferenceSnippetPreprocess,
9 | tokenizersLangPreprocess,
10 | hfOptionsPreprocess,
11 | hashInCodePreprocess,
12 | } from "./preprocessors/index.js";
13 |
14 | /** @type {import('@sveltejs/kit').Config} */
15 | const config = {
16 | // Consult https://kit.svelte.dev/docs/integrations#preprocessors
17 | // for more information about preprocessors
18 | preprocess: [
19 | hashInCodePreprocess,
20 | docstringPreprocess,
21 | frameworkcontentPreprocess,
22 | inferenceSnippetPreprocess,
23 | tokenizersLangPreprocess,
24 | hfOptionsPreprocess,
25 | mdsvexPreprocess,
26 | vitePreprocess({}),
27 | ],
28 |
29 | kit: {
30 | // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
31 | // If your environment is not supported or you settled on a specific environment, switch out the adapter.
32 | // See https://kit.svelte.dev/docs/adapters for more information about adapters.
33 | adapter: adapter({ strict: false }),
34 |
35 | prerender: {
36 | crawl: false, // Do not throw if linked page doesn't exist (eg when forgetting the language prefix)
37 | },
38 |
39 | paths: {
40 | base: process.argv.includes("dev")
41 | ? ""
42 | : "/docs/" +
43 | (process.env.DOCS_LIBRARY || "transformers") +
44 | "/" +
45 | (process.env.DOCS_VERSION || "main") +
46 | "/" +
47 | (process.env.DOCS_LANGUAGE || "en"),
48 | relative: false,
49 | },
50 | },
51 |
52 | onwarn: (warning, handler) => {
53 | if (
54 | warning.message.includes("has unused export property 'fw'") ||
55 | warning.message.includes("A11y")
56 | ) {
57 | /// Too noisy
58 | return;
59 | }
60 | handler(warning);
61 | },
62 | };
63 |
64 | export default config;
65 |
--------------------------------------------------------------------------------
/kit/svelteKitCustomClient/README.md:
--------------------------------------------------------------------------------
1 | # Custom `sveltekit client.js` file
2 |
3 | Sveltekit handles [internal routes](https://kit.svelte.dev/docs/routing) by:
4 |
5 | 1. partially loading changed components
6 | 2. updating the browser's [history](https://developer.mozilla.org/en-US/docs/Web/API/History)
7 |
8 | which makes the user experience better by not loading/reloading pages completely from scratch.
9 |
10 | ### Hugging Face docs
11 |
12 | In [hf docs](https://huggingface.co/docs), we have these redirection rules:
13 |
14 | ```
15 | hf.co/docs/lib/page -> hf.co/docs/lib/default_version/default_lang/page
16 | hf.co/docs/lib/version/page -> hf.co/docs/lib/version/default_lang/page
17 | ```
18 |
19 | However, these rules were being handled as external routes by SvelteKit without taking advantage of partial reloadings. I've tried using [$app/navigation](https://kit.svelte.dev/docs/modules#$app-navigation) without success. Therefore, the simplest solution was: overwriting [sveltekit client.js](https://github.com/sveltejs/kit/blob/master/packages/kit/src/runtime/client/client.js) to handle hf doc routes accordingly.
20 |
21 | Specifically, this [custom client.js](https://github.com/huggingface/doc-builder/blob/ab03d33801595579591ac8cdc49514c4f59fe068/kit/svelteKitCustomClient/client.js) is identical to [sveltekit client.js](https://github.com/sveltejs/kit/blob/master/packages/kit/src/runtime/client/client.js) with only one difference: addition and usage of [getHfDocFullPath function](https://github.com/huggingface/doc-builder/blob/ab03d33801595579591ac8cdc49514c4f59fe068/kit/svelteKitCustomClient/client.js#L43), which makes it possible for hf redirected paths (as described above) to be considered as `internal routes` and take full advantage of partial loading.
22 |
--------------------------------------------------------------------------------
/kit/svelteKitCustomClient/replace.js:
--------------------------------------------------------------------------------
1 | import fs from "fs";
2 | import path from "path";
3 | import { runtime_directory } from "../node_modules/@sveltejs/kit/src/core/utils.js";
4 |
5 | // Step 1: replace client.js
6 | const sourceFilePathClient = path.resolve("./svelteKitCustomClient/client.js");
7 | const destinationFilePathClient = path.join(runtime_directory, "client/client.js");
8 | fs.copyFileSync(sourceFilePathClient, destinationFilePathClient);
9 |
10 | // Step 2: export hf doc const env vars
11 | const sourceFilePathConsts = path.join(runtime_directory, "client/hfDocConsts.js");
12 | const constsString = `export const DOCS_LIBRARY = "${process.env.DOCS_LIBRARY}";
13 | export const DOCS_VERSION = "${process.env.DOCS_VERSION}";
14 | export const DOCS_LANGUAGE = "${process.env.DOCS_LANGUAGE}";`;
15 | fs.writeFileSync(sourceFilePathConsts, constsString, "utf8");
16 |
--------------------------------------------------------------------------------
/kit/tailwind.config.cjs:
--------------------------------------------------------------------------------
1 | const defaultTheme = require("tailwindcss/defaultTheme");
2 | const colors = require("tailwindcss/colors");
3 |
4 | module.exports = {
5 | content: ["./src/**/*.{svelte,ts,mdx}"],
6 |
7 | darkMode: "class",
8 | theme: {
9 | container: {
10 | center: true,
11 | padding: { DEFAULT: "1rem" },
12 | },
13 | extend: {
14 | colors: {
15 | orange: colors.orange,
16 | teal: colors.teal,
17 | sky: colors.sky,
18 | violet: colors.violet,
19 | fuchsia: colors.fuchsia,
20 | pink: colors.pink,
21 | lime: colors.lime,
22 | cyan: colors.cyan,
23 | gray: {
24 | 350: "#b3bcc9",
25 | // Dark blue
26 | // 925: '#131f3d',
27 | // 950: '#0a1226',
28 | // Darker
29 | 850: "#141c2e",
30 | 925: "#101623",
31 | 950: "#0b0f19",
32 | // Darkest
33 | // 925: '#081122',
34 | // 950: '#000511',
35 | },
36 | },
37 | maxWidth: {
38 | "2xs": "16rem",
39 | },
40 | screens: {
41 | "with-hover": { raw: "(hover: hover)" },
42 | "no-hover": { raw: "(hover: none)" },
43 | },
44 | gridTemplateRows: {
45 | full: "100%",
46 | },
47 | fontFamily: {
48 | sans: ["Source Sans Pro", ...defaultTheme.fontFamily.sans],
49 | mono: ["IBM Plex Mono", ...defaultTheme.fontFamily.mono],
50 | serif: ["Charter", ...defaultTheme.fontFamily.serif],
51 | },
52 | fontSize: {
53 | smd: "0.94rem",
54 | },
55 | typography: (theme) => ({
56 | light: {
57 | css: [
58 | {
59 | color: theme("colors.gray.350"),
60 | '[class~="lead"]': {
61 | color: theme("colors.gray.300"),
62 | },
63 | a: {
64 | color: theme("colors.gray.300"),
65 | },
66 | strong: {
67 | color: theme("colors.gray.300"),
68 | },
69 | "ol > li::before": {
70 | color: theme("colors.gray.400"),
71 | },
72 | "ul > li::before": {
73 | backgroundColor: theme("colors.gray.600"),
74 | },
75 | hr: {
76 | borderColor: theme("colors.gray.200"),
77 | },
78 | blockquote: {
79 | color: theme("colors.gray.200"),
80 | borderLeftColor: theme("colors.gray.600"),
81 | },
82 | h1: {
83 | color: theme("colors.gray.200"),
84 | },
85 | h2: {
86 | color: theme("colors.gray.200"),
87 | },
88 | h3: {
89 | color: theme("colors.gray.200"),
90 | },
91 | h4: {
92 | color: theme("colors.gray.200"),
93 | },
94 | "figure figcaption": {
95 | color: theme("colors.gray.400"),
96 | },
97 | code: {
98 | color: theme("colors.gray.300"),
99 | },
100 | "a code": {
101 | color: theme("colors.gray.300"),
102 | },
103 | pre: {
104 | color: theme("colors.gray.300"),
105 | backgroundColor: theme("colors.gray.925"),
106 | },
107 | thead: {
108 | color: theme("colors.gray.200"),
109 | borderBottomColor: theme("colors.gray.400"),
110 | },
111 | "tbody tr": {
112 | borderBottomColor: theme("colors.gray.600"),
113 | },
114 | },
115 | ],
116 | },
117 | DEFAULT: {
118 | css: {
119 | color: colors.gray[600],
120 | maxWidth: "100%",
121 | fontSize: "1.05rem",
122 | h1: {
123 | fontSize: theme("fontSize.xl")[0],
124 | color: theme("colors.gray.700"),
125 | marginBottom: "1.7rem",
126 | fontWeight: 600,
127 | },
128 | h2: {
129 | fontSize: theme("fontSize.xl")[0],
130 | color: theme("colors.gray.700"),
131 | fontWeight: 600,
132 | },
133 |
134 | h3: {
135 | fontSize: theme("fontSize.xl")[0],
136 | color: theme("colors.gray.700"),
137 | fontWeight: 600,
138 | },
139 | h4: {
140 | fontSize: theme("fontSize.lg")[0],
141 | color: theme("colors.gray.700"),
142 | fontWeight: 600,
143 | },
144 | pre: {
145 | color: "currentColor",
146 | backgroundColor: theme("colors.gray.50"),
147 | },
148 | },
149 | },
150 | }),
151 | zIndex: {
152 | 5: "5",
153 | 2: "2",
154 | 1: "1",
155 | "-1": "-1",
156 | },
157 | },
158 | },
159 | plugins: [
160 | require("@tailwindcss/forms"),
161 | require("@tailwindcss/typography"),
162 | require("@tailwindcss/aspect-ratio"),
163 | ],
164 | };
165 |
--------------------------------------------------------------------------------
/kit/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.svelte-kit/tsconfig.json",
3 | "compilerOptions": {
4 | "allowJs": true,
5 | "checkJs": true,
6 | "esModuleInterop": true,
7 | "forceConsistentCasingInFileNames": true,
8 | "resolveJsonModule": true,
9 | "skipLibCheck": true,
10 | "sourceMap": true,
11 | "strict": true
12 | }
13 | // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
14 | //
15 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
16 | // from the referenced tsconfig.json - TypeScript does not merge them in
17 | }
18 |
--------------------------------------------------------------------------------
/kit/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { sveltekit } from "@sveltejs/kit/vite";
2 | import { defineConfig } from "vite";
3 |
4 | export default defineConfig({
5 | plugins: [sveltekit()],
6 | build: {
7 | sourcemap: Boolean(process.env.DOCS_SOURCEMAP),
8 | },
9 | });
10 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.black]
2 | line-length = 119
3 | target-version = ['py39']
4 |
--------------------------------------------------------------------------------
/scripts/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "tabWidth": 2,
3 | "useTabs": true,
4 | "printWidth": 120
5 | }
6 |
--------------------------------------------------------------------------------
/scripts/delete-old-prs.ts:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env -S deno run --allow-env --allow-net --allow-run --allow-read
2 | // To format: npx prettier --write .
3 | import { commit, listFiles } from "npm:@huggingface/hub@0.15.1";
4 |
5 | const oneMonthAgo = new Date(Date.now() - 30 * 24 * 3600 * 1000);
6 |
7 | const allFiles = listFiles({
8 | repo: { type: "dataset", name: "hf-doc-build/doc-build-dev" },
9 | recursive: true,
10 | expand: true,
11 | });
12 |
13 | const filesToDelete: string[] = [];
14 |
15 | let fileCount = 0;
16 | let filesWithoutDates = 0;
17 |
18 | for await (const file of allFiles) {
19 | fileCount++;
20 |
21 | if (file.type !== "file" || !file.path.endsWith(".zip")) {
22 | continue;
23 | }
24 |
25 | const date = file.lastCommit?.date;
26 |
27 | if (!date) {
28 | filesWithoutDates++;
29 | continue;
30 | }
31 |
32 | if (oneMonthAgo < new Date(date)) {
33 | continue;
34 | }
35 |
36 | filesToDelete.push(file.path);
37 | }
38 |
39 | console.log({fileCount, filesWithoutDates});
40 |
41 | if (filesToDelete.length) {
42 | console.log("deleting", filesToDelete.length, "files");
43 | await commit({
44 | repo: { type: "dataset", name: "hf-doc-build/doc-build-dev" },
45 | credentials: { accessToken: Deno.env.get("HF_ACCESS_TOKEN") },
46 | title: "Delete old docs",
47 | operations: filesToDelete.map((file) => ({
48 | operation: "delete",
49 | path: file,
50 | })),
51 | });
52 | }
53 |
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [isort]
2 | default_section = FIRSTPARTY
3 | ensure_newline_before_comments = True
4 | force_grid_wrap = 0
5 | include_trailing_comma = True
6 | known_first_party = transformers
7 | line_length = 119
8 | lines_after_imports = 2
9 | multi_line_output = 3
10 | use_parentheses = True
11 |
12 | [flake8]
13 | ignore = E203, E501, E741, W503, W605
14 | max-line-length = 119
15 |
16 | [tool:pytest]
17 | doctest_optionflags=NUMBER NORMALIZE_WHITESPACE ELLIPSIS
18 |
19 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | # Doc-builder package setup.
2 | # The line above is checked by some of the utilities in this repo, do not change it.
3 |
4 | from setuptools import find_packages, setup
5 |
6 | install_requires = ["black", "GitPython", "tqdm", "pyyaml", "packaging", "nbformat", "huggingface_hub", "pillow"]
7 |
8 | extras = {}
9 |
10 | extras["transformers"] = ["transformers[dev]"]
11 | extras["testing"] = ["pytest", "pytest-xdist", "torch", "transformers", "tokenizers", "timm", "google-api-python-client", "requests"]
12 | extras["quality"] = ["black~=22.0", "isort>=5.5.4", "flake8>=3.8.3"]
13 |
14 | extras["all"] = extras["testing"] + extras["quality"]
15 | extras["dev"] = extras["all"]
16 |
17 | # Should only be utilized by core-devs for release
18 | extras["release"] = ["twine"]
19 |
20 |
21 | setup(
22 | name="hf-doc-builder",
23 | version="0.6.0.dev0",
24 | author="Hugging Face, Inc.",
25 | license="Apache",
26 | author_email="docs@huggingface.co",
27 | description="Doc building utility",
28 | long_description=open("README.md", "r", encoding="utf-8").read(),
29 | long_description_content_type="text/markdown",
30 | keywords="doc documentation doc-builder huggingface hugging face",
31 | url="https://github.com/huggingface/doc-builder",
32 | package_dir={"": "src"},
33 | packages=find_packages("src"),
34 | extras_require=extras,
35 | install_requires=install_requires,
36 | entry_points={"console_scripts": ["doc-builder=doc_builder.commands.doc_builder_cli:main"]},
37 | )
38 |
39 | # Release checklist
40 | # 1. Checkout the release branch (for a patch the current release branch, for a new minor version, create one):
41 | # git checkout -b vXX.xx-release
42 | # The -b is only necessary for creation (so remove it when doing a patch)
43 | # 2. Change the version in __init__.py and setup.py to the proper value.
44 | # 3. Commit these changes with the message: "Release: v"
45 | # 4. Add a tag in git to mark the release:
46 | # git tag v -m 'Adds tag v for pypi'
47 | # Push the tag and release commit to git: git push --tags origin vXX.xx-release
48 | # 5. Run the following commands in the top-level directory:
49 | # rm -rf dist
50 | # rm -rf build
51 | # python setup.py bdist_wheel
52 | # python setup.py sdist
53 | # 6. Upload the package to the pypi test server first:
54 | # twine upload dist/* -r testpypi
55 | # 7. Check that you can install it in a virtualenv by running:
56 | # pip install hf-doc-builder
57 | # pip uninstall hf-doc-builder
58 | # pip install -i https://testpypi.python.org/pypi hf-doc-builder
59 | # It's recommended to check that there are no issues building the docs,
60 | # so try running a command like `doc-builder`
61 | # 8. Upload the final version to actual pypi:
62 | # twine upload dist/* -r pypi
63 | # 9. Add release notes to the tag in github once everything is looking hunky-dory.
64 | # 10. Go back to the main branch and update the version in __init__.py, setup.py to the new version ".dev" and push to
65 | # main.
--------------------------------------------------------------------------------
/src/doc_builder/__init__.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | # Copyright 2021 The HuggingFace Team. All rights reserved.
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 |
16 | # flake8: noqa
17 | # There's no way to ignore "F401 '...' imported but unused" warnings in this
18 | # module, but to preserve other warnings. So, don't check this module at all.
19 |
20 | __version__ = "0.6.0.dev0"
21 |
22 | from .autodoc import autodoc
23 | from .build_doc import build_doc
24 | from .convert_rst_to_mdx import convert_rst_docstring_to_mdx, convert_rst_to_mdx
25 | from .style_doc import style_doc_files
26 | from .utils import update_versions_file
27 |
--------------------------------------------------------------------------------
/src/doc_builder/commands/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huggingface/doc-builder/0967fa8065bbe9b5b1c7599f8109014064e3b6e6/src/doc_builder/commands/__init__.py
--------------------------------------------------------------------------------
/src/doc_builder/commands/doc_builder_cli.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | # Copyright 2021 The HuggingFace Team. All rights reserved.
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 |
16 |
17 | from argparse import ArgumentParser
18 |
19 | from doc_builder.commands.build import build_command_parser
20 | from doc_builder.commands.convert_doc_file import convert_command_parser
21 | from doc_builder.commands.notebook_to_mdx import notebook_to_mdx_command_parser
22 | from doc_builder.commands.preview import preview_command_parser
23 | from doc_builder.commands.push import push_command_parser
24 | from doc_builder.commands.style import style_command_parser
25 |
26 |
27 | def main():
28 | parser = ArgumentParser("Doc Builder CLI tool", usage="doc-builder []")
29 | subparsers = parser.add_subparsers(help="doc-builder command helpers")
30 |
31 | # Register commands
32 | convert_command_parser(subparsers=subparsers)
33 | build_command_parser(subparsers=subparsers)
34 | notebook_to_mdx_command_parser(subparsers=subparsers)
35 | style_command_parser(subparsers=subparsers)
36 | preview_command_parser(subparsers=subparsers)
37 | push_command_parser(subparsers=subparsers)
38 |
39 | # Let's go
40 | args = parser.parse_args()
41 |
42 | if not hasattr(args, "func"):
43 | parser.print_help()
44 | exit(1)
45 |
46 | # Run
47 | args.func(args)
48 |
49 |
50 | if __name__ == "__main__":
51 | main()
52 |
--------------------------------------------------------------------------------
/src/doc_builder/commands/notebook_to_mdx.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | # Copyright 2021 The HuggingFace Team. All rights reserved.
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 |
16 | import argparse
17 | import base64
18 | import io
19 | from pathlib import Path
20 |
21 | import nbformat
22 | from PIL import Image
23 | from tqdm import tqdm
24 |
25 | from ..style_doc import format_code_example
26 |
27 |
28 | def png_to_jpeg(png_base64):
29 | png_bytes = base64.b64decode(png_base64)
30 | png_image = Image.open(io.BytesIO(png_bytes))
31 | png_image = png_image.convert("RGB")
32 | jpeg_bytes = io.BytesIO()
33 | png_image.save(jpeg_bytes, format="JPEG")
34 | jpeg_base64 = base64.b64encode(jpeg_bytes.getvalue()).decode("utf-8")
35 | return jpeg_base64
36 |
37 |
38 | def notebook_to_mdx(notebook, max_len):
39 | content = []
40 | for cell in notebook["cells"]:
41 | if cell["cell_type"] == "code":
42 | code = cell["source"]
43 | outputs = [
44 | o
45 | for o in cell["outputs"]
46 | if ("text" in o and o.get("name", None) == "stdout")
47 | or "text/plain" in o
48 | or ("data" in o and ("image/png" in o["data"] or "image/jpeg" in o["data"]))
49 | ]
50 |
51 | if len(outputs) > 0:
52 | code_lines = code.split("\n")
53 | # We can add >>> everywhere without worrying as format_code_example will replace them by ...
54 | # when needed.
55 | code_lines = [f">>> {l}" if not len(l) == 0 or l.isspace() else l for l in code_lines]
56 | code = "\n".join(code_lines)
57 | code = format_code_example(code, max_len=max_len)[0]
58 | content.append(f"```python\n{code}\n```")
59 |
60 | first_output = outputs[0]
61 | if "text" in first_output:
62 | output = first_output["text"]
63 | output = f"\n{output.strip()}\n "
64 | elif "text/plain" in first_output:
65 | output = first_output["text/plain"]
66 | output = f"\n{output.strip()}\n "
67 | elif "data" in first_output and "image/png" in first_output["data"]:
68 | jpeg_base64 = png_to_jpeg(first_output["data"]["image/png"])
69 | output = f' \n'
70 | elif "data" in first_output and "image/jpeg" in first_output["data"]:
71 | output = f' \n'
72 |
73 | content.append(output)
74 | else:
75 | code = format_code_example(code, max_len=max_len)[0]
76 | content.append(f"```python\n{code}\n```")
77 | elif cell["cell_type"] == "markdown":
78 | content.append(cell["source"])
79 | else:
80 | content.append(f"```\n{cell['source']}\n```")
81 |
82 | mdx_content = "\n\n".join(content)
83 | return mdx_content
84 |
85 |
86 | def notebook_to_mdx_command(args):
87 | src_path = Path(args.notebook_src).resolve()
88 | src_dir = src_path.parent if src_path.is_file() else src_path
89 | notebook_paths = [src_path] if src_path.is_file() else [*src_dir.glob("**/*.ipynb")]
90 |
91 | for notebook_path in tqdm(notebook_paths, desc="Converting .ipynb files to .md files"):
92 | notebook = nbformat.read(notebook_path, as_version=4)
93 | mdx_content = notebook_to_mdx(notebook, args.max_len)
94 | mdx_file_name = notebook_path.name[: -len(".ipynb")] + ".md"
95 | output_dir = notebook_path.parent if args.output_dir is None else Path(args.output_dir).resolve()
96 | dest_file_path = output_dir / mdx_file_name
97 |
98 | if src_path.is_dir() and args.open_notebook_prefix is not None:
99 | relative_path = notebook_path.relative_to(src_path)
100 | colab_link = f"{args.open_notebook_prefix}/{str(relative_path)}"
101 | colab_link_component = f' '
102 | mdx_content = f"{colab_link_component}\n\n" + mdx_content
103 |
104 | with open(dest_file_path, "w", encoding="utf-8") as f:
105 | f.write(mdx_content)
106 |
107 |
108 | def notebook_to_mdx_command_parser(subparsers=None):
109 | if subparsers is not None:
110 | parser = subparsers.add_parser("notebook-to-mdx")
111 | else:
112 | parser = argparse.ArgumentParser("Doc Builder convert notebook to MD command")
113 |
114 | parser.add_argument("notebook_src", type=str, help="The notebook or directory containing notebook(s) to convert.")
115 | parser.add_argument(
116 | "--output_dir",
117 | type=str,
118 | help="Where the markdown files will be. Defaults to notebook source dir.",
119 | default=None,
120 | )
121 | parser.add_argument(
122 | "--max_len",
123 | type=int,
124 | default=119,
125 | help="The number of maximum characters per line.",
126 | )
127 | parser.add_argument(
128 | "--open_notebook_prefix",
129 | type=str,
130 | default=None,
131 | help="Example: https://colab.research.google.com/github/{user}/{repo}/blob/{branch}",
132 | )
133 |
134 | if subparsers is not None:
135 | parser.set_defaults(func=notebook_to_mdx_command)
136 | return parser
137 |
--------------------------------------------------------------------------------
/src/doc_builder/commands/style.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | # Copyright 2021 The HuggingFace Team. All rights reserved.
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 |
16 |
17 | import argparse
18 |
19 | from doc_builder import style_doc_files
20 | from doc_builder.utils import read_doc_config
21 |
22 |
23 | def style_command(args):
24 | if args.path_to_docs is not None:
25 | read_doc_config(args.path_to_docs)
26 | changed = style_doc_files(*args.files, max_len=args.max_len, check_only=args.check_only)
27 | if args.check_only and len(changed) > 0:
28 | raise ValueError(f"{len(changed)} files should be restyled!")
29 | elif len(changed) > 0:
30 | print(f"Cleaned {len(changed)} files!")
31 |
32 |
33 | def style_command_parser(subparsers=None):
34 | if subparsers is not None:
35 | parser = subparsers.add_parser("style")
36 | else:
37 | parser = argparse.ArgumentParser("Doc Builder style command")
38 |
39 | parser.add_argument("files", nargs="+", help="The file(s) or folder(s) to restyle.")
40 | parser.add_argument("--path_to_docs", type=str, help="The path to the doc source folder if using the config.")
41 | parser.add_argument("--max_len", type=int, default=119, help="The maximum length of lines.")
42 | parser.add_argument("--check_only", action="store_true", help="Whether to only check and not fix styling issues.")
43 |
44 | if subparsers is not None:
45 | parser.set_defaults(func=style_command)
46 | return parser
47 |
--------------------------------------------------------------------------------
/src/doc_builder/external.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | # Copyright 2022 The HuggingFace Team. All rights reserved.
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 |
16 | import os
17 | import re
18 | import tempfile
19 | import zlib
20 |
21 | import git
22 | import requests
23 |
24 |
25 | HF_DOC_PREFIX = "https://huggingface.co/docs/"
26 | EXTERNAL_DOC_OBJECTS_CACHE = {}
27 | HUGGINFACE_LIBS = [
28 | "accelerate",
29 | "datasets",
30 | "evaluate",
31 | "huggingface_hub",
32 | "optimum",
33 | "tokenizers",
34 | "transformers",
35 | "trl",
36 | ]
37 |
38 |
39 | def post_process_objects_inv(object_data, doc_url):
40 | """
41 | Post-processes the data in sphinx-like format to get a dictionary object_name: link in doc.
42 |
43 | Args:
44 | object_data (`str`): The data in the `objects.inv` object (except the first 4 lines).
45 | doc_url (`str`): The documentation url of the package.
46 | """
47 | links = {}
48 | for line in object_data:
49 | if len(line) == 0:
50 | continue
51 | name, typ, _, link = line.split(" ")[:4]
52 | if typ in ["py:class", "py:function", "py:method"]:
53 | link = link.replace("$", name)
54 | links[name] = f"{doc_url}/{link}"
55 | return links
56 |
57 |
58 | def get_stable_version(package_name, repo_owner="huggingface", repo_name=None):
59 | """
60 | Gets the version of the last release of a package.
61 |
62 | Args:
63 | package_name (`str`): The name of the package.
64 | repo_owner (`str`): The owner of the GitHub repo.
65 | repo_name (`str`, *optional*, defaults to `package_name`):
66 | The name of the GitHub repo. If not provided, will be the same as the package name.
67 | """
68 | repo_name = repo_name if repo_name is not None else package_name
69 | github_url = f"https://github.com/{repo_owner}/{repo_name}"
70 | try:
71 | # Get the version tags from the GitHub repo in decreasing order (that's what '-v:refname' means)
72 | result = git.cmd.Git().ls_remote(github_url, sort="-v:refname", tags=True)
73 | except git.GitCommandError:
74 | return "main"
75 |
76 | # One line per tag
77 | for line in result.split("\n"):
78 | # Lines returned are {sha}\trefs/tags/{tag}^{}, we grab the tag
79 | candidate = line.split("/")[-1].replace("^", "").replace("{}", "")
80 | # Some tags are not versions (looking at your VERSION and delete tags Datasets)
81 | if re.search(r"v?\d+\.\d+\.\d+", candidate):
82 | # Add the v is missing (looking at you Datasets :-p)
83 | return candidate if candidate.startswith("v") else f"v{candidate}"
84 |
85 | return "main"
86 |
87 |
88 | def get_objects_map(package_name, version="main", language="en", repo_owner="huggingface", repo_name=None):
89 | """
90 | Downloads the `objects.inv` for a package and post-processes it to get a nice dictionary.
91 |
92 | Args:
93 | package_name (`str`): The name of the external package.
94 | version (`str`, *optional*, defaults to `"main"`): The version of the package for which documentation is built.
95 | language (`str`, *optional*, defaults to `"en"`): The language of the documentation being built.
96 | repo_owner (`str`, *optional*, defaults to `"huggingface"`): The owner of the GitHub repo.
97 | repo_name (`str`, *optional*, defaults to `package_name`):
98 | The name of the GitHub repo. If not provided, it will be the same as the package name.
99 | """
100 | repo_name = repo_name if repo_name is not None else package_name
101 | # We link to main in `package_name` from the main doc (or PR docs) but to the last stable release otherwise.
102 | if version in ["main", "master"] or version.startswith("pr_"):
103 | package_version = "main"
104 | else:
105 | package_version = get_stable_version(package_name, repo_owner, repo_name)
106 |
107 | doc_url = f"{HF_DOC_PREFIX}{package_name}/{package_version}/{language}"
108 | url = f"{doc_url}/objects.inv"
109 | try:
110 | request = requests.get(url, stream=True)
111 | request.raise_for_status()
112 | with tempfile.TemporaryDirectory() as tmp_dir:
113 | tmp_file = os.path.join(tmp_dir, "objects.inv")
114 | with open(tmp_file, "ab") as writer:
115 | for chunk in request.iter_content(chunk_size=1024):
116 | if chunk: # filter out keep-alive new chunks
117 | writer.write(chunk)
118 |
119 | with open(tmp_file, "rb") as reader:
120 | object_lines = reader.readlines()[4:]
121 | object_data = zlib.decompress(b"".join(object_lines)).decode().split("\n")
122 | return post_process_objects_inv(object_data, doc_url)
123 | except Exception:
124 | return {}
125 |
126 |
127 | def get_external_object_link(object_name, page_info):
128 | if object_name.startswith("~"):
129 | object_name = object_name[1:]
130 | link_name = object_name.split(".")[-1]
131 | else:
132 | link_name = object_name
133 |
134 | version = page_info.get("version", "main")
135 | language = page_info.get("language", "en")
136 | if language != "en":
137 | # No resolving for other languages then English as we don't translate API doc pages/docstrings for now.
138 | return f"`{link_name}`"
139 |
140 | package_name = object_name.split(".")[0]
141 | if package_name not in HUGGINFACE_LIBS:
142 | # No resolving for non-HF libs for now.
143 | return f"`{link_name}`"
144 |
145 | if package_name not in EXTERNAL_DOC_OBJECTS_CACHE:
146 | EXTERNAL_DOC_OBJECTS_CACHE[package_name] = get_objects_map(package_name, version=version, language=language)
147 | object_url = EXTERNAL_DOC_OBJECTS_CACHE[package_name].get(object_name, None)
148 |
149 | if object_url is None:
150 | # Object not found in the lib
151 | return f"`{link_name}`"
152 | else:
153 | return f"[{link_name}]({object_url})"
154 |
--------------------------------------------------------------------------------
/tests/data/convert_include_dummy.txt:
--------------------------------------------------------------------------------
1 |
2 | # This is the first header
3 | Other text 1
4 |
5 |
6 |
7 | # This is the second header
8 | Other text 2
9 |
10 |
11 |
12 | # This is the third header
13 | Other text 3
14 |
--------------------------------------------------------------------------------
/tests/data/convert_literalinclude_dummy.txt:
--------------------------------------------------------------------------------
1 | # START python_import_answer
2 | import scipy as sp
3 | # END python_import_answer
4 |
5 | # START python_import
6 | import numpy as np
7 | import pandas as pd
8 | # END python_import
9 |
10 | # START node_import
11 | import fs
12 | # END node_import"""
--------------------------------------------------------------------------------
/tests/test_build_doc.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | # Copyright 2021 The HuggingFace Team. All rights reserved.
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 |
16 | import unittest
17 |
18 | from doc_builder.build_doc import _re_autodoc, _re_list_item, resolve_open_in_colab
19 |
20 |
21 | class BuildDocTester(unittest.TestCase):
22 | def test_re_autodoc(self):
23 | self.assertEqual(
24 | _re_autodoc.search("[[autodoc]] transformers.FlaxBertForQuestionAnswering").groups(),
25 | ("transformers.FlaxBertForQuestionAnswering",),
26 | )
27 |
28 | def test_re_list_item(self):
29 | self.assertEqual(_re_list_item.search(" - forward").groups(), ("forward",))
30 |
31 | def test_resolve_open_in_colab(self):
32 | expected = """
33 |
43 | """
44 | self.assertEqual(
45 | resolve_open_in_colab("\n[[open-in-colab]]\n", {"package_name": "transformers", "page": "quicktour.html"}),
46 | expected,
47 | )
48 |
--------------------------------------------------------------------------------
/tests/test_convert_doc_file.py:
--------------------------------------------------------------------------------
1 | # Licensed under the Apache License, Version 2.0 (the "License");
2 | # you may not use this file except in compliance with the License.
3 | # You may obtain a copy of the License at
4 | #
5 | # http://www.apache.org/licenses/LICENSE-2.0
6 | #
7 | # Unless required by applicable law or agreed to in writing, software
8 | # distributed under the License is distributed on an "AS IS" BASIS,
9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | # See the License for the specific language governing permissions and
11 | # limitations under the License.
12 |
13 | import unittest
14 |
15 | from doc_builder.commands.convert_doc_file import shorten_internal_refs
16 |
17 |
18 | class ConvertDocFileTester(unittest.TestCase):
19 | def test_shorten_internal_refs(self):
20 | self.assertEqual(shorten_internal_refs("Checkout the [`~transformers.Trainer`]."), "Checkout the [`Trainer`].")
21 | self.assertEqual(
22 | shorten_internal_refs("Look at the [`~transformers.PreTrainedModel.generate`] method."),
23 | "Look at the [`~PreTrainedModel.generate`] method.",
24 | )
25 |
--------------------------------------------------------------------------------
/tests/test_utils.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | # Copyright 2021 The HuggingFace Team. All rights reserved.
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 |
16 |
17 | import tempfile
18 | import unittest
19 | from pathlib import Path
20 |
21 | import yaml
22 | from doc_builder.utils import sveltify_file_route, update_versions_file
23 |
24 |
25 | class UtilsTester(unittest.TestCase):
26 | def test_update_versions_file(self):
27 | repo_folder = Path(__file__).parent.parent
28 | # test canonical
29 | with tempfile.TemporaryDirectory() as tmp_dir:
30 | with open(f"{tmp_dir}/_versions.yml", "w") as tmp_yml:
31 | versions = [{"version": "main"}, {"version": "v4.2.3"}, {"version": "v4.2.1"}]
32 | yaml.dump(versions, tmp_yml)
33 | update_versions_file(tmp_dir, "v4.2.2", repo_folder)
34 | with open(f"{tmp_dir}/_versions.yml", "r") as tmp_yml:
35 | yml_str = tmp_yml.read()
36 | expected_yml = "- version: main\n- version: v4.2.3\n- version: v4.2.2\n- version: v4.2.1\n"
37 | self.assertEqual(yml_str, expected_yml)
38 |
39 | # test yml with main version only
40 | with tempfile.TemporaryDirectory() as tmp_dir:
41 | with open(f"{tmp_dir}/_versions.yml", "w") as tmp_yml:
42 | versions = [{"version": "main"}]
43 | yaml.dump(versions, tmp_yml)
44 | update_versions_file(tmp_dir, "v4.2.2", repo_folder)
45 | with open(f"{tmp_dir}/_versions.yml", "r") as tmp_yml:
46 | yml_str = tmp_yml.read()
47 | expected_yml = "- version: main\n- version: v4.2.2\n"
48 | self.assertEqual(yml_str, expected_yml)
49 |
50 | # test yml without main version
51 | with tempfile.TemporaryDirectory() as tmp_dir:
52 | with open(f"{tmp_dir}/_versions.yml", "w") as tmp_yml:
53 | versions = [{"version": "v4.2.2"}]
54 | yaml.dump(versions, tmp_yml)
55 |
56 | self.assertRaises(ValueError, update_versions_file, tmp_dir, "v4.2.2", repo_folder)
57 |
58 | # test inserting duplicate version into yml
59 | with tempfile.TemporaryDirectory() as tmp_dir:
60 | with open(f"{tmp_dir}/_versions.yml", "w") as tmp_yml:
61 | versions = [{"version": "main"}]
62 | yaml.dump(versions, tmp_yml)
63 | update_versions_file(tmp_dir, "v4.2.2", repo_folder)
64 | update_versions_file(tmp_dir, "v4.2.2", repo_folder) # inserting duplicate version
65 | with open(f"{tmp_dir}/_versions.yml", "r") as tmp_yml:
66 | yml_str = tmp_yml.read()
67 | expected_yml = "- version: main\n- version: v4.2.2\n"
68 | self.assertEqual(yml_str, expected_yml)
69 |
70 | def test_sveltify_file_route(self):
71 | mdx_file_path = "guide.mdx"
72 | svelte_file_path = sveltify_file_route(mdx_file_path)
73 | expected_path = "guide/+page.svelte"
74 | self.assertEqual(svelte_file_path, expected_path)
75 |
76 | mdx_file_path = "xyz/abc/guide.mdx"
77 | svelte_file_path = sveltify_file_route(mdx_file_path)
78 | expected_path = "xyz/abc/guide/+page.svelte"
79 | self.assertEqual(svelte_file_path, expected_path)
80 |
81 | mdx_file_path = "/xyz/abc/guide.mdx"
82 | svelte_file_path = sveltify_file_route(mdx_file_path)
83 | expected_path = "/xyz/abc/guide/+page.svelte"
84 | self.assertEqual(svelte_file_path, expected_path)
85 |
--------------------------------------------------------------------------------