Todomvc preact - Phase 1 (#104)
This commit is contained in:
parent
09210bc05e
commit
1933672b81
19 changed files with 9319 additions and 5740 deletions
|
|
@ -6,6 +6,7 @@ package-lock.json
|
|||
|
||||
/resources/todomvc/architecture-examples/*
|
||||
!/resources/todomvc/architecture-examples/backbone
|
||||
!/resources/todomvc/architecture-examples/preact
|
||||
|
||||
/resources/todomvc/vanilla-examples/*
|
||||
!/resources/todomvc/vanilla-examples/javascript-es5
|
||||
|
|
|
|||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -5,6 +5,7 @@
|
|||
/node_modules
|
||||
|
||||
/resources/todomvc/architecture-examples/backbone/node_modules/
|
||||
/resources/todomvc/architecture-examples/preact/node_modules/
|
||||
|
||||
/resources/todomvc/vanilla-examples/javascript-es5/node_modules/
|
||||
/resources/todomvc/vanilla-examples/javascript-es6/node_modules/
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ package-lock.json
|
|||
|
||||
/resources/todomvc/architecture-examples/*
|
||||
!/resources/todomvc/architecture-examples/backbone
|
||||
!/resources/todomvc/architecture-examples/preact
|
||||
|
||||
/resources/todomvc/vanilla-examples/*
|
||||
!/resources/todomvc/vanilla-examples/javascript-es5
|
||||
|
|
|
|||
|
|
@ -305,7 +305,7 @@ Suites.push({
|
|||
});
|
||||
|
||||
Suites.push({
|
||||
name: "Preact-TodoMVC",
|
||||
name: "TodoMVC-Preact",
|
||||
url: "todomvc/architecture-examples/preact/dist/index.html",
|
||||
async prepare(page) {
|
||||
const element = await page.waitForElement(".new-todo");
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"presets": [
|
||||
"es2015-loose",
|
||||
"stage-0"
|
||||
],
|
||||
"plugins": [
|
||||
["transform-react-jsx", { "pragma":"h" }]
|
||||
]
|
||||
}
|
||||
|
|
@ -1,16 +1,35 @@
|
|||
# Speedometer 2.1: Preact TodoMVC example
|
||||
# Speedometer 3.0: TodoMVC: Preact
|
||||
|
||||
## Test locally
|
||||
## Description
|
||||
|
||||
1. `npm install`
|
||||
2. `npm start`
|
||||
This application uses Preact 10.11.3 to implement a todo application.
|
||||
|
||||
## Build
|
||||
- [Preact](https://preactjs.com/) Fast 3kB alternative to React with the same modern API.
|
||||
|
||||
1. `npm run build`
|
||||
## Implementation details
|
||||
|
||||
## Notes
|
||||
[TBD]
|
||||
|
||||
The compiled version of the application can be found in the `build` directory.
|
||||
This is what the benchmark runner uses when running the Preact TodoMVC as part
|
||||
of a benchmark run.
|
||||
## Built steps
|
||||
|
||||
```
|
||||
terminal:
|
||||
1. npm run build
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
The only requirement is an installation of Node, to be able to install dependencies and run scripts to serve a local server.
|
||||
|
||||
```
|
||||
* Node (min version: 18.13.0)
|
||||
* NPM (min version: 8.19.3)
|
||||
```
|
||||
|
||||
## Local preview
|
||||
|
||||
```
|
||||
terminal:
|
||||
1. npm install
|
||||
2. npm run start
|
||||
```
|
||||
|
|
|
|||
1
resources/todomvc/architecture-examples/preact/dist/app.css
vendored
Normal file
1
resources/todomvc/architecture-examples/preact/dist/app.css
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -3,8 +3,7 @@
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Preact TodoMVC example</title>
|
||||
<link rel="stylesheet" href="todomvc-common/base.css">
|
||||
<link rel="stylesheet" href="todomvc.css">
|
||||
<link rel="stylesheet" href="app.css">
|
||||
</head>
|
||||
<body>
|
||||
<section class="todoapp"></section>
|
||||
|
|
|
|||
|
|
@ -1,141 +0,0 @@
|
|||
hr {
|
||||
margin: 20px 0;
|
||||
border: 0;
|
||||
border-top: 1px dashed #c5c5c5;
|
||||
border-bottom: 1px dashed #f7f7f7;
|
||||
}
|
||||
|
||||
.learn a {
|
||||
font-weight: normal;
|
||||
text-decoration: none;
|
||||
color: #b83f45;
|
||||
}
|
||||
|
||||
.learn a:hover {
|
||||
text-decoration: underline;
|
||||
color: #787e7e;
|
||||
}
|
||||
|
||||
.learn h3,
|
||||
.learn h4,
|
||||
.learn h5 {
|
||||
margin: 10px 0;
|
||||
font-weight: 500;
|
||||
line-height: 1.2;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.learn h3 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.learn h4 {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.learn h5 {
|
||||
margin-bottom: 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.learn ul {
|
||||
padding: 0;
|
||||
margin: 0 0 30px 25px;
|
||||
}
|
||||
|
||||
.learn li {
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.learn p {
|
||||
font-size: 15px;
|
||||
font-weight: 300;
|
||||
line-height: 1.3;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
#issue-count {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.quote {
|
||||
border: none;
|
||||
margin: 20px 0 60px 0;
|
||||
}
|
||||
|
||||
.quote p {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.quote p:before {
|
||||
content: '“';
|
||||
font-size: 50px;
|
||||
opacity: .15;
|
||||
position: absolute;
|
||||
top: -20px;
|
||||
left: 3px;
|
||||
}
|
||||
|
||||
.quote p:after {
|
||||
content: '”';
|
||||
font-size: 50px;
|
||||
opacity: .15;
|
||||
position: absolute;
|
||||
bottom: -42px;
|
||||
right: 3px;
|
||||
}
|
||||
|
||||
.quote footer {
|
||||
position: absolute;
|
||||
bottom: -40px;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.quote footer img {
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.quote footer a {
|
||||
margin-left: 5px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.speech-bubble {
|
||||
position: relative;
|
||||
padding: 10px;
|
||||
background: rgba(0, 0, 0, .04);
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.speech-bubble:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
right: 30px;
|
||||
border: 13px solid transparent;
|
||||
border-top-color: rgba(0, 0, 0, .04);
|
||||
}
|
||||
|
||||
.learn-bar > .learn {
|
||||
position: absolute;
|
||||
width: 272px;
|
||||
top: 8px;
|
||||
left: -300px;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
background-color: rgba(255, 255, 255, .6);
|
||||
transition-property: left;
|
||||
transition-duration: 500ms;
|
||||
}
|
||||
|
||||
@media (min-width: 899px) {
|
||||
.learn-bar {
|
||||
width: auto;
|
||||
padding-left: 300px;
|
||||
}
|
||||
|
||||
.learn-bar > .learn {
|
||||
left: 8px;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,249 +0,0 @@
|
|||
/* global _ */
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
/* jshint ignore:start */
|
||||
// Underscore's Template Module
|
||||
// Courtesy of underscorejs.org
|
||||
var _ = (function (_) {
|
||||
_.defaults = function (object) {
|
||||
if (!object) {
|
||||
return object;
|
||||
}
|
||||
for (var argsIndex = 1, argsLength = arguments.length; argsIndex < argsLength; argsIndex++) {
|
||||
var iterable = arguments[argsIndex];
|
||||
if (iterable) {
|
||||
for (var key in iterable) {
|
||||
if (object[key] == null) {
|
||||
object[key] = iterable[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
// By default, Underscore uses ERB-style template delimiters, change the
|
||||
// following template settings to use alternative delimiters.
|
||||
_.templateSettings = {
|
||||
evaluate : /<%([\s\S]+?)%>/g,
|
||||
interpolate : /<%=([\s\S]+?)%>/g,
|
||||
escape : /<%-([\s\S]+?)%>/g
|
||||
};
|
||||
|
||||
// When customizing `templateSettings`, if you don't want to define an
|
||||
// interpolation, evaluation or escaping regex, we need one that is
|
||||
// guaranteed not to match.
|
||||
var noMatch = /(.)^/;
|
||||
|
||||
// Certain characters need to be escaped so that they can be put into a
|
||||
// string literal.
|
||||
var escapes = {
|
||||
"'": "'",
|
||||
'\\': '\\',
|
||||
'\r': 'r',
|
||||
'\n': 'n',
|
||||
'\t': 't',
|
||||
'\u2028': 'u2028',
|
||||
'\u2029': 'u2029'
|
||||
};
|
||||
|
||||
var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
|
||||
|
||||
// JavaScript micro-templating, similar to John Resig's implementation.
|
||||
// Underscore templating handles arbitrary delimiters, preserves whitespace,
|
||||
// and correctly escapes quotes within interpolated code.
|
||||
_.template = function(text, data, settings) {
|
||||
var render;
|
||||
settings = _.defaults({}, settings, _.templateSettings);
|
||||
|
||||
// Combine delimiters into one regular expression via alternation.
|
||||
var matcher = new RegExp([
|
||||
(settings.escape || noMatch).source,
|
||||
(settings.interpolate || noMatch).source,
|
||||
(settings.evaluate || noMatch).source
|
||||
].join('|') + '|$', 'g');
|
||||
|
||||
// Compile the template source, escaping string literals appropriately.
|
||||
var index = 0;
|
||||
var source = "__p+='";
|
||||
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
|
||||
source += text.slice(index, offset)
|
||||
.replace(escaper, function(match) { return '\\' + escapes[match]; });
|
||||
|
||||
if (escape) {
|
||||
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
|
||||
}
|
||||
if (interpolate) {
|
||||
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
|
||||
}
|
||||
if (evaluate) {
|
||||
source += "';\n" + evaluate + "\n__p+='";
|
||||
}
|
||||
index = offset + match.length;
|
||||
return match;
|
||||
});
|
||||
source += "';\n";
|
||||
|
||||
// If a variable is not specified, place data values in local scope.
|
||||
if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
|
||||
|
||||
source = "var __t,__p='',__j=Array.prototype.join," +
|
||||
"print=function(){__p+=__j.call(arguments,'');};\n" +
|
||||
source + "return __p;\n";
|
||||
|
||||
try {
|
||||
render = new Function(settings.variable || 'obj', '_', source);
|
||||
} catch (e) {
|
||||
e.source = source;
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (data) return render(data, _);
|
||||
var template = function(data) {
|
||||
return render.call(this, data, _);
|
||||
};
|
||||
|
||||
// Provide the compiled function source as a convenience for precompilation.
|
||||
template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
|
||||
|
||||
return template;
|
||||
};
|
||||
|
||||
return _;
|
||||
})({});
|
||||
|
||||
if (location.hostname === 'todomvc.com') {
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
||||
ga('create', 'UA-31081062-1', 'auto');
|
||||
ga('send', 'pageview');
|
||||
}
|
||||
/* jshint ignore:end */
|
||||
|
||||
function redirect() {
|
||||
if (location.hostname === 'tastejs.github.io') {
|
||||
location.href = location.href.replace('tastejs.github.io/todomvc', 'todomvc.com');
|
||||
}
|
||||
}
|
||||
|
||||
function findRoot() {
|
||||
var base = location.href.indexOf('examples/');
|
||||
return location.href.substr(0, base);
|
||||
}
|
||||
|
||||
function getFile(file, callback) {
|
||||
if (!location.host) {
|
||||
return console.info('Miss the info bar? Run TodoMVC from a server to avoid a cross-origin error.');
|
||||
}
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
|
||||
xhr.open('GET', findRoot() + file, true);
|
||||
xhr.send();
|
||||
|
||||
xhr.onload = function () {
|
||||
if (xhr.status === 200 && callback) {
|
||||
callback(xhr.responseText);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function Learn(learnJSON, config) {
|
||||
if (!(this instanceof Learn)) {
|
||||
return new Learn(learnJSON, config);
|
||||
}
|
||||
|
||||
var template, framework;
|
||||
|
||||
if (typeof learnJSON !== 'object') {
|
||||
try {
|
||||
learnJSON = JSON.parse(learnJSON);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (config) {
|
||||
template = config.template;
|
||||
framework = config.framework;
|
||||
}
|
||||
|
||||
if (!template && learnJSON.templates) {
|
||||
template = learnJSON.templates.todomvc;
|
||||
}
|
||||
|
||||
if (!framework && document.querySelector('[data-framework]')) {
|
||||
framework = document.querySelector('[data-framework]').dataset.framework;
|
||||
}
|
||||
|
||||
this.template = template;
|
||||
|
||||
if (learnJSON.backend) {
|
||||
this.frameworkJSON = learnJSON.backend;
|
||||
this.frameworkJSON.issueLabel = framework;
|
||||
this.append({
|
||||
backend: true
|
||||
});
|
||||
} else if (learnJSON[framework]) {
|
||||
this.frameworkJSON = learnJSON[framework];
|
||||
this.frameworkJSON.issueLabel = framework;
|
||||
this.append();
|
||||
}
|
||||
|
||||
this.fetchIssueCount();
|
||||
}
|
||||
|
||||
Learn.prototype.append = function (opts) {
|
||||
var aside = document.createElement('aside');
|
||||
aside.innerHTML = _.template(this.template, this.frameworkJSON);
|
||||
aside.className = 'learn';
|
||||
|
||||
if (opts && opts.backend) {
|
||||
// Remove demo link
|
||||
var sourceLinks = aside.querySelector('.source-links');
|
||||
var heading = sourceLinks.firstElementChild;
|
||||
var sourceLink = sourceLinks.lastElementChild;
|
||||
// Correct link path
|
||||
var href = sourceLink.getAttribute('href');
|
||||
sourceLink.setAttribute('href', href.substr(href.lastIndexOf('http')));
|
||||
sourceLinks.innerHTML = heading.outerHTML + sourceLink.outerHTML;
|
||||
} else {
|
||||
// Localize demo links
|
||||
var demoLinks = aside.querySelectorAll('.demo-link');
|
||||
Array.prototype.forEach.call(demoLinks, function (demoLink) {
|
||||
if (demoLink.getAttribute('href').substr(0, 4) !== 'http') {
|
||||
demoLink.setAttribute('href', findRoot() + demoLink.getAttribute('href'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.body.className = (document.body.className + ' learn-bar').trim();
|
||||
document.body.insertAdjacentHTML('afterBegin', aside.outerHTML);
|
||||
};
|
||||
|
||||
Learn.prototype.fetchIssueCount = function () {
|
||||
var issueLink = document.getElementById('issue-count-link');
|
||||
if (issueLink) {
|
||||
var url = issueLink.href.replace('https://github.com', 'https://api.github.com/repos');
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', url, true);
|
||||
xhr.onload = function (e) {
|
||||
var parsedResponse = JSON.parse(e.target.responseText);
|
||||
if (parsedResponse instanceof Array) {
|
||||
var count = parsedResponse.length;
|
||||
if (count !== 0) {
|
||||
issueLink.innerHTML = 'This app has ' + count + ' open issues';
|
||||
document.getElementById('issue-count').style.display = 'inline';
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
}
|
||||
};
|
||||
|
||||
redirect();
|
||||
getFile('learn.json', Learn);
|
||||
})();
|
||||
|
|
@ -1,376 +0,0 @@
|
|||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
button {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background: none;
|
||||
font-size: 100%;
|
||||
vertical-align: baseline;
|
||||
font-family: inherit;
|
||||
font-weight: inherit;
|
||||
color: inherit;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
body {
|
||||
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
line-height: 1.4em;
|
||||
background: #f5f5f5;
|
||||
color: #4d4d4d;
|
||||
min-width: 230px;
|
||||
max-width: 550px;
|
||||
margin: 0 auto;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.todoapp {
|
||||
background: #fff;
|
||||
margin: 130px 0 40px 0;
|
||||
position: relative;
|
||||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),
|
||||
0 25px 50px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.todoapp input::-webkit-input-placeholder {
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
color: #e6e6e6;
|
||||
}
|
||||
|
||||
.todoapp input::-moz-placeholder {
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
color: #e6e6e6;
|
||||
}
|
||||
|
||||
.todoapp input::input-placeholder {
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
color: #e6e6e6;
|
||||
}
|
||||
|
||||
.todoapp h1 {
|
||||
position: absolute;
|
||||
top: -155px;
|
||||
width: 100%;
|
||||
font-size: 100px;
|
||||
font-weight: 100;
|
||||
text-align: center;
|
||||
color: rgba(175, 47, 47, 0.15);
|
||||
-webkit-text-rendering: optimizeLegibility;
|
||||
-moz-text-rendering: optimizeLegibility;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
|
||||
.new-todo,
|
||||
.edit {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
font-size: 24px;
|
||||
font-family: inherit;
|
||||
font-weight: inherit;
|
||||
line-height: 1.4em;
|
||||
border: 0;
|
||||
color: inherit;
|
||||
padding: 6px;
|
||||
border: 1px solid #999;
|
||||
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
|
||||
box-sizing: border-box;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.new-todo {
|
||||
padding: 16px 16px 16px 60px;
|
||||
border: none;
|
||||
background: rgba(0, 0, 0, 0.003);
|
||||
box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03);
|
||||
}
|
||||
|
||||
.main {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
border-top: 1px solid #e6e6e6;
|
||||
}
|
||||
|
||||
.toggle-all {
|
||||
text-align: center;
|
||||
border: none; /* Mobile Safari */
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.toggle-all + label {
|
||||
width: 60px;
|
||||
height: 34px;
|
||||
font-size: 0;
|
||||
position: absolute;
|
||||
top: -52px;
|
||||
left: -13px;
|
||||
-webkit-transform: rotate(90deg);
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.toggle-all + label:before {
|
||||
content: '❯';
|
||||
font-size: 22px;
|
||||
color: #e6e6e6;
|
||||
padding: 10px 27px 10px 27px;
|
||||
}
|
||||
|
||||
.toggle-all:checked + label:before {
|
||||
color: #737373;
|
||||
}
|
||||
|
||||
.todo-list {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.todo-list li {
|
||||
position: relative;
|
||||
font-size: 24px;
|
||||
border-bottom: 1px solid #ededed;
|
||||
}
|
||||
|
||||
.todo-list li:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.todo-list li.editing {
|
||||
border-bottom: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.todo-list li.editing .edit {
|
||||
display: block;
|
||||
width: 506px;
|
||||
padding: 12px 16px;
|
||||
margin: 0 0 0 43px;
|
||||
}
|
||||
|
||||
.todo-list li.editing .view {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.todo-list li .toggle {
|
||||
text-align: center;
|
||||
width: 40px;
|
||||
/* auto, since non-WebKit browsers doesn't support input styling */
|
||||
height: auto;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin: auto 0;
|
||||
border: none; /* Mobile Safari */
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
.todo-list li .toggle {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.todo-list li .toggle + label {
|
||||
/*
|
||||
Firefox requires `#` to be escaped - https://bugzilla.mozilla.org/show_bug.cgi?id=922433
|
||||
IE and Edge requires *everything* to be escaped to render, so we do that instead of just the `#` - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7157459/
|
||||
*/
|
||||
background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E');
|
||||
background-repeat: no-repeat;
|
||||
background-position: center left;
|
||||
}
|
||||
|
||||
.todo-list li .toggle:checked + label {
|
||||
background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E');
|
||||
}
|
||||
|
||||
.todo-list li label {
|
||||
word-break: break-all;
|
||||
padding: 15px 15px 15px 60px;
|
||||
display: block;
|
||||
line-height: 1.2;
|
||||
transition: color 0.4s;
|
||||
}
|
||||
|
||||
.todo-list li.completed label {
|
||||
color: #d9d9d9;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.todo-list li .destroy {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 10px;
|
||||
bottom: 0;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin: auto 0;
|
||||
font-size: 30px;
|
||||
color: #cc9a9a;
|
||||
margin-bottom: 11px;
|
||||
transition: color 0.2s ease-out;
|
||||
}
|
||||
|
||||
.todo-list li .destroy:hover {
|
||||
color: #af5b5e;
|
||||
}
|
||||
|
||||
.todo-list li .destroy:after {
|
||||
content: '×';
|
||||
}
|
||||
|
||||
.todo-list li:hover .destroy {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.todo-list li .edit {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.todo-list li.editing:last-child {
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
color: #777;
|
||||
padding: 10px 15px;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
border-top: 1px solid #e6e6e6;
|
||||
}
|
||||
|
||||
.footer:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
height: 50px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2),
|
||||
0 8px 0 -3px #f6f6f6,
|
||||
0 9px 1px -3px rgba(0, 0, 0, 0.2),
|
||||
0 16px 0 -6px #f6f6f6,
|
||||
0 17px 2px -6px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.todo-count {
|
||||
float: left;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.todo-count strong {
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.filters {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.filters li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.filters li a {
|
||||
color: inherit;
|
||||
margin: 3px;
|
||||
padding: 3px 7px;
|
||||
text-decoration: none;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.filters li a:hover {
|
||||
border-color: rgba(175, 47, 47, 0.1);
|
||||
}
|
||||
|
||||
.filters li a.selected {
|
||||
border-color: rgba(175, 47, 47, 0.2);
|
||||
}
|
||||
|
||||
.clear-completed,
|
||||
html .clear-completed:active {
|
||||
float: right;
|
||||
position: relative;
|
||||
line-height: 20px;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.clear-completed:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.info {
|
||||
margin: 65px auto 0;
|
||||
color: #bfbfbf;
|
||||
font-size: 10px;
|
||||
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.info p {
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.info a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.info a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/*
|
||||
Hack to remove background from Mobile Safari.
|
||||
Can't use it globally since it destroys checkboxes in Firefox
|
||||
*/
|
||||
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
||||
.toggle-all,
|
||||
.todo-list li .toggle {
|
||||
background: none;
|
||||
}
|
||||
|
||||
.todo-list li .toggle {
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 430px) {
|
||||
.footer {
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.filters {
|
||||
bottom: 10px;
|
||||
}
|
||||
}
|
||||
14052
resources/todomvc/architecture-examples/preact/package-lock.json
generated
14052
resources/todomvc/architecture-examples/preact/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,46 +1,41 @@
|
|||
{
|
||||
"name": "library-preact",
|
||||
"version": "1.0.0",
|
||||
"description": "TodoMVC app written with Preact.",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "webpack-dev-server",
|
||||
"start": "http-server build -p ${PORT:-8080}",
|
||||
"prestart": "npm run build",
|
||||
"build": "npm run -s build:rollup",
|
||||
"build:webpack": "mkdirp dist && ncp src/index.html dist/index.html && webpack -p",
|
||||
"build:rollup": "rm -rf dist && mkdirp dist/todomvc-common && ncp src/index.html dist/index.html && rollup -c rollup.config.js && cp node_modules/todomvc-common/base.{js,css} dist/todomvc-common/ && cp node_modules/todomvc-app-css/index.css dist/todomvc.css && npm run postbuild",
|
||||
"postbuild": "uglifyjs dist/app.js --pure-funcs classCallCheck Object.defineProperty Object.freeze invariant warning -c unsafe,collapse_vars,evaluate,screw_ie8,loops,keep_fargs=false,pure_getters,unused,dead_code -m -o dist/app.js -p relative --in-source-map dist/app.js.map --source-map dist/app.js.map"
|
||||
"engines": {
|
||||
"node": ">=18.13.0",
|
||||
"npm": ">=8.19.3"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "rollup -c --bundleConfigAsCjs",
|
||||
"watch": "ROLLUP_WATCH=true rollup -c -w --bundleConfigAsCjs",
|
||||
"serve": "http-server ./dist -p 7002 -c-1 --cors -o",
|
||||
"start": "npm-run-all --parallel serve watch"
|
||||
},
|
||||
"author": "The TodoMVC authors",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.5.2",
|
||||
"babel-loader": "^6.2.3",
|
||||
"babel-plugin-transform-class-properties": "^6.5.2",
|
||||
"babel-plugin-transform-decorators-legacy": "^1.3.4",
|
||||
"babel-plugin-transform-react-jsx": "^6.5.2",
|
||||
"babel-preset-babili": "0.0.9",
|
||||
"babel-preset-es2015": "^6.5.0",
|
||||
"babel-preset-es2015-loose": "^8.0.0",
|
||||
"babel-preset-stage-0": "^6.5.0",
|
||||
"css-loader": "^0.26.0",
|
||||
"extract-text-webpack-plugin": "^1.0.1",
|
||||
"http-server": "^0.9.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"ncp": "^2.0.0",
|
||||
"replace-bundle-webpack-plugin": "^1.0.0",
|
||||
"rollup": "^0.36.4",
|
||||
"rollup-plugin-babel": "^2.6.1",
|
||||
"rollup-plugin-commonjs": "^5.0.5",
|
||||
"rollup-plugin-node-resolve": "^2.0.0",
|
||||
"style-loader": "^0.13.0",
|
||||
"webpack": "^1.12.14",
|
||||
"webpack-dev-server": "^1.14.1"
|
||||
"@babel/plugin-transform-react-jsx": "^7.21.0",
|
||||
"@babel/preset-env": "^7.20.2",
|
||||
"@babel/preset-react": "^7.18.6",
|
||||
"@rollup/plugin-babel": "^6.0.3",
|
||||
"@rollup/plugin-commonjs": "^24.0.1",
|
||||
"@rollup/plugin-node-resolve": "^15.0.1",
|
||||
"@rollup/plugin-terser": "^0.4.0",
|
||||
"http-server": "^14.1.1",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"rollup": "^3.19.1",
|
||||
"rollup-plugin-copy": "^3.4.0",
|
||||
"rollup-plugin-gzip": "^3.1.0",
|
||||
"rollup-plugin-import-css": "^3.2.1",
|
||||
"rollup-plugin-postcss": "^4.0.2",
|
||||
"rollup-plugin-resolve": "^0.0.1-predev.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"classnames": "^2.2.5",
|
||||
"linkstate": "^1.0.1",
|
||||
"preact": "^8.2.1",
|
||||
"preact-router": "^2.5.5",
|
||||
"todomvc-app-css": "^2.0.3",
|
||||
"todomvc-common": "^1.0.2"
|
||||
"classnames": "^2.3.2",
|
||||
"linkstate": "^2.0.1",
|
||||
"preact": "^10.13.1",
|
||||
"preact-router": "^4.1.0",
|
||||
"todomvc-app-css": "^2.4.2",
|
||||
"todomvc-common": "^1.0.5"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Preact TodoMVC example</title>
|
||||
<link rel="stylesheet" href="todomvc-common/base.css">
|
||||
<link rel="stylesheet" href="todomvc.css">
|
||||
<link rel="stylesheet" href="app.css">
|
||||
</head>
|
||||
<body>
|
||||
<section class="todoapp"></section>
|
||||
|
|
@ -1,27 +1,52 @@
|
|||
import nodeResolve from 'rollup-plugin-node-resolve';
|
||||
import commonjs from 'rollup-plugin-commonjs';
|
||||
import babel from 'rollup-plugin-babel';
|
||||
import terser from "@rollup/plugin-terser";
|
||||
import resolve from "@rollup/plugin-node-resolve";
|
||||
import commonjs from "@rollup/plugin-commonjs";
|
||||
import babel from "@rollup/plugin-babel";
|
||||
import css from "rollup-plugin-import-css";
|
||||
import copy from "rollup-plugin-copy";
|
||||
|
||||
// `npm run build` -> `production` is true
|
||||
// `npm run dev` -> `production` is false
|
||||
const production = !process.env.ROLLUP_WATCH;
|
||||
|
||||
export default {
|
||||
entry: 'src/index.js',
|
||||
dest: 'dist/app.js',
|
||||
format: 'iife',
|
||||
sourceMap: true,
|
||||
external: [],
|
||||
input: "src/index.js",
|
||||
output: [
|
||||
{
|
||||
file: "dist/app.js",
|
||||
format: "iife",
|
||||
sourcemap: true,
|
||||
},
|
||||
],
|
||||
plugins: [
|
||||
css({
|
||||
minify: true,
|
||||
}),
|
||||
babel({
|
||||
babelrc: false,
|
||||
presets: [
|
||||
['es2015', { loose:true, modules:false }],
|
||||
'stage-0'
|
||||
["@babel/preset-env", { targets: "defaults" }],
|
||||
["@babel/preset-react", { runtime: "automatic" }],
|
||||
],
|
||||
plugins: [
|
||||
['transform-react-jsx', { pragma:'h' }]
|
||||
]
|
||||
[
|
||||
"@babel/plugin-transform-react-jsx",
|
||||
{
|
||||
pragma: "h",
|
||||
pragmaFrag: "Fragment",
|
||||
},
|
||||
],
|
||||
],
|
||||
}),
|
||||
nodeResolve({
|
||||
jsnext: true
|
||||
resolve({
|
||||
jsnext: true,
|
||||
main: true,
|
||||
browser: true,
|
||||
}),
|
||||
commonjs()
|
||||
]
|
||||
commonjs(),
|
||||
copy({
|
||||
targets: [{ src: "public/index.html", dest: "dist/" }],
|
||||
}),
|
||||
production && terser(),
|
||||
],
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,5 +2,5 @@ import { h, render } from 'preact';
|
|||
import App from './app';
|
||||
// import 'todomvc-common';
|
||||
// import 'todomvc-common/base.css';
|
||||
// import 'todomvc-app-css/index.css';
|
||||
import 'todomvc-app-css/index.css';
|
||||
render(<App />, document.querySelector('.todoapp'));
|
||||
|
|
|
|||
|
|
@ -1,39 +0,0 @@
|
|||
import ExtractTextPlugin from 'extract-text-webpack-plugin';
|
||||
import ReplacePlugin from 'replace-bundle-webpack-plugin';
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
app: './src/index.js',
|
||||
'todomvc-common': 'todomvc-common'
|
||||
},
|
||||
output: {
|
||||
path: './dist',
|
||||
filename: '[name].js'
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{
|
||||
test: /\.jsx?$/,
|
||||
exclude: /node_modules/,
|
||||
loader: 'babel'
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
loader: ExtractTextPlugin.extract('style', 'css?sourceMap')
|
||||
}
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new ExtractTextPlugin('style.css', { allChunks: true }),
|
||||
new ReplacePlugin([{
|
||||
// this is actually the property name https://github.com/kimhou/replace-bundle-webpack-plugin/issues/1
|
||||
partten: /throw\s+(new\s+)?[a-zA-Z]+Error\s*\(/g,
|
||||
replacement: () => 'return;('
|
||||
}])
|
||||
],
|
||||
devtool: 'source-map',
|
||||
devServer: {
|
||||
port: process.env.PORT || 8080,
|
||||
contentBase: './src'
|
||||
}
|
||||
};
|
||||
Loading…
Reference in a new issue