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

[Stable11.2] cherry pick backwards compatiblity for github tutorial paths (#10286) #10287

Open
wants to merge 1 commit into
base: stable11.2
Choose a base branch
from
Open
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
35 changes: 33 additions & 2 deletions pxtlib/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,9 @@ namespace pxt.github {
})
}

async loadTutorialMarkdown(repoPath: string, tag?: string) {
const tutorialResponse = (await downloadMarkdownTutorialInfoAsync(repoPath, tag)).resp;
async loadTutorialMarkdown(repopath: string, tag?: string) {
repopath = normalizeTutorialPath(repopath);
const tutorialResponse = (await downloadMarkdownTutorialInfoAsync(repopath, tag)).resp;

const repo = tutorialResponse.markdown as { filename: string, repo: GHTutorialRepoInfo };

Expand Down Expand Up @@ -1441,4 +1442,34 @@ namespace pxt.github {
status: null
}))
}

export function normalizeTutorialPath(repopath: string) {
// repopath will be one of these three formats:
// 1. owner/repo/path/to/file
// 2. github:owner/repo/path/to/file
// 3. https://github.com/owner/repo/path/to/file
//
// That third format is not a valid URL (a proper github URL will have /blob/branchname/
// in it after the repo) but we used to support it so maintain backwards compatibility
if (/^github\:/i.test(repopath)) {
repopath = repopath.slice(7)
}
if (/^https?\:/i.test(repopath)) {
const parsed = new URL(repopath);

// remove the leading slash
repopath = parsed.pathname.slice(1);

// check if this is an actual link to a file in github, for example:
// Mojang/EducationContent/blob/master/computing/unit-2/lesson-1.md
//
// Note the "/blob/master/" which is not present in example 3 above
const fullURLMatch = /^((?:[^\/]+\/){2})blob\/[^\/]+\/(.*)\.md$/.exec(repopath)
if (fullURLMatch) {
repopath = fullURLMatch[1] + fullURLMatch[2];
}
}

return repopath;
}
}
27 changes: 27 additions & 0 deletions tests/pxt-editor-test/editorrunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,33 @@ describe("updateHistory", () => {
});
});


describe("pxt.github.normalizeTutorialPath", () => {
const testPath = "Mojang/EducationContent/computing/unit-2/lesson-1";

it("should parse repos of the format owner/repo/path/to/file", () => {
chai.expect(pxt.github.normalizeTutorialPath(testPath)).equals(testPath);
});

it("should parse repos of the format github:owner/repo/path/to/file", () => {
const path = "github:" + testPath;
chai.expect(pxt.github.normalizeTutorialPath(path)).equals(testPath);
});

it("should parse repos of the format https://github.com/owner/repo/path/to/file", () => {
const path = "https://github.com/" + testPath;
chai.expect(pxt.github.normalizeTutorialPath(path)).equals(testPath);

const path2 = "http://github.com/" + testPath;
chai.expect(pxt.github.normalizeTutorialPath(path2)).equals(testPath);
});

it("should parse actual links to markdown files in github", () => {
const url = "https://github.com/Mojang/EducationContent/blob/master/computing/unit-2/lesson-1.md";
chai.expect(pxt.github.normalizeTutorialPath(url)).equals(testPath);
});
});

function createProjectText(): pxt.workspace.ScriptText {
// A realistic timeline of project edits
const dates = [
Expand Down
5 changes: 2 additions & 3 deletions webapp/src/idbworkspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -537,9 +537,8 @@ export function initGitHubDb() {
}

async loadTutorialMarkdown(repopath: string, tag?: string) {
if (repopath.indexOf(":") !== -1) {
repopath = repopath.split(":").pop();
}
repopath = pxt.github.normalizeTutorialPath(repopath);

const cache = await getGitHubCacheAsync();

const id = this.tutorialCacheKey(repopath, tag);
Expand Down