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

DEVELOPING_TUTORIALS.md

Lines changed: 4 additions & 4 deletions
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

README.md

Lines changed: 1 addition & 1 deletion
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

cypress/integration/tutorials.spec.js

Lines changed: 5 additions & 5 deletions
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

cypress/support/commands.js

Lines changed: 9 additions & 1 deletion
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+
})

cypress/support/index.js

Lines changed: 0 additions & 3 deletions
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')

public/404.html

Lines changed: 42 additions & 0 deletions
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>

public/index.html

Lines changed: 29 additions & 0 deletions
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>

src/components/CodeEditor.vue

Lines changed: 2 additions & 2 deletions
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"

src/components/Navigation.vue

Lines changed: 5 additions & 3 deletions
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 => {

src/router.js

Lines changed: 2 additions & 1 deletion
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

0 commit comments

Comments
 (0)