Skip to content

Use mode: history on the vue-router by using a SPA hack for Github Pages #393

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

Closed
wants to merge 1 commit into from
Closed
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
8 changes: 4 additions & 4 deletions DEVELOPING_TUTORIALS.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ If proofing a PR for someone else, check out their branch (you'll see its name l
> npm run serve
```

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

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.

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

```
![Description of the image](tutorial-assets/T0001L01-diagram.svg)
![Description of the image](/tutorial-assets/T0001L01-diagram.svg)
```

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

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

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

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

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.
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.

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

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Clone the repo, install dependencies, check out the appropriate branch, and run
> npm run serve
```

View the site on localhost at: http://localhost:3000/#/
View the site on localhost at: http://localhost:3000/

## License

Expand Down
10 changes: 5 additions & 5 deletions cypress/integration/tutorials.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ function viewSolutionsAndSubmitAll (tutorialId) {
const lessonCount = tutorials[tutorialId].lessons.length // count excludes resources page
// const hasResources = tutorials[tutorialId].hasOwnProperty('resources')
it(`should find the ${tutorialName} tutorial`, function () {
cy.visit(`/#/${tutorialName}/`)
cy.get(`[href="#/${tutorialName}/01"]`).click()
cy.visit(`/${tutorialName}/`)
cy.get(`[href="/${tutorialName}/01"]`).click()
})
// loop through standard lessons and attempt to pass challenges
for (let i = 1; i <= lessonCount; i++) {
let lessonNr = i.toString().padStart(2, 0)
it(`should view the solution and pass test ${lessonNr}`, function () {
cy.url().should('include', `#/${tutorialName}/${lessonNr}`)
cy.url().should('include', `/${tutorialName}/${lessonNr}`)
cy.get('[data-cy=code-editor-ready]').should('be.visible') // wait for editor to be updated
cy.get('[data-cy=view-solution]').click()
cy.get('[data-cy=solution-editor-ready]').should('be.visible') // wait for editor to be updated
Expand All @@ -49,7 +49,7 @@ function viewSolutionsAndSubmitAll (tutorialId) {
cy.contains('h1', 'Resources') // loads resources page
cy.get('[data-cy=resources-content]') // loads meaningful content
cy.get('[data-cy=more-tutorials]').click()
cy.url().should('include', `#/tutorials/`)
cy.url().should('include', `/tutorials/`)
})
}

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

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

Expand Down
10 changes: 9 additions & 1 deletion cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,12 @@
//
//
// -- This is will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
Cypress.Commands.overwrite('visit', (originalFn, url, options) => {
originalFn(url, { ...options, failOnStatusCode: false })
})

Cypress.on('uncaught:exception', (error, runnable) => {
console.error(error)

return false
})
3 changes: 0 additions & 3 deletions cypress/support/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,3 @@

// Import commands.js using ES2015 syntax:
import './commands'

// Alternatively you can use CommonJS syntax:
// require('./commands')
42 changes: 42 additions & 0 deletions public/404.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8" />

<title>ProtoSchool</title>

<script type="text/javascript">
// Single Page Apps for GitHub Pages
// https://github.com/rafrex/spa-github-pages
// Copyright (c) 2016 Rafael Pedicini, licensed under the MIT License
// ----------------------------------------------------------------------
// This script takes the current url and converts the path and query
// string into just a query string, and then redirects the browser
// to the new url with only a query string and hash fragment,
// e.g. http://www.foo.tld/one/two?a=b&c=d#qwe, becomes
// http://www.foo.tld/?p=/one/two&q=a=b~and~c=d#qwe
// Note: this 404.html file must be at least 512 bytes for it to work
// with Internet Explorer (it is currently > 512 bytes)
var segmentCount = 0;

var l = window.location;
l.replace(
l.protocol + '//' + l.hostname + (l.port ? ':' + l.port : '') +
l.pathname.split('/').slice(0, 1 + segmentCount).join('/') + '/?p=/' +
l.pathname.slice(1).split('/').slice(segmentCount).join('/').replace(/&/g, '~and~') +
(l.search ? '&q=' + l.search.slice(1).replace(/&/g, '~and~') : '') +
l.hash
);

</script>
</head>

<body>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</body>


</html>
29 changes: 29 additions & 0 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,35 @@
font-family: 'Roboto', sans-serif;
}
</style>
<script type="text/javascript">
// Single Page Apps for GitHub Pages
// https://github.com/rafrex/spa-github-pages
// Copyright (c) 2016 Rafael Pedicini, licensed under the MIT License
// ----------------------------------------------------------------------
// This script checks to see if a redirect is present in the query string
// and converts it back into the correct url and adds it to the
// browser's history using window.history.replaceState(...),
// which won't cause the browser to attempt to load the new url.
// When the single page app is loaded further down in this file,
// the correct url will be waiting in the browser's history for
// the single page app to route accordingly.
(function(l) {
if (l.search) {
var q = {};
l.search.slice(1).split('&').forEach(function(v) {
var a = v.split('=');
q[a[0]] = a.slice(1).join('=').replace(/~and~/g, '&');
});
if (q.p !== undefined) {
window.history.replaceState(null, null,
l.pathname.slice(0, -1) + (q.p || '') +
(q.q ? ('?' + q.q) : '') +
l.hash
);
}
}
}(window.location))
</script>
</head>
<body>
<noscript>
Expand Down
4 changes: 2 additions & 2 deletions src/components/CodeEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<span v-if="cachedCode" @click="resetCode" class="textLink" data-cy="reset-code">Reset Code</span>
<MonacoEditor
class="editor mt2"
srcPath="."
srcPath=""
:height="editorHeight"
:options="options"
:code="code"
Expand All @@ -29,7 +29,7 @@
<MonacoEditor
v-show="viewSolution"
class="editor"
srcPath="."
srcPath=""
:height="editorHeight"
:options="Object.assign({}, { readOnly: true }, options)"
:code="solution"
Expand Down
8 changes: 5 additions & 3 deletions src/components/Navigation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<div v-if="tutorial" class="link-list flex overflow-auto items-center bg-aqua navy f5 fw6 center tc mw7">
<router-link class="nav-link navy" to="/tutorials">Tutorials</router-link>
<span class="fw4">></span>
<router-link data-cy="tutorial-landing-link" class="nav-link navy" :to="tutorialLanding">{{tutorial.shortTitle}}</router-link>
<router-link data-cy="tutorial-landing-link" class="nav-link navy" :to="tutorialUrl">{{tutorial.shortTitle}}</router-link>
</div>
<!-- standard nav -->
<div v-else class="link-list dn flex overflow-auto items-center bg-aqua white tc mw7">
Expand All @@ -26,7 +26,7 @@
<div v-if="tutorial" class="flex-auto link fw5 f5 db bb border-aqua navy">
<router-link class="nav-link navy" to="/tutorials">Tutorials</router-link>
<span class="fw4"> > </span>
<router-link class="nav-link navy" :to="tutorialLanding">{{tutorial.shortTitle}}</router-link>
<router-link class="nav-link navy" :to="tutorialUrl">{{tutorial.shortTitle}}</router-link>
</div>
<!-- standard nav -->
<div v-else class="flex-auto link fw6 f5 db bb border-aqua">{{currentPage}}</div>
Expand Down Expand Up @@ -56,7 +56,6 @@ export default {
return {
isHamburgerClosed: true,
currentPath: self.$route.path.toString(),
tutorialLanding: '/' + self.$route.path.split('/')[1],
links: [
{ text: 'Home', path: '/' },
{ text: 'Tutorials', path: '/tutorials' },
Expand All @@ -75,6 +74,9 @@ export default {

return getTutorialByUrl(this.$route.params.tutorialUrl)
},
tutorialUrl: function () {
return `/${this.tutorial.url}`
},
currentPage: function () {
let pageName
this.links.forEach(link => {
Expand Down
3 changes: 2 additions & 1 deletion src/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ const routes = [
migrateCache()

const router = new VueRouter({
mode: 'history',
routes,
scrollBehavior (to, from) {
return { x: 0, y: 0 }
Expand All @@ -89,7 +90,7 @@ const router = new VueRouter({
// track page view via Countly when route changes
router.afterEach((to) => {
if (!window.Countly) return
window.Countly.q.push(['track_pageview', '/#' + to.path])
window.Countly.q.push(['track_pageview', '/' + to.path])
})

export default router
18 changes: 9 additions & 9 deletions src/static/tutorials.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@
},
{
"title": "IPFS: Mutable File System (MFS)",
"link": "https://proto.school/#/mutable-file-system",
"link": "https://proto.school/mutable-file-system",
"type": "tutorial",
"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.)"
},
{
"title": "P2P Data Links with Content Addressing",
"link": "https://proto.school/#/basics/",
"link": "https://proto.school/basics/",
"type": "tutorial",
"description": "Use the IPFS DAG API to create create verifiable links between dataset with Content Identifiers (CIDs). (This tutorial includes JavaScript code challenges.)"
}
Expand All @@ -76,7 +76,7 @@
},
{
"title": "Blogging on the Decentralized Web",
"link": "https://proto.school/#/blog/",
"link": "https://proto.school/blog/",
"type": "tutorial",
"description": "Ready for a bigger challenge with the IPFS DAG API? Use CIDs to build and update a complex web of data."
},
Expand All @@ -94,7 +94,7 @@
},
{
"title": "IPFS: Regular Files API",
"link": "https://proto.school/#/regular-files-api",
"link": "https://proto.school/regular-files-api",
"type": "tutorial",
"description": "Ready to deal with more than primitives? Explore the API custom-built for efficient handling of files in IPFS."
}
Expand Down Expand Up @@ -126,7 +126,7 @@
},
{
"title": "IPFS: Regular Files API",
"link": "https://proto.school/#/regular-files-api",
"link": "https://proto.school/regular-files-api",
"type": "tutorial",
"description": "Ready to deal with more than primitives? Explore the API custom-built for efficient handling of files in IPFS."
}
Expand Down Expand Up @@ -159,7 +159,7 @@
},
{
"title": "IPFS: Regular Files API",
"link": "https://proto.school/#/regular-files-api",
"link": "https://proto.school/regular-files-api",
"type": "tutorial",
"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."
},
Expand All @@ -177,7 +177,7 @@
},
{
"title": "P2P Data Links with Content Addressing",
"link": "https://proto.school/#/basics/",
"link": "https://proto.school/basics/",
"type": "tutorial",
"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."
}
Expand Down Expand Up @@ -210,13 +210,13 @@
},
{
"title": "IPFS: Mutable File System (MFS)",
"link": "https://proto.school/#/mutable-file-system",
"link": "https://proto.school/mutable-file-system",
"type": "tutorial",
"description": "Wish adding files to IPFS felt more like using a traditional name-based file system? Explore the Mutable File System (MFS)."
},
{
"title": "P2P Data Links with Content Addressing",
"link": "https://proto.school/#/basics/",
"link": "https://proto.school/basics/",
"type": "tutorial",
"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."
}
Expand Down
2 changes: 1 addition & 1 deletion src/tutorials/0001-data-structures/05.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ these data structures backwards, from the leaf nodes on up to the root node.

## Directed Acyclic Graphs (DAG)

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

DAG is an acronym for [`Directed Acyclic Graph`](https://en.wikipedia.org/wiki/Directed_acyclic_graph). It's a fancy way of describing a
specific kind of Merkle tree (hash tree) where different branches in the tree can point at other branches
Expand Down
2 changes: 1 addition & 1 deletion src/tutorials/0003-blog/01.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
type: "code"
---

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

```javascript
{
Expand Down
2 changes: 1 addition & 1 deletion src/tutorials/0004-mutable-file-system/01.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

[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.

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.
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.

## Storing and sharing data in IPFS

Expand Down
2 changes: 1 addition & 1 deletion src/tutorials/0004-mutable-file-system/06.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
type: "file-upload"
---

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.
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.

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:

Expand Down
Loading