-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
346 lines (339 loc) · 13.8 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
const fetch = require('node-fetch');
const fs = require('node:fs');
const express = require('express');
const cors = require('cors');
const path = require('path');
const date = new Date();
// Arrays to store api data
let specsAr = [];
let anim = [];
let notFullAnim = [];
let notAnim = [];
let other = [];
let notAnimTitles = [];
let animTitles = [];
let notFullAnimTitles = [];
let otherTitles = [];
// Get data from api
async function fetchF() {
// Get all specs urls
let indexResponse = await fetch('https://w3c.github.io/webref/ed/index.json');
if (indexResponse.ok) {
let json = await indexResponse.json();
let result = json.results;
result.map(async spec => {
specsAr.push(spec);
if (spec.css !== undefined) {
let cssPath = spec.css;
let SpecUrl = 'https://w3c.github.io/webref/ed/' + cssPath;
// Get data from each spec
let specsResponse = await fetch(SpecUrl);
if (specsResponse.ok) {
let json = await specsResponse.json();
let specs = json.spec;
// Get Each spec headings
let title = specs.title;
// Get all properties from each spec
let properties = json.properties;
properties.map(el => {
// Not animatable
if (
el.animationType === 'not animatable' ||
el.animatable == 'no' ||
el.animatable == 'No'
) {
el.title = title;
el.url = spec.url;
notAnim.push(el);
// Get only uniq titles
notAnimTitles.push(title);
notAnimTitles = [...new Set(notAnimTitles)];
}
// Not Fully Animatable
else if (
el.animationType === 'discrete'
) {
el.title = title;
el.url = spec.url;
notFullAnim.push(el);
notFullAnimTitles.push(title);
notFullAnimTitles = [...new Set(notFullAnimTitles)];
}
// Animatable
else if (
el.animationType === 'by computed value' ||
el.animationType === 'by computed value type' ||
el.animationType === 'repeatable list' ||
el.animationType !== undefined ||
el.animatable !== undefined ||
el.animatable == 'yes' ||
el.animatable == 'Yes'
) {
el.title = title;
el.url = spec.url;
anim.push(el);
animTitles.push(title);
animTitles = [...new Set(animTitles)];
}
// Exceptions
// Skip repeated old ones from specs about new properties
else if (
!el.newValues &&
!el.name.includes('-webkit')
) {
el.title = title;
el.url = spec.url;
other.push(el);
otherTitles.push(title);
otherTitles = [...new Set(otherTitles)];
}
// Removed repeats
// else {
// console.log(el.name + ' - ' + el.animationType + ' - ' + title);
// }
});
}
else {
console.log(specsResponse);
}
}
});
console.log('FUNC');
}
else {
console.log(indexResponse);
}
}
// Server
let app = express();
app.use(cors());
// Static page file path
const fileName = './dist/index.html';
const stream = fs.createWriteStream(fileName);
// Build the page
stream.once('open', async function() {
await fetchF();
setTimeout(() => {
fetchF().then(() => {
// Animatable
let animHtml = animTitles.map(el => {
let title = el;
let item = anim.map(el => {
let propName = el.name;
if (el.title == title) {
let item = `<li class="property"><a class="property__link" href="${el.url + '#propdef-' + el.name}">${propName}</a>
${el.animationType !== undefined ? `<p class="property__type">Animation type: ${el.animationType.replace(/[<,>]/g, '')}</p>` : `<p class="property__type">${el.animatable.replace(/[<,>]/g, '')}</p>`}</li>`;
return item;
}
}).join('');
let list = `<ul>${item}</ul>`;
let html = `<h3>${title}</h3>`;
let section = `<section>${html}${list}</section>`;
return section;
}).join('');
// Not fully animatable
let notFullAnimHtml = notFullAnimTitles.map(el => {
let title = el;
let item = notFullAnim.map(el => {
let propName = el.name;
if (el.title == title) {
let item = `<li class="property"><a class="property__link" href="${el.url + '#propdef-' + el.name}">${propName}</a></li>`;
return item;
}
}).join('');
let list = `<ul>${item}</ul>`;
let html = `<h3>${title}</h3>`;
let section = `<section>${html}${list}</section>`;
return section;
}).join('');
// Not animatable
let notAnimHtml = notAnimTitles.map(el => {
let title = el;
let item = notAnim.map(el => {
let propName = el.name;
if (el.title == title) {
let item = `<li class="property"><a class="property__link" href="${el.url + '#propdef-' + el.name}">${propName}</a></li>`;
return item;
}
}).join('');
let list = `<ul>${item}</ul>`;
let html = `<h3>${title}</h3>`;
let section = `<section>${html}${list}</section>`;
return section;
}).join('');
// Exceptions
let otherHtml = otherTitles.map(el => {
let title = el;
let item = other.map(el => {
let propName = el.name;
if (el.title == title) {
let item = `<li class="property"><a class="property__link" href="${el.url + '#propdef-' + el.name}">${propName}</a></li>`;
return item;
}
}).join('');
let list = `<ul>${item}</ul>`;
let html = `<h3>${title}</h3>`;
let section = `<section>${html}${list}</section>`;
return section;
}).join('');
// HTML with variables from above
const html = String.raw;
let buildHtml = html`
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Animatable and not animatable CSS properties</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Lists of Animatable and not animatable CSS properties from W3C api">
<link rel="apple-touch-icon" sizes="180x180" href="apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="favicon-16x16.png">
<link rel="manifest" href="site.webmanifest">
<link rel="mask-icon" href="safari-pinned-tab.svg" color="#5bbad5">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff">
<link rel="stylesheet" href="css/style.css">
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-LCWJ9R5X3T"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-LCWJ9R5X3T');
</script>
</head>
<body class="page">
<script>
const thisPage = document.querySelector('.page');
// Check if user set dark theme before
if (localStorage.getItem('vallek-animatable-css-theme') == 'dark') {
thisPage.classList.add('dark');
}
// Check if user prefers dark theme
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
thisPage.classList.add('dark');
}
</script>
<main class="page__main">
<h1 class="page__title">Animatable and not animatable CSS properties</h1>
<div class="page__notes">
<p>This page contains lists of animatable and not animatable CSS properties. There <a href="https://web.archive.org/web/20230131022559/https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animated_properties">was</a> a list like this on MDN but it was removed (see <a href="https://github.com/mdn/content/issues/27042">discussion here</a>), so I decided to make one) I'd like to thank @yarusome and @Josh-Cena for replying and providing a link to the W3C api.</p>
<p>This page is <em>not</em> affiliated with W3C or MDN. However it uses W3C <a href="https://github.com/w3c/webref">open API</a> to get all the data from specifications.</p>
<p>Some values may differ between W3C api and any other sources (including MDN and specs themselves). There are also multiple <a href="https://www.w3.org/TR/CSS/#css-levels">Levels</a> of same specs where same properties also may differ. Always check different sources and test it yourself!</p>
<p>The point of this page is to be fully automated without need for manual edits. It updates once a day. If you don't see any properties (this means build failed) or if you found any other problem please create an issue on <a href="https://github.com/Vallek/animatable-css">github</a>.</p>
<div class="header__footer">
<span>created by: <a href="https://github.com/Vallek">Vallek</a></span>
<div class="themes">
<h2 class="themes__text visually-hidden">Change Color Theme</h2>
<a class="themes__theme themes__theme_light" href="#">Light Theme</a>
<a class="themes__theme themes__theme_dark" href="#">Dark Theme</a>
</div>
</div>
</div>
<h2>Syntax, how to use:</h2>
<blockquote class="page__syntax">
<p><strong>Spec Title</strong><span> - name of W3C spec where property belongs</span></p>
<ul>
<li>
<p><strong>css-property-name</strong><span> - anchor link to the part of spec about this property.</span></p>
<p><strong>Animation type</strong><span> - you can read about types <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animated_properties#animation_types">on MDN</a></span></p>
</li>
</ul>
</blockquote>
<section class="contents">
<h2>Contents</h2>
<ol class="contents__list">
<li>
<a href="#anim">Animatable CSS properties</a>
</li>
<li>
<a href="#not-full-anim">Not fully animatable CSS properties</a>
</li>
<li>
<a href="#not-anim">Not animatable CSS properties</a>
</li>
<li>
<a href="#other">Other cases</a>
</li>
</ol>
</section>
<section class="page__section" id="anim">
<h2><a href="#anim">Animatable CSS properties</a></h2>
<div class="section__notes">
<p>This is a list of properties that can have actual gradual transition from one state to another.</p>
<p>If it says "see §" as animation type value just click on property link. You will find an anchor link to the specific part of spec there.</p>
<p>If it says "see individual properties" you can find them close to the shorthand or once again in specs following property link. Some of those could actually be <a href="#not-full-anim">not fully animatable.</a></p>
</div>
<div class="lists anim">${animHtml}</div>
</section>
<section class="page__section" id="not-full-anim">
<h2><a href="#not-full-anim">Not Fully Animatable CSS properties</a></h2>
<div class="section__notes">
<p>This is a list of properties with <code>discrete</code> animation type. They are technically animatable but have no real transition and go from start to end with swap at 50%.</p>
</div>
<div class="lists anim">${notFullAnimHtml}</div>
</section>
<section class="page__section" id="not-anim">
<h2><a href="#not-anim">Not animatable CSS properties</a></h2>
<div class="section__notes">
<p>You can see a lot of animation/transition properties here. That's because they animate others but can't be animated themselves.</p>
</div>
<div class="lists non-anim">${notAnimHtml}</div>
</section>
<section class="page__section" id="other">
<h2><a href="#other">Other cases</a></h2>
<div class="section__notes">
<p>This is a list of everything else from api that didn't fit main lists. It happens if there is no animation type so api returns <code>undefined</code>. For example <code>z-index</code>. It has no animation type in specs. But in reality it's <code>discrete</code> (also called<code>an integer</code> on MDN).
<p>There are also some other properties that are duplicates from different specs or with -webkit prefix that already are in main lists. They are filtered out automatically. If you noticed something is missing please create an issue on <a href="https://github.com/Vallek/animatable-css">github</a>.</p>
</div>
<div class="lists other">${otherHtml}</div>
</section>
<section class="footer">
<span>Created by: <a href="https://github.com/Vallek">Vallek</a> using W3C API, Node.js and Github Actions, 2023—<span class="current-year">${date.getFullYear()}</span></span>
<p>CSS Icon from <a href="https://commons.wikimedia.org/wiki/File:CSS3_logo_and_wordmark.svg">Wiki under Creative Commons</a></p>
</section>
</main>
<div class="to-top">
<a class="to-top__link" href="#" aria-label="Go to top" title="Go to top">⏫</a>
</div>
<script>
const page = document.querySelector('.page');
const lightThemeLink = document.querySelector('.themes__theme_light');
const darkThemeLink = document.querySelector('.themes__theme_dark');
// Check theme preference switch real time
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
const newColorScheme = event.matches ? 'dark' : 'light';
if (newColorScheme == 'dark') {
page.classList.add('dark');
}
if (newColorScheme == 'light') {
page.classList.remove('dark');
}
});
// Turn dark theme on
darkThemeLink.addEventListener('click', setDark);
function setDark(el) {
el.preventDefault();
page.classList.add('dark');
localStorage.setItem('vallek-animatable-css-theme', 'dark');
}
// Turn light theme on
lightThemeLink.addEventListener('click', setLight);
function setLight(el) {
el.preventDefault();
page.classList.remove('dark');
localStorage.setItem('vallek-animatable-css-theme', 'light');
}
</script>
</body>
</html>
`;
stream.end(buildHtml);
});
}, 3000);
});
// Static server THIS MUST BE AT THE END
app.use(express.static(__dirname + "/dist/"));
// For local live server
// app.listen(process.env.PORT || 3000);