]> git.lizzy.rs Git - rust.git/blob - src/tools/rustfmt/docs/index.html
Rollup merge of #90202 - matthewjasper:xcrate-hygiene, r=petrochenkov
[rust.git] / src / tools / rustfmt / docs / index.html
1 <!doctype html>
2 <html>
3     <head>
4       <meta name="viewport" content="width=device-width">
5       <title>Rustfmt</title>
6       <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/3.0.1/github-markdown.css" />
7       <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.0/styles/github-gist.min.css">
8       <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
9       <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
10       <script src="https://unpkg.com/vue-async-computed@3.8.1"></script>
11       <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.0/highlight.min.js"></script>
12       <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>
13       <style>
14         @media (max-width: 767px) {
15           .markdown-body {
16             padding: 15px;
17           }
18
19           #search {
20             max-width: 85%;
21           }
22         }
23         body {
24           overflow: scroll;
25         }
26         .markdown-body {
27           box-sizing: border-box;
28           min-width: 200px;
29           max-width: 980px;
30           margin: 0 auto;
31           padding: 45px;
32         }
33         #search {
34           border: 1px solid #d1d5da;
35           padding-left: 30px;
36           overflow: hidden;
37         }
38         .searchCondition {
39           display: flex;
40           flex-wrap: wrap;
41         }
42         .searchCondition > div {
43           margin-right: 30px;
44         }
45         .header-link {
46           position: relative;
47         }
48         .header-link:hover::before {
49           position: absolute;
50           left: -2em;
51           padding-right: 0.5em;
52           content: '\2002\00a7\2002';
53         }
54       </style>
55     </head>
56     <body>
57         <div id="app">
58           <article class="markdown-body">
59             <div class="searchCondition">
60               <div>
61                 <form style="display:flex;">
62                   <label for="search" style="margin-right: 3px;" >search:</label>
63                   <div style="position: relative;">
64                     <input id="search" placeholder="Search all options" v-model="searchCondition">
65                     <svg style="position: absolute; left: 8px; top: 7px;" class="octicon octicon-search subnav-search-icon" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true">
66                       <path fill-rule="evenodd" d="M15.7 13.3l-3.81-3.83A5.93 5.93 0 0 0 13 6c0-3.31-2.69-6-6-6S1 2.69 1 6s2.69 6 6 6c1.3 0 2.48-.41 3.47-1.11l3.83 3.81c.19.2.45.3.7.3.25 0 .52-.09.7-.3a.996.996 0 0 0 0-1.41v.01zM7 10.7c-2.59 0-4.7-2.11-4.7-4.7 0-2.59 2.11-4.7 4.7-4.7 2.59 0 4.7 2.11 4.7 4.7 0 2.59-2.11 4.7-4.7 4.7z"></path>
67                     </svg>
68                   </div>
69                 </form>
70               </div>
71               <div>
72                   <label for="stable">stable: </label>
73                   <input type="checkbox" id="stable" v-model="shouldStable">
74               </div>
75               <div>
76                   <label for="viewVersion">version: </label>
77                   <select name="viewVersion" id="viewVersion" v-model="viewVersion">
78                     <option v-for="option in versionOptions" v-bind:value="option">
79                       {{ option }}
80                     </option>
81                   </select>
82               </div>
83             </div>
84             <div v-html="aboutHtml"></div>
85             <div v-html="configurationAboutHtml"></div>
86             <div v-html="outputHtml"></div>
87           </article>
88         </div>
89         <script>
90             const RusfmtTagsUrl = 'https://api.github.com/repos/rust-lang/rustfmt/tags';
91             const RustfmtLatestUrl = 'https://api.github.com/repos/rust-lang/rustfmt/releases/latest';
92             const UrlHash = window.location.hash.replace(/^#/, '');
93             const queryParams = new URLSearchParams(window.location.search);
94             const searchParam = queryParams.get('search');
95             const searchTerm = null !== searchParam ? searchParam : '';
96             const versionParam = queryParams.get('version');
97             const parseVersionParam = (version) => {
98               if (version === 'master') return 'master';
99               if (version.startsWith('v')) return version;
100               return `v${version}`;
101             };
102             const versionNumber = null !== versionParam ? parseVersionParam(versionParam) : 'master';
103             new Vue({
104               el: '#app',
105               data: {
106                 aboutHtml: '',
107                 configurationAboutHtml: '',
108                 configurationDescriptions: [],
109                 searchCondition: searchTerm,
110                 shouldStable: false,
111                 viewVersion: versionNumber,
112                 oldViewVersion: undefined,
113                 versionOptions: ['master'],
114                 scrolledOnce: false,
115               },
116               asyncComputed: {
117                 async updateVersion() {
118                   let latest;
119                   try {
120                     latest = (await axios.get(RustfmtLatestUrl)).data;
121                   } catch(err) {
122                       console.log(err);
123                     return;
124                   }
125                   if (versionParam == null) {
126                     this.viewVersion = latest.name;
127                   }
128                 },
129                 async outputHtml() {
130                   if (this.viewVersion !== this.oldViewVersion) {
131                     const ConfigurationMdUrl =
132                       `https://raw.githubusercontent.com/rust-lang/rustfmt/${this.viewVersion}/Configurations.md`;
133                     let res;
134                     try {
135                       res = await axios.get(ConfigurationMdUrl).catch(e => { throw e });
136                     } catch(e) {
137                       this.handleReqFailure(e);
138                       return;
139                     }
140                     const {
141                       about,
142                       configurationAbout,
143                       configurationDescriptions
144                     } = parseMarkdownAst(res.data);
145                     this.aboutHtml = marked.parser(about);
146                     this.configurationAboutHtml = marked.parser(configurationAbout);
147                     this.configurationDescriptions = configurationDescriptions;
148                     this.oldViewVersion = this.viewVersion;
149                   }
150
151                   const ast = this.configurationDescriptions
152                       .filter(({ head, text, stable }) => {
153                         if (text.includes(this.searchCondition) === false &&
154                           head.includes(this.searchCondition) === false) {
155                           return false;
156                         }
157                         return (this.shouldStable)
158                           ? stable === true
159                           : true;
160                       })
161                       .reduce((stack, { value }) => {
162                         return stack.concat(value);
163                       }, []);
164                   ast.links = {};
165
166                   queryParams.set('version', this.viewVersion);
167                   queryParams.set('search', this.searchCondition);
168                   const curUrl = window.location.pathname +
169                     '?' + queryParams.toString() + window.location.hash;
170                   history.pushState(null, '', curUrl);
171
172                   const renderer = new marked.Renderer();
173                   renderer.heading = function(text, level) {
174                     const id = htmlToId(text);
175                     return `<h${level}>
176                               <a id="${id}" href="#${id}" name="${id}" class="header-link">${text}</a>
177                             </h${level}>`;
178                   };
179
180                   return marked.parser(ast, {
181                     highlight(code, lang) {
182                       return hljs.highlight(lang ? lang : 'rust', code).value;
183                     },
184                     headerIds: true,
185                     headerPrefix: '',
186                     renderer,
187                   });
188                 }
189               },
190               created: async function() {
191                 let tags;
192                 try {
193                   tags = (await axios.get(RusfmtTagsUrl)).data;
194                 } catch(e) {
195                   this.handleReqFailure(e);
196                   return;
197                 }
198
199                 const excludedTagVersions = new Set(['v0.7', 'v0.8.1']);
200
201                 const tagOptions = tags
202                   .map(tag => tag.name)
203                   .filter(tag => tag.startsWith('v') && !excludedTagVersions.has(tag));
204                 this.versionOptions = this.versionOptions.concat(tagOptions);
205               },
206               updated() {
207                 if (UrlHash === '') return;
208                 this.$nextTick(() => {
209                   const target = document.querySelector(`#${UrlHash}`);
210                   if (target != null && !this.scrolledOnce) {
211                     target.scrollIntoView(true);
212                     this.scrolledOnce = true;
213                   }
214                 });
215               },
216               methods: {
217                 handleReqFailure(e) {
218                   if (e.response.status === 404) {
219                     this.aboutHtml =
220                       "<p>Failed to get configuration options for this version, please select the version from the dropdown above.</p>";
221                   } else if (
222                     e.response.status === 403 &&
223                     e.response.headers["X-RateLimit-Remaining"] === 0
224                   ) {
225                     const resetDate = new Date(
226                       e.response.headers['X-RateLimit-Reset'] * 1000
227                     ).toLocaleString();
228                     this.aboutHtml =
229                       `<p>You have hit the GitHub API rate limit; documentation cannot be updated.` +
230                       `<p>The rate limit will be reset at ${resetDate}.</p>`;
231                   } else {
232                     this.aboutHtml =
233                       `<p>Ecountered an error when fetching documentation data:</p>` +
234                       `<pre><code>${e.response.data}</code></pre>` +
235                       `<p>We would appreciate <a href="https://github.com/rust-lang/rustfmt/issues/new?template=bug_report.md">a bug report</a>.` +
236                       `<p>Try refreshing the page.</p>`;
237                   }
238                 }
239               }
240             });
241             const extractDepthOnes = (ast) => {
242               return ast.reduce((stack, next) => {
243                 if (next.depth === 1) {
244                   stack.push([]);
245                 }
246                 const lastIndex = stack.length - 1;
247                 stack[lastIndex].push(next);
248                 return stack;
249               }, []);
250             }
251             const extractDepthTwos = (ast) => {
252               return ast.map((elem) => {
253                 return elem.reduce((stack, next) => {
254                   if (next.depth === 2) {
255                     stack.push([]);
256                   }
257                   const lastIndex = stack.length - 1;
258                   stack[lastIndex].push(next);
259                   return stack;
260                 },
261                 [[]]);
262               });
263             }
264             const createHeadAndValue = (ast) => {
265               return ast.map((elem) => {
266                 return elem.map((val) => {
267                   return {
268                     head: val[0].text,
269                     value: val,
270                     stable: val.some((elem) => {
271                       return elem.type === "list" &&
272                         !!elem.raw &&
273                         elem.raw.includes("**Stable**: Yes");
274                     }),
275                     text: val.reduce((result, next) => {
276                       return next.text != null
277                         ? `${result} ${next.text}`
278                         : result;
279                     }, '')
280                   }
281                 });
282               })
283             }
284             const parseMarkdownAst = (rawMarkdown) => {
285               const ast = marked.lexer(rawMarkdown);
286               const depthOnes = extractDepthOnes(ast);
287               const depthTwos = extractDepthTwos(depthOnes);
288               const [
289                 abouts, configurations
290               ] = createHeadAndValue(depthTwos);
291               const about = abouts[0].value;
292               about.links = {};
293               const [
294                 configurationAbout, ...configurationDescriptions
295               ] = configurations;
296               configurationAbout.value.links = {};
297
298               return {
299                 about,
300                 configurationAbout: configurationAbout.value,
301                 configurationDescriptions
302               };
303             }
304             function htmlToId(text) {
305               const tmpl = document.createElement('template');
306               tmpl.innerHTML = text.trim();
307               return encodeURIComponent(CSS.escape(tmpl.content.textContent));
308             }
309         </script>
310     </body>
311 </html>