Skip to content

Commit 4836bea

Browse files
Merge commit '129c8880218d4992182f98cc69f4534a5a934ff2' into update-rustfmt
2 parents e243be6 + 129c888 commit 4836bea

File tree

1 file changed

+166
-47
lines changed

1 file changed

+166
-47
lines changed

docs/index.html

Lines changed: 166 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
<head>
44
<meta name="viewport" content="width=device-width">
55
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/3.0.1/github-markdown.css" />
6+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.0/styles/github-gist.min.css">
67
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
78
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
9+
<script src="https://unpkg.com/vue-async-computed@3.8.1"></script>
10+
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.0/highlight.min.js"></script>
811
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>
912
<style>
1013
@media (max-width: 767px) {
@@ -38,6 +41,15 @@
3841
.searchCondition > div {
3942
margin-right: 30px;
4043
}
44+
.header-link {
45+
position: relative;
46+
}
47+
.header-link:hover::before {
48+
position: absolute;
49+
left: -2em;
50+
padding-right: 0.5em;
51+
content: '\2002\00a7\2002';
52+
}
4153
</style>
4254
</head>
4355
<body>
@@ -59,70 +71,170 @@
5971
<label for="stable">stable: </label>
6072
<input type="checkbox" id="stable" v-model="shouldStable">
6173
</div>
74+
<div>
75+
<label for="version">version: </label>
76+
<select name="version" id="version" v-model="version">
77+
<option v-for="option in versionOptions" v-bind:value="option">
78+
{{ option }}
79+
</option>
80+
</select>
81+
</div>
6282
</div>
6383
<div v-html="aboutHtml"></div>
6484
<div v-html="configurationAboutHtml"></div>
6585
<div v-html="outputHtml"></div>
6686
</article>
6787
</div>
6888
<script>
69-
const ConfigurationMdUrl = 'https://raw.githubusercontent.com/rust-lang/rustfmt/master/Configurations.md';
89+
const RusfmtTagsUrl = 'https://api.github.com/repos/rust-lang/rustfmt/tags';
90+
const RustfmtLatestUrl = 'https://api.github.com/repos/rust-lang/rustfmt/releases/latest';
7091
const UrlHash = window.location.hash.replace(/^#/, '');
92+
const queryParams = new URLSearchParams(window.location.search);
93+
const searchParam = queryParams.get('search');
94+
const searchTerm = null !== searchParam ? searchParam : '';
95+
const versionParam = queryParams.get('version');
96+
const parseVersionParam = (version) => {
97+
if (version === 'master') return 'master';
98+
if (version.startsWith('v')) return version;
99+
return `v${version}`;
100+
};
101+
const versionNumber = null !== versionParam ? parseVersionParam(versionParam) : 'master';
71102
new Vue({
72103
el: '#app',
73-
data() {
74-
const configurationDescriptions = [];
75-
configurationDescriptions.links = {};
76-
return {
77-
aboutHtml: '',
78-
configurationAboutHtml: '',
79-
searchCondition: UrlHash,
80-
configurationDescriptions,
81-
shouldStable: false
82-
}
104+
data: {
105+
aboutHtml: '',
106+
configurationAboutHtml: '',
107+
configurationDescriptions: [],
108+
searchCondition: searchTerm,
109+
shouldStable: false,
110+
version: versionNumber,
111+
oldVersion: undefined,
112+
versionOptions: ['master'],
113+
scrolledOnce: false,
83114
},
84-
computed: {
85-
outputHtml() {
115+
asyncComputed: {
116+
async updateVersion() {
117+
let latest;
118+
try {
119+
latest = (await axios.get(RustfmtLatestUrl)).data;
120+
} catch(err) {
121+
console.log(err);
122+
return;
123+
}
124+
if (versionParam == null) {
125+
this.version = latest.name;
126+
}
127+
},
128+
async outputHtml() {
129+
if (this.version !== this.oldVersion) {
130+
const ConfigurationMdUrl =
131+
`https://raw.githubusercontent.com/rust-lang/rustfmt/${this.version}/Configurations.md`;
132+
let res;
133+
try {
134+
res = await axios.get(ConfigurationMdUrl).catch(e => { throw e });
135+
} catch(e) {
136+
this.handleReqFailure(e);
137+
return;
138+
}
139+
const {
140+
about,
141+
configurationAbout,
142+
configurationDescriptions
143+
} = parseMarkdownAst(res.data);
144+
this.aboutHtml = marked.parser(about);
145+
this.configurationAboutHtml = marked.parser(configurationAbout);
146+
this.configurationDescriptions = configurationDescriptions;
147+
this.oldVersion = this.version;
148+
}
149+
86150
const ast = this.configurationDescriptions
87-
.filter(({ head, text, stable }) => {
88-
89-
if (
90-
text.includes(this.searchCondition) === false &&
91-
head.includes(this.searchCondition) === false
92-
) {
93-
return false;
94-
}
95-
return (this.shouldStable)
96-
? stable === true
97-
: true;
98-
})
99-
.reduce((stack, { value }) => {
100-
return stack.concat(value);
101-
}, []);
151+
.filter(({ head, text, stable }) => {
152+
if (text.includes(this.searchCondition) === false &&
153+
head.includes(this.searchCondition) === false) {
154+
return false;
155+
}
156+
return (this.shouldStable)
157+
? stable === true
158+
: true;
159+
})
160+
.reduce((stack, { value }) => {
161+
return stack.concat(value);
162+
}, []);
102163
ast.links = {};
103-
return marked.parser(ast);
164+
165+
queryParams.set('version', this.version);
166+
queryParams.set('search', this.searchCondition);
167+
const curUrl = window.location.pathname +
168+
'?' + queryParams.toString() + window.location.hash;
169+
history.pushState(null, '', curUrl);
170+
171+
const renderer = new marked.Renderer();
172+
renderer.heading = function(text, level) {
173+
const id = htmlToId(text);
174+
return `<h${level}>
175+
<a id="${id}" href="#${id}" name="${id}" class="header-link">${text}</a>
176+
</h${level}>`;
177+
};
178+
179+
return marked.parser(ast, {
180+
highlight(code, lang) {
181+
return hljs.highlight(lang ? lang : 'rust', code).value;
182+
},
183+
headerIds: true,
184+
headerPrefix: '',
185+
renderer,
186+
});
104187
}
105188
},
106189
created: async function() {
107-
const res = await axios.get(ConfigurationMdUrl);
108-
const {
109-
about,
110-
configurationAbout,
111-
configurationDescriptions
112-
} = parseMarkdownAst(res.data);
113-
this.aboutHtml = marked.parser(about);
114-
this.configurationAboutHtml = marked.parser(configurationAbout);
115-
this.configurationDescriptions = configurationDescriptions;
190+
let tags;
191+
try {
192+
tags = (await axios.get(RusfmtTagsUrl)).data;
193+
} catch(e) {
194+
this.handleReqFailure(e);
195+
return;
196+
}
197+
198+
const excludedTagVersions = new Set(['v0.7', 'v0.8.1']);
199+
200+
const tagOptions = tags
201+
.map(tag => tag.name)
202+
.filter(tag => tag.startsWith('v') && !excludedTagVersions.has(tag));
203+
this.versionOptions = this.versionOptions.concat(tagOptions);
116204
},
117-
mounted() {
205+
updated() {
118206
if (UrlHash === '') return;
119-
const interval = setInterval(() => {
207+
this.$nextTick(() => {
120208
const target = document.querySelector(`#${UrlHash}`);
121-
if (target != null) {
209+
if (target != null && !this.scrolledOnce) {
122210
target.scrollIntoView(true);
123-
clearInterval(interval);
211+
this.scrolledOnce = true;
212+
}
213+
});
214+
},
215+
methods: {
216+
handleReqFailure(e) {
217+
if (e.response.status === 404) {
218+
this.aboutHtml =
219+
"<p>Failed to get configuration options for this version, please select the version from the dropdown above.</p>";
220+
} else if (
221+
e.response.status === 403 &&
222+
e.response.headers["X-RateLimit-Remaining"] === 0
223+
) {
224+
const resetDate = new Date(
225+
e.response.headers['X-RateLimit-Reset'] * 1000
226+
).toLocaleString();
227+
this.aboutHtml =
228+
`<p>You have hit the GitHub API rate limit; documentation cannot be updated.` +
229+
`<p>The rate limit will be reset at ${resetDate}.</p>`;
230+
} else {
231+
this.aboutHtml =
232+
`<p>Ecountered an error when fetching documentation data:</p>` +
233+
`<pre><code>${e.response.data}</code></pre>` +
234+
`<p>We would appreciate <a href="https://github.com/rust-lang/rustfmt/issues/new?template=bug_report.md">a bug report</a>.` +
235+
`<p>Try refreshing the page.</p>`;
124236
}
125-
}, 100);
237+
}
126238
}
127239
});
128240
const extractDepthOnes = (ast) => {
@@ -144,7 +256,7 @@
144256
const lastIndex = stack.length - 1;
145257
stack[lastIndex].push(next);
146258
return stack;
147-
},
259+
},
148260
[[]]);
149261
});
150262
}
@@ -155,7 +267,9 @@
155267
head: val[0].text,
156268
value: val,
157269
stable: val.some((elem) => {
158-
return !!elem.text && elem.text.includes("**Stable**: Yes")
270+
return elem.type === "list" &&
271+
!!elem.raw &&
272+
elem.raw.includes("**Stable**: Yes");
159273
}),
160274
text: val.reduce((result, next) => {
161275
return next.text != null
@@ -179,13 +293,18 @@
179293
configurationAbout, ...configurationDescriptions
180294
] = configurations;
181295
configurationAbout.value.links = {};
182-
296+
183297
return {
184298
about,
185299
configurationAbout: configurationAbout.value,
186300
configurationDescriptions
187301
};
188302
}
303+
function htmlToId(text) {
304+
const tmpl = document.createElement('template');
305+
tmpl.innerHTML = text.trim();
306+
return encodeURIComponent(CSS.escape(tmpl.content.textContent));
307+
}
189308
</script>
190309
</body>
191-
</html>
310+
</html>

0 commit comments

Comments
 (0)