Skip to content

Commit 90bd5d0

Browse files
committed
fix: use mode: history on the vue-router by using a SPA hack for GH Pages
1 parent 21ba5b4 commit 90bd5d0

File tree

22 files changed

+122
-43
lines changed

22 files changed

+122
-43
lines changed

Diff for: DEVELOPING_TUTORIALS.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ If proofing a PR for someone else, check out their branch (you'll see its name l
9292
> npm run serve
9393
```
9494

95-
6. Open a web browser to the following address to preview your work: http://localhost:3000/#/
95+
6. Open a web browser to the following address to preview your work: http://localhost:3000/
9696

9797
Vue will update your localhost preview automatically as you make changes. However, you won't be able to see any newly added lessons until you've updated the appropriate routes and import statements, as described below.
9898

@@ -170,13 +170,13 @@ If you want to add images to your Markdown file, place them in the `public/tutor
170170
Then in your lesson Markdown file, you can either add it with regular Markdown:
171171

172172
```
173-
![Description of the image](tutorial-assets/T0001L01-diagram.svg)
173+
![Description of the image](/tutorial-assets/T0001L01-diagram.svg)
174174
```
175175

176176
...or with regular HTML, if you need to set the image size:
177177

178178
```html
179-
<img src="tutorial-assets/T0001L01-diagram.svg" width="300px" height="150px" />
179+
<img src="/tutorial-assets/T0001L01-diagram.svg" width="300px" height="150px" />
180180
```
181181

182182
##### JavaScript file (skip for text-only lessons)
@@ -503,7 +503,7 @@ The `title` of your tutorial will be seen in course listings on our tutorials pa
503503

504504
![screenshot](public/title-in-featured-tutorials.png)
505505

506-
The `url` will appear in the URL of your tutorial landing page and lessons. For example, `http://proto.school/#/short-tutorial-title/01`. In most cases this will match your tutorial title, but you may find that you need to make it shorter. Note that this URL will also be used to create the abbreviated title that is shown in the breadcrumb navigation and the small header at the top of each page of your tutorial.
506+
The `url` will appear in the URL of your tutorial landing page and lessons. For example, `http://proto.school/short-tutorial-title/01`. In most cases this will match your tutorial title, but you may find that you need to make it shorter. Note that this URL will also be used to create the abbreviated title that is shown in the breadcrumb navigation and the small header at the top of each page of your tutorial.
507507

508508
![screenshot](public/url-breadcrumb-header.png)
509509

Diff for: README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Clone the repo, install dependencies, check out the appropriate branch, and run
3838
> npm run serve
3939
```
4040

41-
View the site on localhost at: http://localhost:3000/#/
41+
View the site on localhost at: http://localhost:3000/
4242

4343
## License
4444

Diff for: cypress/integration/tutorials.spec.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@ function viewSolutionsAndSubmitAll (tutorialId) {
2929
const lessonCount = tutorials[tutorialId].lessons.length // count excludes resources page
3030
// const hasResources = tutorials[tutorialId].hasOwnProperty('resources')
3131
it(`should find the ${tutorialName} tutorial`, function () {
32-
cy.visit(`/#/${tutorialName}/`)
33-
cy.get(`[href="#/${tutorialName}/01"]`).click()
32+
cy.visit(`/${tutorialName}/`)
33+
cy.get(`[href="/${tutorialName}/01"]`).click()
3434
})
3535
// loop through standard lessons and attempt to pass challenges
3636
for (let i = 1; i <= lessonCount; i++) {
3737
let lessonNr = i.toString().padStart(2, 0)
3838
it(`should view the solution and pass test ${lessonNr}`, function () {
39-
cy.url().should('include', `#/${tutorialName}/${lessonNr}`)
39+
cy.url().should('include', `/${tutorialName}/${lessonNr}`)
4040
cy.get('[data-cy=code-editor-ready]').should('be.visible') // wait for editor to be updated
4141
cy.get('[data-cy=view-solution]').click()
4242
cy.get('[data-cy=solution-editor-ready]').should('be.visible') // wait for editor to be updated
@@ -49,7 +49,7 @@ function viewSolutionsAndSubmitAll (tutorialId) {
4949
cy.contains('h1', 'Resources') // loads resources page
5050
cy.get('[data-cy=resources-content]') // loads meaningful content
5151
cy.get('[data-cy=more-tutorials]').click()
52-
cy.url().should('include', `#/tutorials/`)
52+
cy.url().should('include', `/tutorials/`)
5353
})
5454
}
5555

@@ -59,7 +59,7 @@ function renderAllLessonsInTutorial (tutorialId) {
5959
const standardLessonCount = standardLessons.length
6060

6161
it(`should find ${tutorialName} landing page with correct lesson count`, function () {
62-
cy.visit(`/#/${tutorialName}/`)
62+
cy.visit(`/${tutorialName}/`)
6363
cy.get(`[data-cy=lesson-link]`).should('have.length', standardLessonCount)
6464
})
6565

Diff for: cypress/support/commands.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,12 @@
2222
//
2323
//
2424
// -- This is will overwrite an existing command --
25-
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
25+
Cypress.Commands.overwrite('visit', (originalFn, url, options) => {
26+
originalFn(url, { ...options, failOnStatusCode: false })
27+
})
28+
29+
Cypress.on('uncaught:exception', (error, runnable) => {
30+
console.error(error)
31+
32+
return false
33+
})

Diff for: cypress/support/index.js

-3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,3 @@
1515

1616
// Import commands.js using ES2015 syntax:
1717
import './commands'
18-
19-
// Alternatively you can use CommonJS syntax:
20-
// require('./commands')

Diff for: public/404.html

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="utf-8" />
6+
7+
<title>ProtoSchool</title>
8+
9+
<script type="text/javascript">
10+
// Single Page Apps for GitHub Pages
11+
// https://github.com/rafrex/spa-github-pages
12+
// Copyright (c) 2016 Rafael Pedicini, licensed under the MIT License
13+
// ----------------------------------------------------------------------
14+
// This script takes the current url and converts the path and query
15+
// string into just a query string, and then redirects the browser
16+
// to the new url with only a query string and hash fragment,
17+
// e.g. http://www.foo.tld/one/two?a=b&c=d#qwe, becomes
18+
// http://www.foo.tld/?p=/one/two&q=a=b~and~c=d#qwe
19+
// Note: this 404.html file must be at least 512 bytes for it to work
20+
// with Internet Explorer (it is currently > 512 bytes)
21+
var segmentCount = 0;
22+
23+
var l = window.location;
24+
l.replace(
25+
l.protocol + '//' + l.hostname + (l.port ? ':' + l.port : '') +
26+
l.pathname.split('/').slice(0, 1 + segmentCount).join('/') + '/?p=/' +
27+
l.pathname.slice(1).split('/').slice(segmentCount).join('/').replace(/&/g, '~and~') +
28+
(l.search ? '&q=' + l.search.slice(1).replace(/&/g, '~and~') : '') +
29+
l.hash
30+
);
31+
32+
</script>
33+
</head>
34+
35+
<body>
36+
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
37+
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
38+
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
39+
</body>
40+
41+
42+
</html>

Diff for: public/index.html

+29
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,35 @@
2222
font-family: 'Roboto', sans-serif;
2323
}
2424
</style>
25+
<script type="text/javascript">
26+
// Single Page Apps for GitHub Pages
27+
// https://github.com/rafrex/spa-github-pages
28+
// Copyright (c) 2016 Rafael Pedicini, licensed under the MIT License
29+
// ----------------------------------------------------------------------
30+
// This script checks to see if a redirect is present in the query string
31+
// and converts it back into the correct url and adds it to the
32+
// browser's history using window.history.replaceState(...),
33+
// which won't cause the browser to attempt to load the new url.
34+
// When the single page app is loaded further down in this file,
35+
// the correct url will be waiting in the browser's history for
36+
// the single page app to route accordingly.
37+
(function(l) {
38+
if (l.search) {
39+
var q = {};
40+
l.search.slice(1).split('&').forEach(function(v) {
41+
var a = v.split('=');
42+
q[a[0]] = a.slice(1).join('=').replace(/~and~/g, '&');
43+
});
44+
if (q.p !== undefined) {
45+
window.history.replaceState(null, null,
46+
l.pathname.slice(0, -1) + (q.p || '') +
47+
(q.q ? ('?' + q.q) : '') +
48+
l.hash
49+
);
50+
}
51+
}
52+
}(window.location))
53+
</script>
2554
</head>
2655
<body>
2756
<noscript>

Diff for: src/components/CodeEditor.vue

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<span v-if="cachedCode" @click="resetCode" class="textLink" data-cy="reset-code">Reset Code</span>
1111
<MonacoEditor
1212
class="editor mt2"
13-
srcPath="."
13+
srcPath=""
1414
:height="editorHeight"
1515
:options="options"
1616
:code="code"
@@ -29,7 +29,7 @@
2929
<MonacoEditor
3030
v-show="viewSolution"
3131
class="editor"
32-
srcPath="."
32+
srcPath=""
3333
:height="editorHeight"
3434
:options="Object.assign({}, { readOnly: true }, options)"
3535
:code="solution"

Diff for: src/components/Navigation.vue

+5-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<div v-if="tutorial" class="link-list flex overflow-auto items-center bg-aqua navy f5 fw6 center tc mw7">
77
<router-link class="nav-link navy" to="/tutorials">Tutorials</router-link>
88
<span class="fw4">></span>
9-
<router-link data-cy="tutorial-landing-link" class="nav-link navy" :to="tutorialLanding">{{tutorial.shortTitle}}</router-link>
9+
<router-link data-cy="tutorial-landing-link" class="nav-link navy" :to="tutorialUrl">{{tutorial.shortTitle}}</router-link>
1010
</div>
1111
<!-- standard nav -->
1212
<div v-else class="link-list dn flex overflow-auto items-center bg-aqua white tc mw7">
@@ -26,7 +26,7 @@
2626
<div v-if="tutorial" class="flex-auto link fw5 f5 db bb border-aqua navy">
2727
<router-link class="nav-link navy" to="/tutorials">Tutorials</router-link>
2828
<span class="fw4"> > </span>
29-
<router-link class="nav-link navy" :to="tutorialLanding">{{tutorial.shortTitle}}</router-link>
29+
<router-link class="nav-link navy" :to="tutorialUrl">{{tutorial.shortTitle}}</router-link>
3030
</div>
3131
<!-- standard nav -->
3232
<div v-else class="flex-auto link fw6 f5 db bb border-aqua">{{currentPage}}</div>
@@ -56,7 +56,6 @@ export default {
5656
return {
5757
isHamburgerClosed: true,
5858
currentPath: self.$route.path.toString(),
59-
tutorialLanding: '/' + self.$route.path.split('/')[1],
6059
links: [
6160
{ text: 'Home', path: '/' },
6261
{ text: 'Tutorials', path: '/tutorials' },
@@ -75,6 +74,9 @@ export default {
7574
7675
return getTutorialByUrl(this.$route.params.tutorialUrl)
7776
},
77+
tutorialUrl: function () {
78+
return `/${this.tutorial.url}`
79+
},
7880
currentPage: function () {
7981
let pageName
8082
this.links.forEach(link => {

Diff for: src/router.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ const routes = [
8080
migrateCache()
8181

8282
const router = new VueRouter({
83+
mode: 'history',
8384
routes,
8485
scrollBehavior (to, from) {
8586
return { x: 0, y: 0 }
@@ -89,7 +90,7 @@ const router = new VueRouter({
8990
// track page view via Countly when route changes
9091
router.afterEach((to) => {
9192
if (!window.Countly) return
92-
window.Countly.q.push(['track_pageview', '/#' + to.path])
93+
window.Countly.q.push(['track_pageview', '/' + to.path])
9394
})
9495

9596
export default router

Diff for: src/static/tutorials.json

+9-9
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,13 @@
5050
},
5151
{
5252
"title": "IPFS: Mutable File System (MFS)",
53-
"link": "https://proto.school/#/mutable-file-system",
53+
"link": "https://proto.school/mutable-file-system",
5454
"type": "tutorial",
5555
"description": "Explore the Mutable File System (MFS), which lets you work with files and directories in IPFS as if you were using a traditional name-based file system. (This tutorial includes JavaScript code challenges.)"
5656
},
5757
{
5858
"title": "P2P Data Links with Content Addressing",
59-
"link": "https://proto.school/#/basics/",
59+
"link": "https://proto.school/basics/",
6060
"type": "tutorial",
6161
"description": "Use the IPFS DAG API to create create verifiable links between dataset with Content Identifiers (CIDs). (This tutorial includes JavaScript code challenges.)"
6262
}
@@ -76,7 +76,7 @@
7676
},
7777
{
7878
"title": "Blogging on the Decentralized Web",
79-
"link": "https://proto.school/#/blog/",
79+
"link": "https://proto.school/blog/",
8080
"type": "tutorial",
8181
"description": "Ready for a bigger challenge with the IPFS DAG API? Use CIDs to build and update a complex web of data."
8282
},
@@ -94,7 +94,7 @@
9494
},
9595
{
9696
"title": "IPFS: Regular Files API",
97-
"link": "https://proto.school/#/regular-files-api",
97+
"link": "https://proto.school/regular-files-api",
9898
"type": "tutorial",
9999
"description": "Ready to deal with more than primitives? Explore the API custom-built for efficient handling of files in IPFS."
100100
}
@@ -126,7 +126,7 @@
126126
},
127127
{
128128
"title": "IPFS: Regular Files API",
129-
"link": "https://proto.school/#/regular-files-api",
129+
"link": "https://proto.school/regular-files-api",
130130
"type": "tutorial",
131131
"description": "Ready to deal with more than primitives? Explore the API custom-built for efficient handling of files in IPFS."
132132
}
@@ -159,7 +159,7 @@
159159
},
160160
{
161161
"title": "IPFS: Regular Files API",
162-
"link": "https://proto.school/#/regular-files-api",
162+
"link": "https://proto.school/regular-files-api",
163163
"type": "tutorial",
164164
"description": "Explore the other half of the IPFS Files API, where you'll add and retrieve files and read their contents without the abstraction layer of the Mutable File System."
165165
},
@@ -177,7 +177,7 @@
177177
},
178178
{
179179
"title": "P2P Data Links with Content Addressing",
180-
"link": "https://proto.school/#/basics/",
180+
"link": "https://proto.school/basics/",
181181
"type": "tutorial",
182182
"description": "You've seen the IPFS Files API. Now explore the IPFS DAG API, where you'll use CIDs to create verifiable links between datasets."
183183
}
@@ -210,13 +210,13 @@
210210
},
211211
{
212212
"title": "IPFS: Mutable File System (MFS)",
213-
"link": "https://proto.school/#/mutable-file-system",
213+
"link": "https://proto.school/mutable-file-system",
214214
"type": "tutorial",
215215
"description": "Wish adding files to IPFS felt more like using a traditional name-based file system? Explore the Mutable File System (MFS)."
216216
},
217217
{
218218
"title": "P2P Data Links with Content Addressing",
219-
"link": "https://proto.school/#/basics/",
219+
"link": "https://proto.school/basics/",
220220
"type": "tutorial",
221221
"description": "You've seen the IPFS Files API. Now explore the IPFS DAG API, where you'll use CIDs to create verifiable links between datasets."
222222
}

Diff for: src/tutorials/0001-data-structures/05.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ these data structures backwards, from the leaf nodes on up to the root node.
5454

5555
## Directed Acyclic Graphs (DAG)
5656

57-
![Directed Acycil Graphs](tutorial-assets/T0001L01-dag.svg)
57+
![Directed Acycil Graphs](/tutorial-assets/T0001L01-dag.svg)
5858

5959
DAG is an acronym for [`Directed Acyclic Graph`](https://en.wikipedia.org/wiki/Directed_acyclic_graph). It's a fancy way of describing a
6060
specific kind of Merkle tree (hash tree) where different branches in the tree can point at other branches

Diff for: src/tutorials/0003-blog/01.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
type: "code"
44
---
55

6-
In the [Basics tutorial](#/basics/02), we learned that a link in IPFS is represented as an instance of `CID`:
6+
In the [Basics tutorial](/basics/02), we learned that a link in IPFS is represented as an instance of `CID`:
77

88
```javascript
99
{

Diff for: src/tutorials/0004-mutable-file-system/01.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
[IPFS](https://ipfs.io/), or the InterPlanetary File System, is a peer-to-peer (P2P) networking protocol used to share data on the distributed web. As its full name suggests, you can think of IPFS as a file system, and it has some unique characteristics that make it ideal for safe, decentralized sharing.
99

10-
If you haven't yet done so, we encourage you to check out our [Decentralized Data Structures tutorial](https://proto.school/#/data-structures/), where you can learn all about the decentralized web and how it compares to the web you're accustomed to. There you'll learn all about content addressing, cryptographic hashing, Content Identifiers (CIDs), and sharing with peers, all of which you'll need to understand to make the most of this tutorial on IPFS.
10+
If you haven't yet done so, we encourage you to check out our [Decentralized Data Structures tutorial](https://proto.school/data-structures/), where you can learn all about the decentralized web and how it compares to the web you're accustomed to. There you'll learn all about content addressing, cryptographic hashing, Content Identifiers (CIDs), and sharing with peers, all of which you'll need to understand to make the most of this tutorial on IPFS.
1111

1212
## Storing and sharing data in IPFS
1313

Diff for: src/tutorials/0004-mutable-file-system/06.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
type: "file-upload"
44
---
55

6-
As you learned in the [Decentralized Data Structures tutorial](https://proto.school/#/data-structures), CIDs (Content Identifiers) are uniquely matched to the content they represent through cryptographic hashing. Two files with identical contents have identical CIDs (hashes) and two files with even the smallest difference between them have distinct CIDs. The same is true for directories. Every time you update the contents of a file or directory, its CID changes.
6+
As you learned in the [Decentralized Data Structures tutorial](https://proto.school/data-structures), CIDs (Content Identifiers) are uniquely matched to the content they represent through cryptographic hashing. Two files with identical contents have identical CIDs (hashes) and two files with even the smallest difference between them have distinct CIDs. The same is true for directories. Every time you update the contents of a file or directory, its CID changes.
77

88
When your root directory was empty and you checked its status using [`ipfs.files.stat`](https://github.com/ipfs/interface-js-ipfs-core/blob/master/SPEC/FILES.md#filesstat), you saw this result:
99

0 commit comments

Comments
 (0)