1
0
mirror of https://github.com/chinchang/web-maker.git synced 2025-05-07 11:05:18 +02:00

Merge pull request #509 from chinchang/v5

V5
This commit is contained in:
Kushagra Gour 2022-04-07 13:26:25 +05:30 committed by GitHub
commit 48c475d17b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
50 changed files with 61104 additions and 13175 deletions

View File

@ -1,4 +1,5 @@
{
// "presets": ["preact-cli/babel"],
"env": {
"test": {
"presets": [["preact-cli/babel", { "modules": "commonjs" }]]

3
.gitignore vendored
View File

@ -17,4 +17,5 @@ node_modules/
.sass-cache
extension/
yarn-error.log
extension-*.zip
src/locales/_build
extension-*.zip

1
.nvmrc Normal file
View File

@ -0,0 +1 @@
16

View File

@ -1,4 +1,6 @@
{
"singleQuote": true,
"useTabs": true
"useTabs": true,
"trailingComma": "none",
"arrowParens": "avoid"
}

View File

@ -44,10 +44,10 @@ Support with $ETH - 0x39989c0E53cfdcF6792e09d7573c65E911e774bA
If not that, you can support by simply sharing about how much you love 💖 [@webmakerapp](https://twitter.com/webmakerApp).
## Sponsors
[![](https://user-images.githubusercontent.com/379918/134402085-15cf29bc-2266-4b2d-9354-1830adc4a240.png)](https://cssbattle.dev)
Web Maker stays stable as rock with every release, thanks to the sponsored testing on the awesome
Web Maker stays stable as rock with every release, thanks to the sponsored testing on the awesome
<a href="http://browserstack.com/"><img alt="Browserstack logo" src="https://user-images.githubusercontent.com/379918/134403020-50167453-223a-4841-8ef6-312219bcb2e6.png" height="60"></a>
Deployed on the superfast [Netlify](https://www.netlify.com/) platform.

View File

@ -2,7 +2,7 @@
const fs = require('fs');
const gulp = require('gulp');
const runSequence = require('run-sequence');
const { parallel, series } = require('gulp');
const useref = require('gulp-useref');
const cleanCSS = require('gulp-clean-css');
const rename = require('gulp-rename');
@ -23,15 +23,18 @@ function minifyJs(fileName) {
).code;
fs.writeFileSync(fileName, minifiedContent);
console.log(
`[${fileName}]: ${content.length / 1024}K -> ${minifiedContent.length /
1024}K`
`[${fileName}]: ${content.length / 1024}K -> ${
minifiedContent.length / 1024
}K`
);
}
gulp.task('runWebpack', function() {
return child_process.execSync('yarn run build');
gulp.task('runWebpack', function () {
return child_process.exec('npm run build', (error, stdout, stderr) => {
console.log('runWebpack', error, stdout, stderr);
});
});
gulp.task('copyFiles', function() {
gulp.task('copyFiles', function () {
return merge(
gulp
.src('src/lib/codemirror/theme/*')
@ -56,19 +59,11 @@ gulp.task('copyFiles', function() {
'src/detached-window.js',
'src/icon-48.png',
'src/icon-128.png',
'manifest.json'
'src/manifest.json'
])
.pipe(gulp.dest('app')),
gulp
.src('build/bundle.*.js')
.pipe(rename('script.js'))
.pipe(gulp.dest('app')),
gulp
.src('build/vendor.*.js')
.pipe(rename('vendor.js'))
.pipe(gulp.dest('app')),
gulp.src('build/monaco.*.js').pipe(gulp.dest('app')),
gulp.src('build/*').pipe(gulp.dest('app')),
// Following CSS are copied to build/ folder where they'll be referenced by
// useRef plugin to concat into one.
@ -86,7 +81,7 @@ gulp.task('copyFiles', function() {
.pipe(gulp.dest('build/lib/codemirror/addon/dialog')),
gulp.src('src/lib/hint.min.css').pipe(gulp.dest('build/lib')),
gulp.src('src/lib/inlet.css').pipe(gulp.dest('build/lib')),
gulp.src('src/style.css').pipe(gulp.dest('build')),
// gulp.src('src/style.css').pipe(gulp.dest('build')),
gulp
.src([
@ -99,23 +94,26 @@ gulp.task('copyFiles', function() {
);
});
gulp.task('useRef', function() {
gulp.task('useRef', function () {
return gulp.src('build/index.html').pipe(useref()).pipe(gulp.dest('app'));
});
gulp.task('concatSwRegistration', function () {
const bundleFile = fs
.readdirSync('app')
.filter(allFilesPaths => allFilesPaths.match(/bundle.*\.js$/) !== null)[0];
console.log('matched', bundleFile);
return gulp
.src('build/index.html')
.pipe(useref())
.src(['src/service-worker-registration.js', `app/${bundleFile}`])
.pipe(concat(bundleFile))
.pipe(gulp.dest('app'));
});
gulp.task('concatSwRegistration', function() {
return gulp
.src(['src/service-worker-registration.js', 'app/script.js'])
.pipe(concat('script.js'))
.pipe(gulp.dest('app'));
});
gulp.task('minify', function() {
minifyJs('app/script.js');
minifyJs('app/vendor.js');
gulp.task('minify', function () {
// minifyJs('app/script.js');
// minifyJs('app/vendor.js');
minifyJs('app/lib/screenlog.js');
return gulp
@ -127,9 +125,7 @@ gulp.task('minify', function() {
},
details => {
console.log(
`${details.name}: ${details.stats.originalSize} 👉🏼 ${
details.stats.minifiedSize
}`
`${details.name}: ${details.stats.originalSize} 👉🏼 ${details.stats.minifiedSize}`
);
}
)
@ -137,7 +133,7 @@ gulp.task('minify', function() {
.pipe(gulp.dest('app'));
});
gulp.task('fixIndex', function() {
gulp.task('fixIndex', function (cb) {
var contents = fs.readFileSync('build/index.html', 'utf8');
// Replace hashed-filename script tags with unhashed ones
contents = contents.replace(
@ -151,10 +147,11 @@ gulp.task('fixIndex', function() {
''
);
fs.writeFileSync('build/index.html', contents, 'utf8');
// fs.writeFileSync('build/index.html', contents, 'utf8');
cb();
});
gulp.task('generate-service-worker', function(callback) {
gulp.task('generate-service-worker', function (callback) {
var swPrecache = require('sw-precache');
var rootDir = 'app';
@ -173,7 +170,7 @@ gulp.task('generate-service-worker', function(callback) {
);
});
gulp.task('packageExtension', function() {
gulp.task('packageExtension', function () {
child_process.execSync('rm -rf extension');
child_process.execSync('cp -R app extension');
child_process.execSync('cp src/manifest.json extension');
@ -186,30 +183,36 @@ gulp.task('packageExtension', function() {
gulp
.src('build/bundle.*.js')
.pipe(rename('script.js'))
.pipe(gulp.dest('extension')),
.pipe(gulp.dest('extension'))
gulp
.src('extension/**/*')
.pipe(zip(`extension-${packageJson.version}.zip`))
.pipe(gulp.dest('./'))
// gulp
// .src('extension/**/*')
// .pipe(zip(`extension-${packageJson.version}.zip`))
// .pipe(gulp.dest('./'))
);
});
gulp.task('buildWebsite', function() {
return child_process.execSync('yarn run build-website');
gulp.task('buildWebsite', function () {
return child_process.exec(
'npm run build-website',
(error, stdout, stderr) => {
console.log('buildWebsite', error, stdout, stderr);
}
);
});
gulp.task('buildDistFolder', function() {
gulp.task('buildDistFolder', function (cb) {
child_process.execSync('rm -rf dist');
child_process.execSync('mv packages/website/_site dist');
child_process.execSync('mv app dist/');
cb();
});
gulp.task('cleanup', function() {
return child_process.execSync('rm -rf build');
gulp.task('cleanup', function () {
return child_process.exec('rm -rf build');
});
gulp.task('start-preview-server', function() {
gulp.task('start-preview-server', function () {
connect.server({
root: 'preview',
port: 7888,
@ -217,64 +220,62 @@ gulp.task('start-preview-server', function() {
});
});
gulp.task('release', function(callback) {
runSequence(
['runWebpack', 'buildWebsite'],
'copyFiles',
'fixIndex',
'useRef',
'concatSwRegistration',
'minify',
'generate-service-worker',
'packageExtension',
'buildDistFolder',
'cleanup',
function(error) {
if (error) {
console.log(error.message);
} else {
console.log('RELEASE FINISHED SUCCESSFULLY');
}
callback(error);
exports.release = series(
parallel('runWebpack', 'buildWebsite'),
'copyFiles',
'fixIndex',
'useRef',
'concatSwRegistration',
'minify',
'generate-service-worker',
'packageExtension',
'buildDistFolder',
'cleanup',
function (callback, error) {
if (error) {
console.log(error.message);
} else {
console.log('RELEASE FINISHED SUCCESSFULLY');
}
);
});
gulp.task('dev-release', function(callback) {
runSequence(
['runWebpack', 'buildWebsite'],
'copyFiles',
'fixIndex',
'useRef',
'concatSwRegistration',
'generate-service-worker',
'buildDistFolder',
'cleanup',
function(error) {
if (error) {
console.log(error.message);
} else {
console.log('DEV RELEASE FINISHED SUCCESSFULLY');
}
callback(error);
}
);
});
callback(error);
}
);
gulp.task('build-extension', function(callback) {
runSequence(
'runWebpack',
'copyFiles',
'fixIndex',
'useRef',
'packageExtension',
function(error) {
if (error) {
console.log(error.message);
} else {
console.log('DEV RELEASE FINISHED SUCCESSFULLY');
}
callback(error);
exports.devRelease = gulp.series(
parallel('runWebpack', 'buildWebsite'),
'copyFiles',
'fixIndex',
'useRef',
// 'concatSwRegistration',
// 'generate-service-worker',
'buildDistFolder',
'cleanup',
function (callback, error) {
if (error) {
console.log(error.message);
} else {
console.log('DEV-RELEASE FINISHED SUCCESSFULLY');
}
);
});
callback(error);
}
);
// gulp.task('build-extension', function (callback) {
// runSequence(
// 'runWebpack',
// 'copyFiles',
// 'fixIndex',
// 'useRef',
// 'packageExtension',
// function (error) {
// if (error) {
// console.log(error.message);
// } else {
// console.log('DEV RELEASE FINISHED SUCCESSFULLY');
// }
// callback(error);
// }
// );
// });

57934
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,11 @@
{
"name": "web-maker",
"version": "4.2.0",
"version": "5.0.0",
"description": "A blazing fast & offline web playground",
"scripts": {
"start": "npm run -s dev && gulp start-preview-server",
"build": "preact build --template src/index.html --no-prerender --service-worker false",
"serve": "preact build && preact serve",
"dev": "preact watch --template src/index.html --no-prerender",
"start": "concurrently --kill-others \"gulp start-preview-server\" \"npm run -s dev\"",
"build": "preact build --template src/index.html --prerender false --no-inline-css --sw false --esm false",
"dev": "preact watch --template src/index.html",
"serve-website": "cd packages/website; npm start",
"build-website": "cd packages/website; npm run build",
"lint": "eslint src",
@ -14,7 +13,8 @@
"precommit": "lint-staged",
"add-locale": "lingui add-locale",
"extract": "lingui extract",
"compile": "lingui compile"
"compile": "lingui compile",
"release:dev": "gulp devRelease"
},
"eslintConfig": {
"extends": "eslint-config-synacor"
@ -33,17 +33,22 @@
]
},
"devDependencies": {
"@lingui/cli": "^2.7.0",
"@lingui/macro": "^2.7.0",
"babel-core": "^6.26.3",
"@11ty/eleventy": "^0.7.1",
"@babel/core": "^7.5.4",
"@lingui/cli": "^2.8.3",
"@lingui/macro": "^2.8.3",
"babel-core": "^7.0.0-bridge.0",
"babel-eslint": "^7.2.3",
"babel-minify": "^0.2.0",
"babel-plugin-macros": "^2.6.1",
"concurrently": "^7.0.0",
"eslint": "^4.9.0",
"eslint-config-prettier": "^2.3.0",
"eslint-config-synacor": "^2.0.2",
"gulp": "^3.9.1",
"gulp": "^4.0.2",
"gulp-clean-css": "^3.9.2",
"gulp-concat": "^2.6.1",
"gulp-connect": "^5.7.0",
"gulp-rename": "^1.3.0",
"gulp-uglify": "^3.0.0",
"gulp-useref": "^3.1.3",
@ -51,37 +56,34 @@
"husky": "^0.14.3",
"identity-obj-proxy": "^3.0.0",
"if-env": "^1.0.0",
"jest": "^21.2.1",
"jest": "^24.8.0",
"jest-cli": "^24.8.0",
"lint-staged": "^7.2.0",
"merge-stream": "^1.0.1",
"preact-cli": "^2.1.0",
"preact-render-spy": "^1.2.1",
"run-sequence": "^2.2.1",
"sw-precache": "^5.2.0",
"@11ty/eleventy": "^0.7.1",
"markdown-it": "^8.4.2",
"markdown-it-anchor": "^5.0.2"
"markdown-it-anchor": "^5.0.2",
"merge-stream": "^1.0.1",
"preact-cli": "^3.0.0",
"sw-precache": "^5.2.0"
},
"dependencies": {
"@emmetio/codemirror-plugin": "^0.5.4",
"@lingui/react": "^2.7.0",
"@lingui/react": "^2.8.3",
"code-blast-codemirror": "chinchang/code-blast-codemirror#web-maker",
"codemirror": "^5.37.0",
"copy-webpack-plugin": "^4.5.1",
"esprima": "^4.0.0",
"firebase": "^5.5.8",
"gulp-connect": "^5.7.0",
"firebase": "^8.10.0",
"jszip": "^3.1.5",
"preact": "^8.2.6",
"preact-compat": "^3.17.0",
"preact": "^10.5.13",
"preact-portal": "^1.1.3",
"preact-router": "^2.5.7",
"prettier": "^1.16.4",
"preact-render-to-string": "^5.1.4",
"preact-router": "^3.2.1",
"prettier": "^2.2.1",
"react-inspector": "^2.3.0",
"split.js": "1.3.4"
"split.js": "^1.5.11"
},
"engines": {
"node": "10"
"node": "16"
},
"jest": {
"verbose": true,
@ -105,10 +107,9 @@
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/tests/__mocks__/fileMock.js",
"\\.(css|less|scss)$": "identity-obj-proxy",
"^./style$": "identity-obj-proxy",
"^preact$": "<rootDir>/node_modules/preact/dist/preact.min.js",
"^react$": "preact-compat",
"^react-dom$": "preact-compat",
"^create-react-class$": "preact-compat/lib/create-react-class",
"^preact$": "<rootDir>/node_modules/preact/dist/preact.js",
"^react$": "preact/compat",
"^react-dom$": "preact/compat",
"^react-addons-css-transition-group$": "preact-css-transition-group"
}
},
@ -132,5 +133,5 @@
"bugs": {
"url": "https://github.com/chinchang/web-maker/issues"
},
"homepage": "https://webmakerapp.com"
"homepage": "https://webmaker.app"
}

View File

@ -187,7 +187,7 @@
.screenshot {
box-shadow: 0 51px 33px -40px rgba(0, 0, 0, 0.6);
transform: rotateX(4deg) rotateY(-2deg);
border: 1px solid black;
border: 1px solid black;
border-radius: 10px;
}
@ -430,21 +430,19 @@
<svg class="logo" width="160" height="84">
<use xlink:href="#logo"></use>
</svg>
<h1 class="homepage-title">
Web Maker
</h1>
<h2 style="margin-bottom:0.4em;">
<h1 class="homepage-title">Web Maker</h1>
<h2 style="margin-bottom: 0.4em">
A blazing fast & offline web playground in your browser
</h2>
<div style="margin-top: 30px;" id="cta" class="mb-2">
<a class="btn download-btn web-app-btn" href="/app/">
<div style="margin-top: 30px" id="cta" class="mb-2">
<a class="btn download-btn web-app-btn" href="/app/">
<span>Open Web App</span>
</a>
<p style="margin-top:3px;">
<p style="margin-top: 3px">
Recommended: Works Offline! More features. More fun!
</p>
<a
class="btn download-btn js-chrome-btn"
class="btn download-btn js-chrome-btn"
href="https://chrome.google.com/webstore/detail/web-maker/lkfkkhfhhdkiemehlpkgjeojomhpccnh"
>
<img src="images/chrome-logo.png" height="40" alt="" />
@ -478,7 +476,7 @@
>
</div>
</header>
<div style="margin-top:30px; perspective: 400px">
<div style="margin-top: 30px; perspective: 400px">
<img
class="screenshot"
src="images/ss1.png?v4"
@ -490,7 +488,7 @@
{% else %}
<header class="site-header">
<div>
<h2 style="display: inline;">
<h2 style="display: inline">
<a href="/">
<svg class="site-header__logo">
<use xlink:href="#logo"></use>
@ -519,9 +517,7 @@
</header>
{% endif %}
<main class="main-content">
{{ content }}
</main>
<main class="main-content">{{ content }}</main>
<div id="info" class="info">
<p>
@ -550,7 +546,7 @@
or you can set up a filter in Adblock Plus or similar ad blocker tools
like AdBlock, uBlock or Adblock Pro.
</p>
<div style="text-align: center;">
<div style="text-align: center">
<a class="btn" href="javascript:void(0)" onclick="closeInfo()">Close</a>
</div>
</div>
@ -572,7 +568,7 @@
{% include footer.html %}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" style="display:none">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" style="display: none">
<symbol id="logo" viewBox="-145 -2 372 175">
<g
stroke="none"
@ -625,7 +621,7 @@
<script type="text/javascript">
window.$crisp = [];
window.CRISP_WEBSITE_ID = 'c00b07b9-42da-45dd-87b0-e614bf7fb240';
(function() {
(function () {
d = document;
s = d.createElement('script');
s.src = 'https://client.crisp.chat/l.js';

View File

@ -18,7 +18,7 @@
<a href="https://twitter.com/webmakerApp" rel="external">
<svg
viewBox="0 0 16 16"
style="width:1em;height:1em;margin-right:8px;fill:#55ACEE;"
style="width: 1em; height: 1em; margin-right: 8px; fill: #55acee"
>
<path
d="M15.969,3.058c-0.586,0.26-1.217,0.436-1.878,0.515c0.675-0.405,1.194-1.045,1.438-1.809
@ -31,7 +31,7 @@
<a href="https://github.com/chinchang/web-maker" rel="external">
<svg
viewBox="0 0 16 16"
style="width:1em;height:1em;margin-right:8px;fill:#666;"
style="width: 1em; height: 1em; margin-right: 8px; fill: #666"
>
<path
d="M7.999,0.431c-4.285,0-7.76,3.474-7.76,7.761 c0,3.428,2.223,6.337,5.307,7.363c0.388,0.071,0.53-0.168,0.53-0.374c0-0.184-0.007-0.672-0.01-1.32 c-2.159,0.469-2.614-1.04-2.614-1.04c-0.353-0.896-0.862-1.135-0.862-1.135c-0.705-0.481,0.053-0.472,0.053-0.472 c0.779,0.055,1.189,0.8,1.189,0.8c0.692,1.186,1.816,0.843,2.258,0.645c0.071-0.502,0.271-0.843,0.493-1.037 C4.86,11.425,3.049,10.76,3.049,7.786c0-0.847,0.302-1.54,0.799-2.082C3.768,5.507,3.501,4.718,3.924,3.65 c0,0,0.652-0.209,2.134,0.796C6.677,4.273,7.34,4.187,8,4.184c0.659,0.003,1.323,0.089,1.943,0.261 c1.482-1.004,2.132-0.796,2.132-0.796c0.423,1.068,0.157,1.857,0.077,2.054c0.497,0.542,0.798,1.235,0.798,2.082 c0,2.981-1.814,3.637-3.543,3.829c0.279,0.24,0.527,0.713,0.527,1.437c0,1.037-0.01,1.874-0.01,2.129 c0,0.208,0.14,0.449,0.534,0.373c3.081-1.028,5.302-3.935,5.302-7.362C15.76,3.906,12.285,0.431,7.999,0.431z"
@ -45,31 +45,31 @@
</ul>
</div>
</div>
<p class="ta-c" style="position: relative">
<img
src="https://cssbattle.dev/images/avatar-chang.png"
style="width: 260px; border-radius: 45px"
/>
<span
style="
position: absolute;
bottom: 0;
background: black;
border-radius: 35px;
padding: 5px 10px;
color: white;
display: inline-block;
width: 30ch;
left: calc(50% - 15ch);
"
>Made by
<a
href="https://twitter.com/chinchang457"
rel="external"
style="color: yellow"
>Kushagra Gour</a
></span
>
<img
src="https://cssbattle.dev/images/avatar-chang.png"
style="width: 260px; border-radius: 45px"
/>
<span
style="
position: absolute;
bottom: 0;
background: black;
border-radius: 35px;
padding: 5px 10px;
color: white;
display: inline-block;
width: 30ch;
left: calc(50% - 15ch);
"
>Made by
<a
href="https://twitter.com/chinchang457"
rel="external"
style="color: yellow"
>Kushagra Gour</a
></span
>
</p>
</footer>

View File

@ -1,4 +1,4 @@
var CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
// var CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
/**
* Function that mutates original webpack config.
@ -8,7 +8,7 @@ var CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
* @param {object} env - options passed to CLI.
* @param {WebpackConfigHelpers} helpers - object with useful helpers when working with config.
**/
export default function(config, env, helpers) {
export default function (config, env, helpers) {
const htmlWebpackPlugin = helpers.getPluginsByName(
config,
'HtmlWebpackPlugin'
@ -34,20 +34,24 @@ export default function(config, env, helpers) {
// Remove the default hash append in chunk name
config.output.chunkFilename = '[name].chunk.js';
config.plugins.push(
new CommonsChunkPlugin({
name: 'vendor',
minChunks: ({ resource }) => /node_modules/.test(resource)
})
);
// config.plugins.push(
// new CommonsChunkPlugin({
// name: 'vendor',
// minChunks: ({ resource }) => /node_modules/.test(resource)
// })
// );
const swPlugin = helpers.getPluginsByName(
config,
'SWPrecacheWebpackPlugin'
)[0];
config.plugins.splice(swPlugin.index, 1);
if (swPlugin) {
// config.plugins.splice(swPlugin.index, 1);
}
const uglifyPlugin = helpers.getPluginsByName(config, 'UglifyJsPlugin')[0];
config.plugins.splice(uglifyPlugin.index, 1);
if (uglifyPlugin) {
// config.plugins.splice(uglifyPlugin.index, 1);
}
}
}

View File

@ -2,6 +2,8 @@ import { h, Component } from 'preact';
import { jsLibs, cssLibs } from '../libraryList';
import { trackEvent } from '../analytics';
import { LibraryAutoSuggest } from './LibraryAutoSuggest';
import { Trans, t } from '@lingui/macro';
import { I18n } from '@lingui/react';
export default class AddLibrary extends Component {
constructor(props) {
@ -58,87 +60,104 @@ export default class AddLibrary extends Component {
}
render() {
return (
<div>
<h1>Add Library</h1>
<I18n>
{({ i18n }) => (
<div>
<h1>
<Trans>Add Library</Trans>
</h1>
<div class="flex flex-v-center">
<svg style="width: 30px; height: 30px;fill:rgb(255,255,255,0.5)">
<use xlinkHref="#search" />
</svg>
<LibraryAutoSuggest
fullWidth
onSelect={this.suggestionSelectHandler.bind(this)}
>
<input
type="text"
id="externalLibrarySearchInput"
<div class="flex flex-v-center">
<svg style="width: 30px; height: 30px;fill:rgb(255,255,255,0.5)">
<use xlinkHref="#search" />
</svg>
<LibraryAutoSuggest
fullWidth
onSelect={this.suggestionSelectHandler.bind(this)}
>
<input
type="text"
id="externalLibrarySearchInput"
class="full-width"
placeholder={i18n._(t`Type here to search libraries`)}
/>
</LibraryAutoSuggest>
</div>
<div class="tar opacity--70">
<small>
<Trans>Powered by cdnjs</Trans>
</small>
</div>
<div style="margin:20px 0;">
<Trans>Choose from popular libraries</Trans>:{' '}
<select
name=""
id="js-add-library-select"
onChange={this.onSelectChange.bind(this)}
>
<option value="">-------</option>
<optgroup label="JavaScript Libraries">
{jsLibs.map(lib => (
<option data-type={lib.type} value={lib.url}>
{lib.label}
</option>
))}
</optgroup>
<optgroup label="CSS Libraries">
{cssLibs.map(lib => (
<option data-type={lib.type} value={lib.url}>
{lib.label}
</option>
))}
</optgroup>
</select>
</div>
<h3 class="mb-0">JS</h3>
<p class="mt-0 help-text">
<Trans>Put each library in new line</Trans>
</p>
<p
style="font-size: 0.8em;"
class="show-when-extension opacity--70"
>
<Trans>
Note: You can load external scripts only from following domains:
</Trans>
localhost, https://ajax.googleapis.com, https://code.jquery.com,
https://cdnjs.cloudflare.com, https://unpkg.com,
https://maxcdn.com, https://cdn77.com,
https://maxcdn.bootstrapcdn.com, https://cdn.jsdelivr.net/,
https://rawgit.com, https://wzrd.in, https://cdn.tailwindcss.com
</p>
<textarea
onBlur={this.textareaBlurHandler.bind(this)}
data-lang="js"
class="full-width"
placeholder="Type here to search libraries"
id="externalJsTextarea"
cols="30"
rows="5"
value={this.state.js}
/>
</LibraryAutoSuggest>
</div>
<div class="tar opacity--70">
<small>Powered by cdnjs</small>
</div>
<div style="margin:20px 0;">
Choose from popular libraries:{' '}
<select
name=""
id="js-add-library-select"
onChange={this.onSelectChange.bind(this)}
>
<option value="">-------</option>
<optgroup label="JavaScript Libraries">
{jsLibs.map(lib => (
<option data-type={lib.type} value={lib.url}>
{lib.label}
</option>
))}
</optgroup>
<optgroup label="CSS Libraries">
{cssLibs.map(lib => (
<option data-type={lib.type} value={lib.url}>
{lib.label}
</option>
))}
</optgroup>
</select>
</div>
<h3 class="mb-0">JS</h3>
<p class="mt-0 help-text">Put each library in new line</p>
<p style="font-size: 0.8em;" class="show-when-extension opacity--70">
Note: You can load external scripts only from following domains:
localhost, https://ajax.googleapis.com, https://code.jquery.com,
https://cdnjs.cloudflare.com, https://unpkg.com, https://maxcdn.com,
https://cdn77.com, https://maxcdn.bootstrapcdn.com,
https://cdn.jsdelivr.net/, https://rawgit.com, https://wzrd.in,
https://cdn.tailwindcss.com
</p>
<textarea
onBlur={this.textareaBlurHandler.bind(this)}
data-lang="js"
class="full-width"
id="externalJsTextarea"
cols="30"
rows="5"
value={this.state.js}
/>
<h3 class="mb-0">CSS</h3>
<p class="mt-0 help-text">Put each library in new line</p>
<textarea
onBlur={this.textareaBlurHandler.bind(this)}
data-lang="css"
class="full-width"
id="externalCssTextarea"
cols="30"
rows="5"
value={this.state.css}
/>
</div>
<h3 class="mb-0">CSS</h3>
<p class="mt-0 help-text">
<Trans>Put each library in new line</Trans>
</p>
<textarea
onBlur={this.textareaBlurHandler.bind(this)}
data-lang="css"
class="full-width"
id="externalCssTextarea"
cols="30"
rows="5"
value={this.state.css}
/>
</div>
)}
</I18n>
);
}
}

View File

@ -1,7 +1,8 @@
import { h, Component } from 'preact';
import { Inspector, chromeDark } from 'react-inspector';
import { Trans } from '@lingui/macro';
import { PureComponent } from 'preact-compat';
import { Trans, t, NumberFormat } from '@lingui/macro';
import { I18n } from '@lingui/react';
import { PureComponent } from 'preact/compat';
class LogRow extends Component {
shouldComponentUpdate() {
@ -24,6 +25,10 @@ class LogRow extends Component {
}
export class Console extends PureComponent {
constructor(props) {
super(props);
this.mouseMoveHandler = this.mouseMoveHandler.bind(this);
}
componentDidUpdate(previousProps) {
if (this.props.logs !== previousProps.logs) {
// Scroll down after new log dom is inserted
@ -32,6 +37,42 @@ export class Console extends PureComponent {
}, 1);
}
}
componentWillUnmount() {
this.endDragging();
}
endDragging() {
if (!this.isDragging) {
return;
}
this.isDragging = false;
window.consoleEl.style.transition = this.savedTransition;
window.removeEventListener('mousemove', this.mouseMoveHandler);
window.removeEventListener('mouseup', this.mouseUpHandler);
}
mouseDownHandler(e) {
if (!this.props.isConsoleOpen) {
return true;
}
this.isDragging = true;
this.startY = e.pageY;
this.startHeight = window.consoleEl.getBoundingClientRect().height;
this.savedTransition = window.getComputedStyle(window.consoleEl).transition;
window.consoleEl.style.transition = 'none';
window.addEventListener('mousemove', this.mouseMoveHandler);
window.addEventListener('mouseup', this.mouseUpHandler);
}
mouseUpHandler() {
this.endDragging();
}
mouseMoveHandler(e) {
if (!this.isDragging) return true;
const newHeight = this.startHeight + (this.startY - e.pageY);
window.consoleEl.style.height = `${newHeight}px`;
}
render() {
const {
@ -44,62 +85,70 @@ export class Console extends PureComponent {
} = this.props;
return (
<div
id="consoleEl"
class={`console ${isConsoleOpen ? '' : 'is-minimized'}`}
>
<div id="consoleLogEl" class="console__log">
<I18n>
{({ i18n }) => (
<div
class="js-console__header code-wrap__header"
title="Double click to toggle console"
onDblClick={onConsoleHeaderDblClick}
id="consoleEl"
class={`console ${isConsoleOpen ? '' : 'is-minimized'}`}
>
<span class="code-wrap__header-label">
<Trans>Console</Trans>
<span class="count-label">{logs.length}</span>
</span>
<div class="code-wrap__header-right-options">
<a
class="code-wrap__header-btn"
title="Clear console (CTRL + L)"
onClick={onClearConsoleBtnClick}
<div id="consoleLogEl" class="console__log">
<div
class="js-console__header code-wrap__header"
title={i18n._(t`Double click to toggle console`)}
onDblClick={onConsoleHeaderDblClick}
onMouseDown={this.mouseDownHandler.bind(this)}
onMouseUp={this.mouseUpHandler.bind(this)}
>
<svg>
<use xlinkHref="#cancel-icon" />
</svg>
</a>
<a
class="code-wrap__header-btn code-wrap__collapse-btn"
title="Toggle console"
onClick={toggleConsole}
<span class="code-wrap__header-label">
<Trans>Console</Trans>
<span class="count-label">
<NumberFormat value={logs.length} />
</span>
</span>
<div class="code-wrap__header-right-options">
<a
class="code-wrap__header-btn"
title={i18n._(t`Clear console (CTRL + L)`)}
onClick={onClearConsoleBtnClick}
>
<svg>
<use xlinkHref="#cancel-icon" />
</svg>
</a>
<a
class="code-wrap__header-btn code-wrap__collapse-btn"
title={i18n._(t`Toggle console`)}
onClick={toggleConsole}
/>
</div>
</div>
<ul
class="console__items"
ref={el => {
this.logContainerEl = el;
}}
>
{logs.map(log => (
<LogRow data={log} />
))}
</ul>
</div>
<div
id="consolePromptEl"
class="console__prompt flex flex-v-center flex-shrink-0"
>
<svg width="18" height="18" fill="#346fd2">
<use xlinkHref="#chevron-icon" />
</svg>
<input
tabIndex={isConsoleOpen ? 0 : -1}
onKeyUp={onEvalInputKeyup}
class="console-exec-input"
/>
</div>
</div>
<ul
class="console__items"
ref={el => {
this.logContainerEl = el;
}}
>
{logs.map(log => (
<LogRow data={log} />
))}
</ul>
</div>
<div
id="consolePromptEl"
class="console__prompt flex flex-v-center flex-shrink-0"
>
<svg width="18" height="18" fill="#346fd2">
<use xlinkHref="#chevron-icon" />
</svg>
<input
tabIndex={isConsoleOpen ? 0 : -1}
onKeyUp={onEvalInputKeyup}
class="console-exec-input"
/>
</div>
</div>
)}
</I18n>
);
}
}

View File

@ -2,12 +2,16 @@ import { h, Component } from 'preact';
import CodeEditor from './CodeEditor.jsx';
import { computeHtml, computeCss, computeJs } from '../computes';
import { modes, HtmlModes, CssModes, JsModes } from '../codeModes';
import { log, writeFile, loadJS, getCompleteHtml } from '../utils';
import {
log,
writeFile,
getCompleteHtml,
handleModeRequirements,
sanitizeSplitSizes
} from '../utils';
import { SplitPane } from './SplitPane.jsx';
import { trackEvent } from '../analytics';
import CodeMirror from '../CodeMirror';
import { Console } from './Console';
import { deferred } from '../deferred';
import CssSettingsModal from './CssSettingsModal';
import { PreviewDimension } from './PreviewDimension.jsx';
const minCodeWrapSize = 33;
@ -313,9 +317,7 @@ export default class ContentWrap extends Component {
// Replace correct css file in LINK tags's href
if (prefs.editorTheme) {
window.editorThemeLinkTag.href = `lib/codemirror/theme/${
prefs.editorTheme
}.css`;
window.editorThemeLinkTag.href = `lib/codemirror/theme/${prefs.editorTheme}.css`;
}
window.fontStyleTag.textContent = window.fontStyleTemplate.textContent.replace(
@ -391,12 +393,18 @@ export default class ContentWrap extends Component {
resetSplitting() {
this.setState({
codeSplitSizes: this.getCodeSplitSizes(),
mainSplitSizes: this.getMainSplitSizesToApply()
codeSplitSizes: sanitizeSplitSizes(this.getCodeSplitSizes()),
mainSplitSizes: sanitizeSplitSizes(this.getMainSplitSizesToApply())
});
}
updateSplits() {
this.props.onSplitUpdate();
updateSplits(sizes) {
// HACK: This is weird thing happening. We call `onSplitUpdate` on parent. That calculates
// and sets sizes from the DOM on the currentItem. And then we read that size to update
// this component's state (codeSplitSizes and mainSPlitSizes).
// If we don't update, then some re-render will reset the pane sizes as ultimately the state
// variables here govern the split.
this.props.onSplitUpdate(sizes);
// Not using setState to avoid re-render
this.state.codeSplitSizes = this.props.currentItem.sizes;
this.state.mainSplitSizes = this.props.currentItem.mainSizes;
@ -426,7 +434,7 @@ export default class ContentWrap extends Component {
return [33.33, 33.33, 33.33];
}
mainSplitDragEndHandler() {
mainSplitDragEndHandler(sizes) {
if (this.props.prefs.refreshOnResize) {
// Running preview updation in next call stack, so that error there
// doesn't affect this dragend listener.
@ -434,7 +442,7 @@ export default class ContentWrap extends Component {
this.setPreviewContent(true);
}, 1);
}
this.updateSplits();
this.updateSplits(sizes);
}
mainSplitDragHandler() {
this.previewDimension.update({
@ -445,77 +453,30 @@ export default class ContentWrap extends Component {
codeSplitDragStart() {
document.body.classList.add('is-dragging');
}
codeSplitDragEnd() {
codeSplitDragEnd(sizes) {
this.updateCodeWrapCollapseStates();
document.body.classList.remove('is-dragging');
this.updateSplits();
}
/**
* Loaded the code comiler based on the mode selected
*/
handleModeRequirements(mode) {
const baseTranspilerPath = 'lib/transpilers';
// Exit if already loaded
var d = deferred();
if (modes[mode].hasLoaded) {
d.resolve();
return d.promise;
}
function setLoadedFlag() {
modes[mode].hasLoaded = true;
d.resolve();
}
if (mode === HtmlModes.JADE) {
loadJS(`${baseTranspilerPath}/jade.js`).then(setLoadedFlag);
} else if (mode === HtmlModes.MARKDOWN) {
loadJS(`${baseTranspilerPath}/marked.js`).then(setLoadedFlag);
} else if (mode === CssModes.LESS) {
loadJS(`${baseTranspilerPath}/less.min.js`).then(setLoadedFlag);
} else if (mode === CssModes.SCSS || mode === CssModes.SASS) {
loadJS(`${baseTranspilerPath}/sass.js`).then(function() {
window.sass = new Sass(`${baseTranspilerPath}/sass.worker.js`);
setLoadedFlag();
});
} else if (mode === CssModes.STYLUS) {
loadJS(`${baseTranspilerPath}/stylus.min.js`).then(setLoadedFlag);
} else if (mode === CssModes.ACSS) {
loadJS(`${baseTranspilerPath}/atomizer.browser.js`).then(setLoadedFlag);
} else if (mode === JsModes.COFFEESCRIPT) {
loadJS(`${baseTranspilerPath}/coffee-script.js`).then(setLoadedFlag);
} else if (mode === JsModes.ES6) {
loadJS(`${baseTranspilerPath}/babel.min.js`).then(setLoadedFlag);
} else if (mode === JsModes.TS) {
loadJS(`${baseTranspilerPath}/typescript.js`).then(setLoadedFlag);
} else {
d.resolve();
}
return d.promise;
this.updateSplits(sizes);
}
updateHtmlMode(value) {
this.props.onCodeModeChange('html', value);
this.props.currentItem.htmlMode = value;
this.cm.html.setLanguage(value);
return this.handleModeRequirements(value);
return handleModeRequirements(value);
}
updateCssMode(value) {
this.props.onCodeModeChange('css', value);
this.props.currentItem.cssMode = value;
this.cm.css.setOption('readOnly', modes[value].cmDisable);
window.cssSettingsBtn.classList[
modes[value].hasSettings ? 'remove' : 'add'
]('hide');
this.cm.css.setLanguage(value);
return this.handleModeRequirements(value);
return handleModeRequirements(value);
}
updateJsMode(value) {
this.props.onCodeModeChange('js', value);
this.props.currentItem.jsMode = value;
this.cm.js.setLanguage(value);
return this.handleModeRequirements(value);
return handleModeRequirements(value);
}
codeModeChangeHandler(e) {
var mode = e.target.value;
@ -776,17 +737,19 @@ export default class ContentWrap extends Component {
</select>
</label>
<div class="code-wrap__header-right-options">
<a
href="#"
id="cssSettingsBtn"
title="Atomic CSS configuration"
onClick={this.cssSettingsBtnClickHandler.bind(this)}
class="code-wrap__header-btn hide"
>
<svg>
<use xlinkHref="#settings-icon" />
</svg>
</a>
{modes[this.props.currentItem.cssMode || 'css'].hasSettings && (
<a
href="#"
id="cssSettingsBtn"
title="Atomic CSS configuration"
onClick={this.cssSettingsBtnClickHandler.bind(this)}
class="code-wrap__header-btn"
>
<svg>
<use xlinkHref="#settings-icon" />
</svg>
</a>
)}
<a
class="code-wrap__header-btn "
title="Format code"
@ -919,6 +882,7 @@ export default class ContentWrap extends Component {
toggleConsole={this.toggleConsole}
onEvalInputKeyup={this.evalConsoleExpr}
/>
<CssSettingsModal
show={this.state.isCssSettingsModalOpen}
closeHandler={() =>

View File

@ -1,7 +1,12 @@
import { h, Component } from 'preact';
import CodeEditor from './CodeEditor';
import { modes, HtmlModes, CssModes, JsModes } from '../codeModes';
import { log, loadJS, BASE_PATH } from '../utils';
import { modes, HtmlModes } from '../codeModes';
import {
log,
handleModeRequirements,
BASE_PATH,
sanitizeSplitSizes
} from '../utils';
import {
linearizeFiles,
@ -14,7 +19,6 @@ import { SplitPane } from './SplitPane';
import { trackEvent } from '../analytics';
import CodeMirror from '../CodeMirror';
import 'codemirror/mode/meta';
import { deferred } from '../deferred';
import { SidePane } from './SidePane';
import { Console } from './Console';
import { SWITCH_FILE_EVENT } from '../commands';
@ -353,9 +357,7 @@ export default class ContentWrapFiles extends Component {
// Replace correct css file in LINK tags's href
if (prefs.editorTheme) {
window.editorThemeLinkTag.href = `lib/codemirror/theme/${
prefs.editorTheme
}.css`;
window.editorThemeLinkTag.href = `lib/codemirror/theme/${prefs.editorTheme}.css`;
}
window.fontStyleTag.textContent = window.fontStyleTemplate.textContent.replace(
@ -393,11 +395,11 @@ export default class ContentWrapFiles extends Component {
resetSplitting() {
this.setState({
mainSplitSizes: this.getMainSplitSizesToApply()
mainSplitSizes: sanitizeSplitSizes(this.getMainSplitSizesToApply())
});
}
updateSplits() {
this.props.onSplitUpdate();
updateSplits(sizes) {
this.props.onSplitUpdate(sizes);
// Not using setState to avoid re-render
this.state.mainSplitSizes = this.props.currentItem.mainSizes;
}
@ -419,7 +421,7 @@ export default class ContentWrapFiles extends Component {
return mainSplitSizes;
}
mainSplitDragEndHandler() {
mainSplitDragEndHandler(sizes) {
if (this.props.prefs.refreshOnResize) {
// Running preview updation in next call stack, so that error there
// doesn't affect this dragend listener.
@ -427,7 +429,7 @@ export default class ContentWrapFiles extends Component {
this.setPreviewContent(true);
}, 1);
}
this.updateSplits();
this.updateSplits(sizes);
}
mainSplitDragHandler() {
this.previewDimension.update({
@ -436,51 +438,6 @@ export default class ContentWrapFiles extends Component {
});
}
/**
* Loaded the code comiler based on the mode selected
*/
handleModeRequirements(mode) {
const baseTranspilerPath = 'lib/transpilers';
// Exit if already loaded
var d = deferred();
if (modes[mode].hasLoaded) {
d.resolve();
return d.promise;
}
function setLoadedFlag() {
modes[mode].hasLoaded = true;
d.resolve();
}
if (mode === HtmlModes.JADE) {
loadJS(`${baseTranspilerPath}/jade.js`).then(setLoadedFlag);
} else if (mode === HtmlModes.MARKDOWN) {
loadJS(`${baseTranspilerPath}/marked.js`).then(setLoadedFlag);
} else if (mode === CssModes.LESS) {
loadJS(`${baseTranspilerPath}/less.min.js`).then(setLoadedFlag);
} else if (mode === CssModes.SCSS || mode === CssModes.SASS) {
loadJS(`${baseTranspilerPath}/sass.js`).then(function() {
window.sass = new Sass(`${baseTranspilerPath}/sass.worker.js`);
setLoadedFlag();
});
} else if (mode === CssModes.STYLUS) {
loadJS(`${baseTranspilerPath}/stylus.min.js`).then(setLoadedFlag);
} else if (mode === CssModes.ACSS) {
loadJS(`${baseTranspilerPath}/atomizer.browser.js`).then(setLoadedFlag);
} else if (mode === JsModes.COFFEESCRIPT) {
loadJS(`${baseTranspilerPath}/coffee-script.js`).then(setLoadedFlag);
} else if (mode === JsModes.ES6) {
loadJS(`${baseTranspilerPath}/babel.min.js`).then(setLoadedFlag);
} else if (mode === JsModes.TS) {
loadJS(`${baseTranspilerPath}/typescript.js`).then(setLoadedFlag);
} else {
d.resolve();
}
return d.promise;
}
updateHtmlMode(value) {
// this.props.onCodeModeChange('html', value);
// this.props.currentItem.htmlMode = value;
@ -489,29 +446,7 @@ export default class ContentWrapFiles extends Component {
// this.cm,
// modes[value].cmPath || modes[value].cmMode
// );
// return this.handleModeRequirements(value);
}
updateCssMode(value) {
// this.props.onCodeModeChange('css', value);
// this.props.currentItem.cssMode = value;
this.cm.setOption('mode', modes[value].cmMode);
this.cm.setOption('readOnly', modes[value].cmDisable);
/* window.cssSettingsBtn.classList[
modes[value].hasSettings ? 'remove' : 'add'
]('hide'); */
CodeMirror.autoLoadMode(
this.cm,
modes[value].cmPath || modes[value].cmMode
);
return this.handleModeRequirements(value);
}
updateJsMode(value) {
this.cm.setOption('mode', modes[value].cmMode);
CodeMirror.autoLoadMode(
this.cm,
modes[value].cmPath || modes[value].cmMode
);
return this.handleModeRequirements(value);
// return handleModeRequirements(value);
}
getDemoFrame(callback) {
@ -727,8 +662,11 @@ export default class ContentWrapFiles extends Component {
id="demo-frame"
allowfullscreen
/>
<iframe src={`${PREVIEW_FRAME_HOST}/talk.html`} id="talkFrame" />
<PreviewDimension ref={comp => (this.previewDimension = comp)} />
<Console
logs={this.state.logs}
isConsoleOpen={this.state.isConsoleOpen}

View File

@ -1,5 +1,7 @@
import { h, Component } from 'preact';
import { Button } from './common';
import { Trans, t } from '@lingui/macro';
import { I18n } from '@lingui/react';
class JS13K extends Component {
constructor(props) {
@ -71,259 +73,265 @@ export default class Footer extends Component {
render() {
return (
<div id="footer" class="footer">
<div>
<a href="/" target="_blank" rel="noopener noreferrer">
<div class="logo" />
</a>
&copy;
<span class="web-maker-with-tag">Web Maker</span> &nbsp;&nbsp;
<Button
onClick={this.props.helpBtnClickHandler}
data-event-category="ui"
data-event-action="helpButtonClick"
class="footer__link hint--rounded hint--top-right"
aria-label="Help"
>
<svg
style="width:20px; height:20px; vertical-align:text-bottom"
viewBox="0 0 24 24"
>
<path d="M15.07,11.25L14.17,12.17C13.45,12.89 13,13.5 13,15H11V14.5C11,13.39 11.45,12.39 12.17,11.67L13.41,10.41C13.78,10.05 14,9.55 14,9C14,7.89 13.1,7 12,7A2,2 0 0,0 10,9H8A4,4 0 0,1 12,5A4,4 0 0,1 16,9C16,9.88 15.64,10.67 15.07,11.25M13,19H11V17H13M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,6.47 17.5,2 12,2Z" />
</svg>
</Button>
<Button
onClick={this.props.keyboardShortcutsBtnClickHandler}
data-event-category="ui"
data-event-action="keyboardShortcutButtonClick"
class="footer__link hint--rounded hint--top-right hide-on-mobile"
aria-label="Keyboard shortcuts"
>
<svg
style={{
width: '20px',
height: '20px',
verticalAlign: 'text-bottom'
}}
>
<use xlinkHref="#keyboard-icon" />
</svg>
</Button>
<a
class="footer__link hint--rounded hint--top-right"
aria-label="Tweet about 'Web Maker'"
href="http://twitter.com/share?url=https://webmaker.app/&text=Web Maker - A blazing fast %26 offline web playground! via @webmakerApp&related=webmakerApp&hashtags=web,frontend,playground,offline"
target="_blank"
rel="noopener noreferrer"
>
<svg
style={{
width: '20px',
height: '20px',
verticalAlign: 'text-bottom'
}}
>
<use xlinkHref="#twitter-icon" />
</svg>
</a>
<Button
onClick={this.props.supportDeveloperBtnClickHandler}
data-event-category="ui"
data-event-action="supportDeveloperFooterBtnClick"
class="footer__link ml-1 hint--rounded hint--top-right hide-on-mobile support-link"
aria-label="Support the developer by pledging some amount"
>
Donate
</Button>
</div>
<I18n>
{({ i18n }) => (
<div id="footer" class="footer">
<div>
<a href="/" target="_blank" rel="noopener noreferrer">
<div class="logo" />
</a>
&copy;
<span class="web-maker-with-tag">Web Maker</span> &nbsp;&nbsp;
<Button
onClick={this.props.helpBtnClickHandler}
data-event-category="ui"
data-event-action="helpButtonClick"
class="footer__link hint--rounded hint--top-right"
aria-label={i18n._(t`Help`)}
>
<svg
style="width:20px; height:20px; vertical-align:text-bottom"
viewBox="0 0 24 24"
>
<path d="M15.07,11.25L14.17,12.17C13.45,12.89 13,13.5 13,15H11V14.5C11,13.39 11.45,12.39 12.17,11.67L13.41,10.41C13.78,10.05 14,9.55 14,9C14,7.89 13.1,7 12,7A2,2 0 0,0 10,9H8A4,4 0 0,1 12,5A4,4 0 0,1 16,9C16,9.88 15.64,10.67 15.07,11.25M13,19H11V17H13M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,6.47 17.5,2 12,2Z" />
</svg>
</Button>
<Button
onClick={this.props.keyboardShortcutsBtnClickHandler}
data-event-category="ui"
data-event-action="keyboardShortcutButtonClick"
class="footer__link hint--rounded hint--top-right hide-on-mobile"
aria-label={i18n._(t`Keyboard shortcuts`)}
>
<svg
style={{
width: '20px',
height: '20px',
verticalAlign: 'text-bottom'
}}
>
<use xlinkHref="#keyboard-icon" />
</svg>
</Button>
<a
class="footer__link hint--rounded hint--top-right"
aria-label={i18n._(t`Tweet about 'Web Maker'`)}
href="http://twitter.com/share?url=https://webmaker.app/&text=Web Maker - A blazing fast %26 offline web playground! via @webmakerApp&related=webmakerApp&hashtags=web,frontend,playground,offline"
target="_blank"
rel="noopener noreferrer"
>
<svg
style={{
width: '20px',
height: '20px',
verticalAlign: 'text-bottom'
}}
>
<use xlinkHref="#twitter-icon" />
</svg>
</a>
<Button
onClick={this.props.supportDeveloperBtnClickHandler}
data-event-category="ui"
data-event-action="supportDeveloperFooterBtnClick"
class="footer__link ml-1 hint--rounded hint--top-right hide-on-mobile support-link"
aria-label={i18n._(
t`Support the developer by pledging some amount`
)}
>
<Trans>Donate</Trans>
</Button>
</div>
{this.props.prefs.isJs13kModeOn ? (
<div class="flex flex-v-center">
<JS13K
isOpen={this.state.isJs13kDropdownOpen}
codeSize={this.props.codeSize}
onClick={this.js13kClickHandler.bind(this)}
onBlur={() =>
setTimeout(
() => this.setState({ isJs13kDropdownOpen: false }),
300
)
}
/>
{this.state.isJs13kDropdownOpen && (
<div className="js13k__dropdown">
<button
class="btn"
style={{
width: '200px',
display: 'block',
marginBottom: '16px'
}}
onClick={this.props.onJs13KDownloadBtnClick}
>
Download game as zip
</button>
<a
class="btn"
rel="noopener"
style={{
width: '200px',
display: 'block',
marginBottom: '16px'
}}
href="https://pasteboard.co/"
target="_blank"
>
Upload Image
</a>
<button
class="btn"
style={{ width: '200px', display: 'block' }}
onClick={this.props.onJs13KHelpBtnClick}
>
Help
</button>
{this.props.prefs.isJs13kModeOn ? (
<div class="flex flex-v-center">
<JS13K
isOpen={this.state.isJs13kDropdownOpen}
codeSize={this.props.codeSize}
onClick={this.js13kClickHandler.bind(this)}
onBlur={() =>
setTimeout(
() => this.setState({ isJs13kDropdownOpen: false }),
300
)
}
/>
{this.state.isJs13kDropdownOpen && (
<div className="js13k__dropdown">
<button
class="btn"
style={{
width: '200px',
display: 'block',
marginBottom: '16px'
}}
onClick={this.props.onJs13KDownloadBtnClick}
>
<Trans>Download game as zip</Trans>
</button>
<a
class="btn"
rel="noopener"
style={{
width: '200px',
display: 'block',
marginBottom: '16px'
}}
href="https://pasteboard.co/"
target="_blank"
>
<Trans>Upload Image</Trans>
</a>
<button
class="btn"
style={{ width: '200px', display: 'block' }}
onClick={this.props.onJs13KHelpBtnClick}
>
<Trans>Help</Trans>
</button>
</div>
)}
</div>
)}
) : null}
<div class="footer__right">
<button
onClick={this.props.saveHtmlBtnClickHandler}
id="saveHtmlBtn"
class="mode-btn hint--rounded hint--top-left hide-on-mobile hide-in-file-mode"
aria-label={i18n._(t`Save as HTML file`)}
>
<svg viewBox="0 0 24 24">
<path d="M5,20H19V18H5M19,9H15V3H9V9H5L12,16L19,9Z" />
</svg>
</button>
<svg style="display: none;" xmlns="http://www.w3.org/2000/svg">
<symbol id="codepen-logo" viewBox="0 0 120 120">
<path
class="outer-ring"
d="M60.048 0C26.884 0 0 26.9 0 60.048s26.884 60 60 60.047c33.163 0 60.047-26.883 60.047-60.047 S93.211 0 60 0z M60.048 110.233c-27.673 0-50.186-22.514-50.186-50.186S32.375 9.9 60 9.9 c27.672 0 50.2 22.5 50.2 50.186S87.72 110.2 60 110.233z"
/>
<path
class="inner-box"
d="M97.147 48.319c-0.007-0.047-0.019-0.092-0.026-0.139c-0.016-0.09-0.032-0.18-0.056-0.268 c-0.014-0.053-0.033-0.104-0.05-0.154c-0.025-0.078-0.051-0.156-0.082-0.232c-0.021-0.053-0.047-0.105-0.071-0.156 c-0.033-0.072-0.068-0.143-0.108-0.211c-0.029-0.051-0.061-0.1-0.091-0.148c-0.043-0.066-0.087-0.131-0.135-0.193 c-0.035-0.047-0.072-0.094-0.109-0.139c-0.051-0.059-0.104-0.117-0.159-0.172c-0.042-0.043-0.083-0.086-0.127-0.125 c-0.059-0.053-0.119-0.104-0.181-0.152c-0.048-0.037-0.095-0.074-0.145-0.109c-0.019-0.012-0.035-0.027-0.053-0.039L61.817 23.5 c-1.072-0.715-2.468-0.715-3.54 0L24.34 46.081c-0.018 0.012-0.034 0.027-0.053 0.039c-0.05 0.035-0.097 0.072-0.144 0.1 c-0.062 0.049-0.123 0.1-0.181 0.152c-0.045 0.039-0.086 0.082-0.128 0.125c-0.056 0.055-0.108 0.113-0.158 0.2 c-0.038 0.045-0.075 0.092-0.11 0.139c-0.047 0.062-0.092 0.127-0.134 0.193c-0.032 0.049-0.062 0.098-0.092 0.1 c-0.039 0.068-0.074 0.139-0.108 0.211c-0.024 0.051-0.05 0.104-0.071 0.156c-0.031 0.076-0.057 0.154-0.082 0.2 c-0.017 0.051-0.035 0.102-0.05 0.154c-0.023 0.088-0.039 0.178-0.056 0.268c-0.008 0.047-0.02 0.092-0.025 0.1 c-0.019 0.137-0.029 0.275-0.029 0.416V71.36c0 0.1 0 0.3 0 0.418c0.006 0 0 0.1 0 0.1 c0.017 0.1 0 0.2 0.1 0.268c0.015 0.1 0 0.1 0.1 0.154c0.025 0.1 0.1 0.2 0.1 0.2 c0.021 0.1 0 0.1 0.1 0.154c0.034 0.1 0.1 0.1 0.1 0.213c0.029 0 0.1 0.1 0.1 0.1 c0.042 0.1 0.1 0.1 0.1 0.193c0.035 0 0.1 0.1 0.1 0.139c0.05 0.1 0.1 0.1 0.2 0.2 c0.042 0 0.1 0.1 0.1 0.125c0.058 0.1 0.1 0.1 0.2 0.152c0.047 0 0.1 0.1 0.1 0.1 c0.019 0 0 0 0.1 0.039L58.277 96.64c0.536 0.4 1.2 0.5 1.8 0.537c0.616 0 1.233-0.18 1.77-0.537 l33.938-22.625c0.018-0.012 0.034-0.027 0.053-0.039c0.05-0.035 0.097-0.072 0.145-0.109c0.062-0.049 0.122-0.1 0.181-0.152 c0.044-0.039 0.085-0.082 0.127-0.125c0.056-0.055 0.108-0.113 0.159-0.172c0.037-0.045 0.074-0.09 0.109-0.139 c0.048-0.062 0.092-0.127 0.135-0.193c0.03-0.049 0.062-0.098 0.091-0.146c0.04-0.07 0.075-0.141 0.108-0.213 c0.024-0.051 0.05-0.102 0.071-0.154c0.031-0.078 0.057-0.156 0.082-0.234c0.017-0.051 0.036-0.102 0.05-0.154 c0.023-0.088 0.04-0.178 0.056-0.268c0.008-0.045 0.02-0.092 0.026-0.137c0.018-0.139 0.028-0.277 0.028-0.418V48.735 C97.176 48.6 97.2 48.5 97.1 48.319z M63.238 32.073l25.001 16.666L77.072 56.21l-13.834-9.254V32.073z M56.856 32.1 v14.883L43.023 56.21l-11.168-7.471L56.856 32.073z M29.301 54.708l7.983 5.34l-7.983 5.34V54.708z M56.856 88.022L31.855 71.4 l11.168-7.469l13.833 9.252V88.022z M60.048 67.597l-11.286-7.549l11.286-7.549l11.285 7.549L60.048 67.597z M63.238 88.022V73.14 l13.834-9.252l11.167 7.469L63.238 88.022z M90.794 65.388l-7.982-5.34l7.982-5.34V65.388z"
/>
</symbol>
</svg>
<button
onClick={this.props.codepenBtnClickHandler}
id="codepenBtn"
class="mode-btn hint--rounded hint--top-left hide-on-mobile hide-in-file-mode"
aria-label={i18n._(t`Edit on CodePen`)}
>
<svg>
<use xlinkHref="#codepen-logo" />
</svg>
</button>
<button
id="screenshotBtn"
class="mode-btn hint--rounded hint--top-left show-when-extension"
onClick={this.props.screenshotBtnClickHandler}
aria-label={i18n._(t`Take screenshot of preview`)}
>
<svg style="width:24px;height:24px" viewBox="0 0 24 24">
<path d="M4,4H7L9,2H15L17,4H20A2,2 0 0,1 22,6V18A2,2 0 0,1 20,20H4A2,2 0 0,1 2,18V6A2,2 0 0,1 4,4M12,7A5,5 0 0,0 7,12A5,5 0 0,0 12,17A5,5 0 0,0 17,12A5,5 0 0,0 12,7M12,9A3,3 0 0,1 15,12A3,3 0 0,1 12,15A3,3 0 0,1 9,12A3,3 0 0,1 12,9Z" />
</svg>
</button>
<div class="footer__separator hide-on-mobile" />
<button
onClick={this.layoutBtnClickhandler.bind(this, 1)}
id="layoutBtn1"
class="mode-btn hide-on-mobile hide-in-file-mode"
aria-label={i18n._(t`Switch to layout with preview on right`)}
>
<svg viewBox="0 0 100 100" style="transform:rotate(-90deg)">
<use xlinkHref="#mode-icon" />
</svg>
</button>
<button
onClick={this.layoutBtnClickhandler.bind(this, 2)}
id="layoutBtn2"
class="mode-btn hide-on-mobile hide-in-file-mode"
aria-label={i18n._(t`Switch to layout with preview on bottom`)}
>
<svg viewBox="0 0 100 100">
<use xlinkHref="#mode-icon" />
</svg>
</button>
<button
onClick={this.layoutBtnClickhandler.bind(this, 3)}
id="layoutBtn3"
class="mode-btn hide-on-mobile hide-in-file-mode"
aria-label={i18n._(t`Switch to layout with preview on left`)}
>
<svg viewBox="0 0 100 100" style="transform:rotate(90deg)">
<use xlinkHref="#mode-icon" />
</svg>
</button>
<button
onClick={this.layoutBtnClickhandler.bind(this, 5)}
id="layoutBtn5"
class="mode-btn hide-on-mobile hide-in-file-mode"
aria-label={i18n._(t`Switch to layout with all vertical panes`)}
>
<svg viewBox="0 0 100 100">
<use xlinkHref="#vertical-mode-icon" />
</svg>
</button>
<button
onClick={this.layoutBtnClickhandler.bind(this, 4)}
id="layoutBtn4"
class="mode-btn hint--top-left hint--rounded hide-on-mobile"
aria-label={i18n._(t`Toggle full screen preview`)}
>
<svg viewBox="0 0 100 100">
<rect x="0" y="0" width="100" height="100" />
</svg>
</button>
<button
class="mode-btn hint--top-left hint--rounded hide-on-mobile"
aria-label={i18n._(t`Detach preview`)}
onClick={this.props.detachedPreviewBtnHandler}
>
<svg viewBox="0 0 24 24">
<path d="M22,17V7H6V17H22M22,5A2,2 0 0,1 24,7V17C24,18.11 23.1,19 22,19H16V21H18V23H10V21H12V19H6C4.89,19 4,18.11 4,17V7A2,2 0 0,1 6,5H22M2,3V15H0V3A2,2 0 0,1 2,1H20V3H2Z" />
</svg>
</button>
<div class="footer__separator" />
<button
onClick={this.props.notificationsBtnClickHandler}
id="notificationsBtn"
class={`notifications-btn mode-btn hint--top-left hint--rounded ${
this.props.hasUnseenChangelog ? 'has-new' : ''
}`}
aria-label={i18n._(t`See changelog`)}
>
<svg viewBox="0 0 24 24">
<path d="M14,20A2,2 0 0,1 12,22A2,2 0 0,1 10,20H14M12,2A1,1 0 0,1 13,3V4.08C15.84,4.56 18,7.03 18,10V16L21,19H3L6,16V10C6,7.03 8.16,4.56 11,4.08V3A1,1 0 0,1 12,2Z" />
</svg>
<span class="notifications-btn__dot" />
</button>
<Button
onClick={this.props.settingsBtnClickHandler}
data-event-category="ui"
data-event-action="settingsBtnClick"
class="mode-btn hint--top-left hint--rounded"
aria-label={i18n._(t`Settings`)}
>
<svg>
<use xlinkHref="#settings-icon" />
</svg>
</Button>
</div>
</div>
) : null}
<div class="footer__right">
<button
onClick={this.props.saveHtmlBtnClickHandler}
id="saveHtmlBtn"
class="mode-btn hint--rounded hint--top-left hide-on-mobile hide-in-file-mode"
aria-label="Save as HTML file"
>
<svg viewBox="0 0 24 24">
<path d="M5,20H19V18H5M19,9H15V3H9V9H5L12,16L19,9Z" />
</svg>
</button>
<svg style="display: none;" xmlns="http://www.w3.org/2000/svg">
<symbol id="codepen-logo" viewBox="0 0 120 120">
<path
class="outer-ring"
d="M60.048 0C26.884 0 0 26.9 0 60.048s26.884 60 60 60.047c33.163 0 60.047-26.883 60.047-60.047 S93.211 0 60 0z M60.048 110.233c-27.673 0-50.186-22.514-50.186-50.186S32.375 9.9 60 9.9 c27.672 0 50.2 22.5 50.2 50.186S87.72 110.2 60 110.233z"
/>
<path
class="inner-box"
d="M97.147 48.319c-0.007-0.047-0.019-0.092-0.026-0.139c-0.016-0.09-0.032-0.18-0.056-0.268 c-0.014-0.053-0.033-0.104-0.05-0.154c-0.025-0.078-0.051-0.156-0.082-0.232c-0.021-0.053-0.047-0.105-0.071-0.156 c-0.033-0.072-0.068-0.143-0.108-0.211c-0.029-0.051-0.061-0.1-0.091-0.148c-0.043-0.066-0.087-0.131-0.135-0.193 c-0.035-0.047-0.072-0.094-0.109-0.139c-0.051-0.059-0.104-0.117-0.159-0.172c-0.042-0.043-0.083-0.086-0.127-0.125 c-0.059-0.053-0.119-0.104-0.181-0.152c-0.048-0.037-0.095-0.074-0.145-0.109c-0.019-0.012-0.035-0.027-0.053-0.039L61.817 23.5 c-1.072-0.715-2.468-0.715-3.54 0L24.34 46.081c-0.018 0.012-0.034 0.027-0.053 0.039c-0.05 0.035-0.097 0.072-0.144 0.1 c-0.062 0.049-0.123 0.1-0.181 0.152c-0.045 0.039-0.086 0.082-0.128 0.125c-0.056 0.055-0.108 0.113-0.158 0.2 c-0.038 0.045-0.075 0.092-0.11 0.139c-0.047 0.062-0.092 0.127-0.134 0.193c-0.032 0.049-0.062 0.098-0.092 0.1 c-0.039 0.068-0.074 0.139-0.108 0.211c-0.024 0.051-0.05 0.104-0.071 0.156c-0.031 0.076-0.057 0.154-0.082 0.2 c-0.017 0.051-0.035 0.102-0.05 0.154c-0.023 0.088-0.039 0.178-0.056 0.268c-0.008 0.047-0.02 0.092-0.025 0.1 c-0.019 0.137-0.029 0.275-0.029 0.416V71.36c0 0.1 0 0.3 0 0.418c0.006 0 0 0.1 0 0.1 c0.017 0.1 0 0.2 0.1 0.268c0.015 0.1 0 0.1 0.1 0.154c0.025 0.1 0.1 0.2 0.1 0.2 c0.021 0.1 0 0.1 0.1 0.154c0.034 0.1 0.1 0.1 0.1 0.213c0.029 0 0.1 0.1 0.1 0.1 c0.042 0.1 0.1 0.1 0.1 0.193c0.035 0 0.1 0.1 0.1 0.139c0.05 0.1 0.1 0.1 0.2 0.2 c0.042 0 0.1 0.1 0.1 0.125c0.058 0.1 0.1 0.1 0.2 0.152c0.047 0 0.1 0.1 0.1 0.1 c0.019 0 0 0 0.1 0.039L58.277 96.64c0.536 0.4 1.2 0.5 1.8 0.537c0.616 0 1.233-0.18 1.77-0.537 l33.938-22.625c0.018-0.012 0.034-0.027 0.053-0.039c0.05-0.035 0.097-0.072 0.145-0.109c0.062-0.049 0.122-0.1 0.181-0.152 c0.044-0.039 0.085-0.082 0.127-0.125c0.056-0.055 0.108-0.113 0.159-0.172c0.037-0.045 0.074-0.09 0.109-0.139 c0.048-0.062 0.092-0.127 0.135-0.193c0.03-0.049 0.062-0.098 0.091-0.146c0.04-0.07 0.075-0.141 0.108-0.213 c0.024-0.051 0.05-0.102 0.071-0.154c0.031-0.078 0.057-0.156 0.082-0.234c0.017-0.051 0.036-0.102 0.05-0.154 c0.023-0.088 0.04-0.178 0.056-0.268c0.008-0.045 0.02-0.092 0.026-0.137c0.018-0.139 0.028-0.277 0.028-0.418V48.735 C97.176 48.6 97.2 48.5 97.1 48.319z M63.238 32.073l25.001 16.666L77.072 56.21l-13.834-9.254V32.073z M56.856 32.1 v14.883L43.023 56.21l-11.168-7.471L56.856 32.073z M29.301 54.708l7.983 5.34l-7.983 5.34V54.708z M56.856 88.022L31.855 71.4 l11.168-7.469l13.833 9.252V88.022z M60.048 67.597l-11.286-7.549l11.286-7.549l11.285 7.549L60.048 67.597z M63.238 88.022V73.14 l13.834-9.252l11.167 7.469L63.238 88.022z M90.794 65.388l-7.982-5.34l7.982-5.34V65.388z"
/>
</symbol>
</svg>
<button
onClick={this.props.codepenBtnClickHandler}
id="codepenBtn"
class="mode-btn hint--rounded hint--top-left hide-on-mobile hide-in-file-mode"
aria-label="Edit on CodePen"
>
<svg>
<use xlinkHref="#codepen-logo" />
</svg>
</button>
<button
id="screenshotBtn"
class="mode-btn hint--rounded hint--top-left show-when-extension"
onClick={this.props.screenshotBtnClickHandler}
aria-label="Take screenshot of preview"
>
<svg style="width:24px;height:24px" viewBox="0 0 24 24">
<path d="M4,4H7L9,2H15L17,4H20A2,2 0 0,1 22,6V18A2,2 0 0,1 20,20H4A2,2 0 0,1 2,18V6A2,2 0 0,1 4,4M12,7A5,5 0 0,0 7,12A5,5 0 0,0 12,17A5,5 0 0,0 17,12A5,5 0 0,0 12,7M12,9A3,3 0 0,1 15,12A3,3 0 0,1 12,15A3,3 0 0,1 9,12A3,3 0 0,1 12,9Z" />
</svg>
</button>
<div class="footer__separator hide-on-mobile" />
<button
onClick={this.layoutBtnClickhandler.bind(this, 1)}
id="layoutBtn1"
class="mode-btn hide-on-mobile hide-in-file-mode"
aria-label="Switch to layout with preview on right"
>
<svg viewBox="0 0 100 100" style="transform:rotate(-90deg)">
<use xlinkHref="#mode-icon" />
</svg>
</button>
<button
onClick={this.layoutBtnClickhandler.bind(this, 2)}
id="layoutBtn2"
class="mode-btn hide-on-mobile hide-in-file-mode"
aria-label="Switch to layout with preview on bottom"
>
<svg viewBox="0 0 100 100">
<use xlinkHref="#mode-icon" />
</svg>
</button>
<button
onClick={this.layoutBtnClickhandler.bind(this, 3)}
id="layoutBtn3"
class="mode-btn hide-on-mobile hide-in-file-mode"
aria-label="Switch to layout with preview on left"
>
<svg viewBox="0 0 100 100" style="transform:rotate(90deg)">
<use xlinkHref="#mode-icon" />
</svg>
</button>
<button
onClick={this.layoutBtnClickhandler.bind(this, 5)}
id="layoutBtn5"
class="mode-btn hide-on-mobile hide-in-file-mode"
aria-label="Switch to layout with all vertical panes"
>
<svg viewBox="0 0 100 100">
<use xlinkHref="#vertical-mode-icon" />
</svg>
</button>
<button
onClick={this.layoutBtnClickhandler.bind(this, 4)}
id="layoutBtn4"
class="mode-btn hint--top-left hint--rounded hide-in-file-mode hide-on-mobile"
aria-label="Switch to full screen preview"
>
<svg viewBox="0 0 100 100">
<rect x="0" y="0" width="100" height="100" />
</svg>
</button>
<button
class="mode-btn hint--top-left hint--rounded hide-on-mobile"
aria-label="Detach Preview"
onClick={this.props.detachedPreviewBtnHandler}
>
<svg viewBox="0 0 24 24">
<path d="M22,17V7H6V17H22M22,5A2,2 0 0,1 24,7V17C24,18.11 23.1,19 22,19H16V21H18V23H10V21H12V19H6C4.89,19 4,18.11 4,17V7A2,2 0 0,1 6,5H22M2,3V15H0V3A2,2 0 0,1 2,1H20V3H2Z" />
</svg>
</button>
<div class="footer__separator" />
<button
onClick={this.props.notificationsBtnClickHandler}
id="notificationsBtn"
class={`notifications-btn mode-btn hint--top-left hint--rounded ${
this.props.hasUnseenChangelog ? 'has-new' : ''
}`}
aria-label="See Changelog"
>
<svg viewBox="0 0 24 24">
<path d="M14,20A2,2 0 0,1 12,22A2,2 0 0,1 10,20H14M12,2A1,1 0 0,1 13,3V4.08C15.84,4.56 18,7.03 18,10V16L21,19H3L6,16V10C6,7.03 8.16,4.56 11,4.08V3A1,1 0 0,1 12,2Z" />
</svg>
<span class="notifications-btn__dot" />
</button>
<Button
onClick={this.props.settingsBtnClickHandler}
data-event-category="ui"
data-event-action="settingsBtnClick"
class="mode-btn hint--top-left hint--rounded"
aria-label="Settings"
>
<svg>
<use xlinkHref="#settings-icon" />
</svg>
</Button>
</div>
</div>
)}
</I18n>
);
}
}

View File

@ -1,6 +1,7 @@
import { h } from 'preact';
import Modal from './Modal';
import { Button } from './common';
import { Trans } from '@lingui/macro';
export function HelpModal(props) {
return (
@ -12,47 +13,51 @@ export function HelpModal(props) {
<div>
<p>
Made with <span style="margin-right: 8px;">💖</span>&{' '}
<span style="margin-right: 8px;"> 🙌</span> by{' '}
<a
href="https://twitter.com/chinchang457"
target="_blank"
rel="noopener noreferrer"
>
Kushagra Gour
<Trans>
Made with <span style="margin-right: 8px;">💖</span>&{' '}
<span style="margin-right: 8px;"> 🙌</span> by{' '}
<a
href="https://twitter.com/chinchang457"
target="_blank"
rel="noopener noreferrer"
>
Kushagra Gour
</a>
</Trans>
</p>
<p>
<a href="/docs" target="_blank" rel="noopener noreferrer">
<Trans>Read the documentation.</Trans>
</a>
</p>
<p>
<a href="https://webmaker.app/docs" target="_blank" rel="noopener noreferrer">
Read the documentation
</a>
.
</p>
<p>
Tweet out your feature requests, comments & suggestions to{' '}
<a
target="_blank"
rel="noopener noreferrer"
href="https://twitter.com/webmakerApp"
>
@webmakerApp
</a>
<Trans>
Tweet out your feature requests, comments & suggestions to{' '}
<a
target="_blank"
rel="noopener noreferrer"
href="https://twitter.com/webmakerApp"
>
@webmakerApp
</a>
</Trans>
.
</p>
<p class="show-when-extension">
Like this extension? Please{' '}
<a
href="https://chrome.google.com/webstore/detail/web-maker/lkfkkhfhhdkiemehlpkgjeojomhpccnh/reviews"
target="_blank"
rel="noopener noreferrer"
>
rate it here
</a>
.
<Trans>
Like this extension? Please{' '}
<a
href="https://chrome.google.com/webstore/detail/web-maker/lkfkkhfhhdkiemehlpkgjeojomhpccnh/reviews"
target="_blank"
rel="noopener noreferrer"
>
rate it here
</a>
.
</Trans>
</p>
<p>
<Button
aria-label="Support the developer"
onClick={props.onSupportBtnClick}
data-event-action="supportDeveloperHelpBtnClick"
data-event-category="ui"
@ -61,10 +66,9 @@ export function HelpModal(props) {
<svg>
<use xlinkHref="#gift-icon" />
</svg>
Support the developer
<Trans>Support the developer</Trans>
</Button>{' '}
<a
aria-label="Rate Web Maker"
href="https://chrome.google.com/webstore/detail/web-maker/lkfkkhfhhdkiemehlpkgjeojomhpccnh/reviews"
target="_blank"
rel="noopener noreferrer"
@ -73,10 +77,9 @@ export function HelpModal(props) {
<svg>
<use xlinkHref="#heart-icon" />
</svg>
Review Web Maker
<Trans>Review Web Maker</Trans>
</a>{' '}
<a
aria-label="Chat"
href="https://spectrum.chat/web-maker"
target="_blank"
rel="noopener noreferrer"
@ -85,10 +88,9 @@ export function HelpModal(props) {
<svg>
<use xlinkHref="#chat-icon" />
</svg>
Chat
<Trans>Chat</Trans>
</a>{' '}
<a
aria-label="Report a Bug"
href="https://github.com/chinchang/web-maker/issues"
target="_blank"
rel="noopener noreferrer"
@ -97,14 +99,16 @@ export function HelpModal(props) {
<svg>
<use xlinkHref="#bug-icon" />
</svg>
Report a bug
<Trans>Report a bug</Trans>
</a>
</p>
<p>
<details>
<summary>
<h3 class="d-i">See awesome libraries used</h3>
<h3 class="d-i">
<Trans>See awesome libraries used</Trans>
</h3>
</summary>
<ul>
<li>
@ -187,24 +191,27 @@ export function HelpModal(props) {
</p>
<p>
<h3>License</h3>
"Web Maker" is{' '}
<a
target="_blank"
rel="noopener noreferrer"
href="https://github.com/chinchang/web-maker"
>
open-source
</a>{' '}
under the{' '}
<a
href="https://opensource.org/licenses/MIT"
target="_blank"
rel="noopener noreferrer"
>
MIT License
</a>
.
<h3>
<Trans>License</Trans>
</h3>
<Trans>
"Web Maker" is{' '}
<a
target="_blank"
rel="noopener noreferrer"
href="https://github.com/chinchang/web-maker"
>
open-source
</a>{' '}
under the{' '}
<a
href="https://opensource.org/licenses/MIT"
target="_blank"
rel="noopener noreferrer"
>
MIT License
</a>
</Trans>
</p>
</div>
</Modal>

View File

@ -22,22 +22,22 @@ export function ItemTile({
>
<div class="saved-item-tile__btns">
{onForkBtnClick ? (
<a
<button
class="js-saved-item-tile__fork-btn saved-item-tile__btn hint--left hint--medium"
aria-label="Creates a duplicate of this creation (Ctrl/⌘ + F)"
onClick={onForkBtnClick}
>
Fork<span class="show-when-selected">(Ctrl/ + F)</span>
</a>
</button>
) : null}
{onRemoveBtnClick ? (
<a
<button
class="js-saved-item-tile__remove-btn saved-item-tile__btn hint--left"
aria-label="Remove"
onClick={onRemoveBtnClick}
>
X
</a>
</button>
) : null}
</div>
<div className="flex flex-v-center">

View File

@ -1,95 +1,124 @@
import { h } from 'preact';
import Modal from './Modal';
import { Trans } from '@lingui/macro';
export function KeyboardShortcutsModal({ show, closeHandler }) {
return (
<Modal show={show} closeHandler={closeHandler}>
<h1>Keyboard Shortcuts</h1>
<h1>
<Trans>Keyboard Shortcuts</Trans>
</h1>
<div class="flex">
<div>
<h2>Global</h2>
<h2>
<Trans>Global</Trans>
</h2>
{/*<p>
<span class="kbd-shortcut__keys">Ctrl/ + Shift + ?</span>
<span class="kbd-shortcut__details">See keyboard shortcuts</span>
</p>*/}
<p>
<span class="kbd-shortcut__keys">Ctrl/ + Shift + 5</span>
<span class="kbd-shortcut__details">Refresh preview</span>
<span class="kbd-shortcut__details">
<Trans>Refresh preview</Trans>
</span>
</p>
<p>
<span class="kbd-shortcut__keys">Ctrl/ + S</span>
<span class="kbd-shortcut__details">Save current creations</span>
<span class="kbd-shortcut__details">
<Trans>Save current creations</Trans>
</span>
</p>
<p>
<span class="kbd-shortcut__keys">Ctrl/ + O</span>
<span class="kbd-shortcut__details">
Open list of saved creations
<Trans>Open list of saved creations</Trans>
</span>
</p>
<p>
<span class="kbd-shortcut__keys">Ctrl + L</span>
<span class="kbd-shortcut__details">
Clear console (works when console input is focused)
<Trans>Clear console (works when console input is focused)</Trans>
</span>
</p>
<p>
<span class="kbd-shortcut__keys">Esc</span>
<span class="kbd-shortcut__details">
Close saved creations panel & modals
<Trans>Close saved creations panel & modals</Trans>
</span>
</p>
</div>
<div class="ml-2">
<h2>Editor</h2>
<h2>
<Trans>Editor</Trans>
</h2>
<p>
<span class="kbd-shortcut__keys">Ctrl/ + F</span>
<span class="kbd-shortcut__details">Find</span>
<span class="kbd-shortcut__details">
<Trans>Find</Trans>
</span>
</p>
<p>
<span class="kbd-shortcut__keys">Ctrl/ + G</span>
<span class="kbd-shortcut__details">Select next match</span>
<span class="kbd-shortcut__details">
<Trans>Select next match</Trans>
</span>
</p>
<p>
<span class="kbd-shortcut__keys">Ctrl/ + Shift + G</span>
<span class="kbd-shortcut__details">Select previous match</span>
<span class="kbd-shortcut__details">
<Trans>Select previous match</Trans>
</span>
</p>
<p>
<span class="kbd-shortcut__keys">Ctrl/ + Opt/Alt + F</span>
<span class="kbd-shortcut__details">Find & replace</span>
<span class="kbd-shortcut__details">
<Trans>Find & replace</Trans>
</span>
</p>
<p>
<span class="kbd-shortcut__keys">Shift + Tab</span>
<span class="kbd-shortcut__details">Realign code</span>
<span class="kbd-shortcut__details">
<Trans>Realign code</Trans>
</span>
</p>
<p>
<span class="kbd-shortcut__keys">Ctrl/ + ]</span>
<span class="kbd-shortcut__details">Indent code right</span>
<span class="kbd-shortcut__details">
<Trans>Indent code right</Trans>
</span>
</p>
<p>
<span class="kbd-shortcut__keys">Ctrl/ + [</span>
<span class="kbd-shortcut__details">Indent code left</span>
<span class="kbd-shortcut__details">
<Trans>Indent code left</Trans>
</span>
</p>
<p>
<span class="kbd-shortcut__keys">Tab</span>
<span class="kbd-shortcut__details">
Emmet code completion{' '}
<Trans>Emmet code completion</Trans>{' '}
<a
href="https://emmet.io/"
target="_blank"
rel="noopener noreferrer"
>
Read more
<Trans>Read more</Trans>
</a>
</span>
</p>
<p>
<span class="kbd-shortcut__keys">Ctrl/ + /</span>
<span class="kbd-shortcut__details">Single line comment</span>
<span class="kbd-shortcut__details">
<Trans>Single line comment</Trans>
</span>
</p>
<p>
<span class="kbd-shortcut__keys">Ctrl + Shift + F</span>
<span class="kbd-shortcut__details">Run Prettier</span>
<span class="kbd-shortcut__details">
<Trans>Run Prettier</Trans>
</span>
</p>
</div>
</div>

View File

@ -36,7 +36,8 @@ export default class Login extends Component {
>
<svg>
<use xlinkHref="#github-icon" />
</svg>Login with Github
</svg>
Login with Github
</button>
</p>
<p>
@ -49,7 +50,8 @@ export default class Login extends Component {
>
<svg>
<use xlinkHref="#google-icon" />
</svg>Login with Google
</svg>
Login with Google
</button>
</p>
<p class="mb-2">
@ -62,7 +64,8 @@ export default class Login extends Component {
>
<svg>
<use xlinkHref="#fb-icon" />
</svg>Login with Facebook
</svg>
Login with Facebook (deprecated)
</button>
</p>
<p>Join a community of 50,000+ Developers</p>

View File

@ -1,12 +1,17 @@
import { h } from 'preact';
import { Button } from './common';
import { Trans, t } from '@lingui/macro';
import { Trans, NumberFormat, t } from '@lingui/macro';
import { I18n } from '@lingui/react';
const DEFAULT_PROFILE_IMG =
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23ccc' d='M12,19.2C9.5,19.2 7.29,17.92 6,16C6.03,14 10,12.9 12,12.9C14,12.9 17.97,14 18,16C16.71,17.92 14.5,19.2 12,19.2M12,5A3,3 0 0,1 15,8A3,3 0 0,1 12,11A3,3 0 0,1 9,8A3,3 0 0,1 12,5M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,6.47 17.5,2 12,2Z'/%3E%3C/svg%3E";
export function MainHeader(props) {
const isAutoPreviewOn =
window.forcedSettings.autoPreview !== undefined
? window.forcedSettings
: props.isAutoPreviewOn;
return (
<I18n>
{({ i18n }) => (
@ -20,19 +25,20 @@ export function MainHeader(props) {
onBlur={props.titleInputBlurHandler}
/>
<div class="main-header__btn-wrap flex flex-v-center">
<button
id="runBtn"
class="hide btn btn btn--dark flex flex-v-center hint--rounded hint--bottom-left"
aria-label="Run preview (Ctrl/⌘ + Shift + 5)"
onClick={props.runBtnClickHandler}
>
<svg>
<use xlinkHref="#play-icon" />
</svg>
<Trans>Run</Trans>
</button>
{!isAutoPreviewOn && (
<button
class="btn btn btn--dark flex flex-v-center hint--rounded hint--bottom-left"
aria-label={i18n._(t`Run preview (Ctrl/⌘ + Shift + 5)`)}
onClick={props.runBtnClickHandler}
>
<svg>
<use xlinkHref="#play-icon" />
</svg>
<Trans>Run</Trans>
</button>
)}
{!this.props.isFileMode && (
{!props.isFileMode && (
<Button
onClick={props.addLibraryBtnHandler}
data-event-category="ui"
@ -48,14 +54,14 @@ export function MainHeader(props) {
}`}
class="count-label"
>
{props.externalLibCount}
<NumberFormat value={props.externalLibCount} />
</span>
</Button>
)}
<button
class="btn btn--dark hint--rounded hint--bottom-left"
aria-label="Start a new creation"
aria-label={i18n._(t`Start a new creation`)}
onClick={props.newBtnHandler}
>
<svg viewBox="0 0 24 24">
@ -68,7 +74,7 @@ export function MainHeader(props) {
class={`btn btn--dark hint--rounded hint--bottom-left ${
props.isSaving ? 'is-loading' : ''
} ${props.unsavedEditCount ? 'is-marked' : 0}`}
aria-label="Save current creation (Ctrl/⌘ + S)"
aria-label={i18n._(t`Save current creation (Ctrl/⌘ + S)`)}
onClick={props.saveBtnHandler}
>
<svg viewBox="0 0 24 24">
@ -84,7 +90,7 @@ export function MainHeader(props) {
class={`btn btn--dark hint--rounded hint--bottom-left ${
props.isFetchingItems ? 'is-loading' : ''
}`}
aria-label="Open a saved creation (Ctrl/⌘ + O)"
aria-label={i18n._(t`Open a saved creation (Ctrl/⌘ + O)`)}
onClick={props.openBtnHandler}
>
<svg viewBox="0 0 24 24">
@ -95,31 +101,33 @@ export function MainHeader(props) {
</svg>
<Trans>Open</Trans>
</button>
<Button
onClick={props.loginBtnHandler}
data-event-category="ui"
data-event-action="loginButtonClick"
class="hide-on-login btn btn--dark hint--rounded hint--bottom-left"
aria-label="Login/Signup"
>
<Trans>Login</Trans>/<Trans>Signup</Trans>
</Button>
<Button
onClick={props.profileBtnHandler}
data-event-category="ui"
data-event-action="headerAvatarClick"
aria-label="See profile or Logout"
class="hide-on-logout btn--dark hint--rounded hint--bottom-left"
>
<img
id="headerAvatarImg"
width="20"
src={
props.user ? props.user.photoURL || DEFAULT_PROFILE_IMG : ''
}
class="main-header__avatar-img"
/>
</Button>
{!props.user ? (
<Button
onClick={props.loginBtnHandler}
data-event-category="ui"
data-event-action="loginButtonClick"
class="btn btn--dark hint--rounded hint--bottom-left"
>
<Trans>Login/Signup</Trans>
</Button>
) : (
<Button
onClick={props.profileBtnHandler}
data-event-category="ui"
data-event-action="headerAvatarClick"
aria-label={i18n._(t`See profile or Logout`)}
class="btn--dark hint--rounded hint--bottom-left"
>
<img
id="headerAvatarImg"
width="20"
src={
props.user ? props.user.photoURL || DEFAULT_PROFILE_IMG : ''
}
class="main-header__avatar-img"
/>
</Button>
)}
</div>
</div>
)}

View File

@ -1,91 +1,108 @@
import { h, Component } from 'preact';
import Portal from 'preact-portal';
import { h } from 'preact';
import { createPortal, useEffect, useRef } from 'preact/compat';
export default class Modal extends Component {
componentDidMount() {
window.addEventListener('keydown', this.onKeyDownHandler.bind(this));
}
componentWillUnmount() {
window.removeEventListener('keydown', this.onKeyDownHandler.bind(this));
if (this.focusGrabber) {
this.focusGrabber.remove();
this.focusGrabber = null;
}
}
onKeyDownHandler(e) {
const Portal = ({ children, into }) => {
const container = document.querySelector(into);
return createPortal(children, container);
};
const Modal = ({
show,
extraClasses,
small,
hideCloseButton,
closeHandler,
noOverlay,
children
}) => {
const focusGrabberRef = useRef();
const overlayRef = useRef();
const onKeyDownHandler = e => {
if (e.keyCode === 27) {
this.props.closeHandler();
closeHandler();
}
}
onOverlayClick(e) {
if (e.target === this.overlayEl) {
this.props.closeHandler();
};
const onOverlayClick = e => {
if (e.target === overlayRef.current) {
closeHandler();
}
}
componentDidUpdate(prevProps) {
if (this.props.show !== prevProps.show) {
if (!this.props.noOverlay) {
document.body.classList[this.props.show ? 'add' : 'remove'](
'overlay-visible'
);
};
useEffect(() => {
window.addEventListener('keydown', onKeyDownHandler);
return () => {
window.removeEventListener('keydown', onKeyDownHandler.bind(this));
if (focusGrabberRef.current) {
focusGrabberRef.current.remove();
focusGrabberRef.current = null;
}
if (this.props.show) {
// HACK: refs will evaluate on next tick due to portals
setTimeout(() => {
const closeButton = this.overlayEl.querySelector(
'.js-modal__close-btn'
);
if (closeButton) {
closeButton.focus();
}
}, 0);
};
}, []);
/* We insert a dummy hidden input which will take focus as soon as focus
escapes the modal, instead of focus going outside modal because modal
is last focusable element. */
this.focusGrabber = document.createElement('input');
this.focusGrabber.setAttribute(
'style',
'height:0;opacity:0;overflow:hidden;width:0;'
useEffect(() => {
if (!noOverlay) {
document.body.classList[show ? 'add' : 'remove']('overlay-visible');
}
if (show) {
// HACK: refs will evaluate on next tick due to portals
setTimeout(() => {
const closeButton = overlayRef.current.querySelector(
'.js-modal__close-btn'
);
setTimeout(() => {
document.body.appendChild(this.focusGrabber);
}, 10);
} else {
this.focusGrabber.remove();
this.focusGrabber = null;
if (closeButton) {
closeButton.focus();
}
}, 0);
/* We insert a dummy hidden input which will take focus as soon as focus
* escapes the modal, instead of focus going outside modal because modal
* is last focusable element.
*/
focusGrabberRef.current = document.createElement('input');
focusGrabberRef.current.setAttribute(
'style',
'height:0;opacity:0;overflow:hidden;width:0;'
);
setTimeout(() => {
document.body.appendChild(focusGrabberRef.current);
}, 10);
} else {
if (focusGrabberRef.current) {
focusGrabberRef.current.remove();
focusGrabberRef.current = null;
}
}
}
render() {
if (!this.props.show) return null;
}, [show]);
return (
<Portal into="body">
<div
role="dialog"
class={`${this.props.extraClasses || ''} modal is-modal-visible ${
this.props.small ? 'modal--small' : ''
}`}
ref={el => (this.overlayEl = el)}
onClick={this.onOverlayClick.bind(this)}
>
<div class="modal__content">
{this.props.hideCloseButton ? null : (
<button
type="button"
onClick={this.props.closeHandler}
aria-label="Close modal"
title="Close"
class="js-modal__close-btn modal__close-btn"
>
Close
</button>
)}
{this.props.children}
</div>
if (!show) return null;
return (
<Portal into={`body`}>
<div
role="dialog"
class={`${extraClasses || ''} modal is-modal-visible ${
small ? 'modal--small' : ''
}`}
ref={overlayRef}
onClick={onOverlayClick}
>
<div class="modal__content">
{hideCloseButton ? null : (
<button
type="button"
onClick={closeHandler}
aria-label="Close modal"
title="Close"
class="js-modal__close-btn modal__close-btn"
>
Close
</button>
)}
{children}
</div>
</Portal>
);
}
}
</div>
</Portal>
);
};
export default Modal;

View File

@ -114,6 +114,23 @@ export function Notifications(props) {
return (
<div>
<h1>Whats new?</h1>
<Notification version="5.0.0" {...props} isLatest={true}>
<li>
<strong>We are Back! 😎</strong>: After almost 2 years of nothing
being shipped, we are back in action. That too with a bang! We have a
small team of amazing developers working on Web Maker now. So expect
some crazy useful features coming soon!
</li>
<NotificationItem type="ui">
First up, is local language support! We have added Hindi and Spanish
to start with! Thanks{' '}
<ThanksTo
url="https://github.com/leninalbertolp"
name="@leninalbertolp"
/>{' '}
for the Spanish translation. It was long due!
</NotificationItem>
</Notification>
<Notification version="4.2.0" {...props} isLatest={true}>
<li>
Tailwind CSS now added to popular libraries list. Thanks

71
src/components/Portal.jsx Normal file
View File

@ -0,0 +1,71 @@
import { h, Component, render, toChildArray } from 'preact';
/** Redirect rendering of descendants into the given CSS selector.
* @example
* <Portal into="body">
* <div>I am rendered into document.body</div>
* </Portal>
*/
export default class Portal extends Component {
componentDidUpdate(props) {
for (let i in props) {
if (props[i] !== this.props[i]) {
return setTimeout(this.renderLayer);
}
}
}
componentDidMount() {
this.isMounted = true;
this.renderLayer = this.renderLayer.bind(this);
this.renderLayer();
}
componentWillUnmount() {
this.renderLayer(false);
this.isMounted = false;
if (this.remote && this.remote.parentNode)
this.remote.parentNode.removeChild(this.remote);
}
findNode(node) {
return typeof node === 'string' ? document.querySelector(node) : node;
}
renderLayer(show = true) {
if (!this.isMounted) return;
// clean up old node if moving bases:
if (this.props.into !== this.intoPointer) {
this.intoPointer = this.props.into;
if (this.into && this.remote) {
this.remote = render(<PortalProxy />, this.into, this.remote);
}
this.into = this.findNode(this.props.into);
}
this.remote = render(
<PortalProxy context={this.context}>
{(show && this.props.children) || null}
</PortalProxy>,
this.into,
this.remote
);
}
render() {
return null;
}
}
// high-order component that renders its first child if it exists.
// used as a conditional rendering proxy.
class PortalProxy extends Component {
getChildContext() {
return this.props.context;
}
render({ children }) {
const arr = toChildArray(children);
return (arr && arr[0]) || null;
}
}

View File

@ -1,5 +1,5 @@
import { h } from 'preact';
import { PureComponent } from 'preact-compat';
import { PureComponent } from 'preact/compat';
/**
* This component udpates not through props or state, but by some parent

View File

@ -1,63 +1,63 @@
import { h, Component } from 'preact';
import { h } from 'preact';
import { useState, useEffect, useRef } from 'preact/hooks';
import { log } from '../utils';
import { trackEvent } from '../analytics';
import { itemService } from '../itemService';
import { alertsService } from '../notifications';
import { deferred } from '../deferred';
import { ItemTile } from './ItemTile';
import { Trans, t } from '@lingui/macro';
import { I18n } from '@lingui/react';
export default class SavedItemPane extends Component {
constructor(props) {
super(props);
// this.items = [];
}
export default function SavedItemPane({
itemsMap,
isOpen,
closeHandler,
onItemSelect,
onItemRemove,
onItemFork,
onExport,
mergeImportedItems
}) {
const [items, setItems] = useState([]);
const [filteredItems, setFilteredItems] = useState([]);
const searchInputRef = useRef();
static getDerivedStateFromProps({ items = {} }, state) {
const newItems = Object.values(items);
newItems.sort(function(a, b) {
useEffect(() => {
if (!itemsMap) return;
const newItems = Object.values(itemsMap);
newItems.sort(function (a, b) {
return b.updatedOn - a.updatedOn;
});
return {
items: newItems
};
}
shouldComponentUpdate(nextProps, nextState) {
return (
nextProps.items !== this.props.items ||
nextProps.isOpen !== this.props.isOpen ||
nextState.filteredItems !== this.state.filteredItems
);
}
setItems(newItems);
setFilteredItems(newItems);
}, [itemsMap]);
componentDidUpdate(prevProps) {
useEffect(() => {
// Opening
if (this.props.isOpen && !prevProps.isOpen) {
window.searchInput.value = '';
window.searchInput.focus();
if (isOpen) {
searchInputRef.current.value = '';
searchInputRef.current.focus();
}
// Closing
if (!this.props.isOpen && prevProps.isOpen) {
this.setState({
filteredItems: undefined
});
if (!isOpen) {
setFilteredItems([]);
}
}, [isOpen]);
function onCloseIntent() {
closeHandler();
}
onCloseIntent() {
this.props.closeHandler();
function itemClickHandler(item) {
onItemSelect(item);
}
itemClickHandler(item) {
this.props.itemClickHandler(item);
}
itemRemoveBtnClickHandler(item, e) {
function itemRemoveBtnClickHandler(item, e) {
e.stopPropagation();
this.props.itemRemoveBtnClickHandler(item);
onItemRemove(item);
}
itemForkBtnClickHandler(item, e) {
function itemForkBtnClickHandler(item, e) {
e.stopPropagation();
this.props.itemForkBtnClickHandler(item);
onItemFork(item);
}
keyDownHandler(event) {
if (!this.props.isOpen) {
function keyDownHandler(event) {
if (!isOpen) {
return;
}
@ -85,22 +85,21 @@ export default class SavedItemPane extends Component {
}
if (isEnterKeyPressed && selectedItemElement) {
const item = this.props.items[selectedItemElement.dataset.itemId];
console.log('opening', item);
this.props.itemClickHandler(item);
const item = itemsMap[selectedItemElement.dataset.itemId];
onItemSelect(item);
trackEvent('ui', 'openItemKeyboardShortcut');
}
// Fork shortcut inside saved creations panel with Ctrl/ + F
if (isForkKeyPressed) {
event.preventDefault();
const item = this.props.items[selectedItemElement.dataset.itemId];
this.props.itemForkBtnClickHandler(item);
const item = itemsMap[selectedItemElement.dataset.itemId];
itemForkBtnClickHandler(item);
trackEvent('ui', 'forkKeyboardShortcut');
}
}
importFileChangeHandler(e) {
function importFileChangeHandler(e) {
var file = e.target.files[0];
var reader = new FileReader();
@ -109,11 +108,13 @@ export default class SavedItemPane extends Component {
try {
items = JSON.parse(progressEvent.target.result);
log(items);
this.props.mergeImportedItems(items);
mergeImportedItems(items);
} catch (exception) {
log(exception);
alert(
'Oops! Selected file is corrupted. Please select a file that was generated by clicking the "Export" button.'
i18n._(
t`'Oops! Selected file is corrupted. Please select a file that was generated by clicking the "Export" button.`
)
);
}
});
@ -121,102 +122,115 @@ export default class SavedItemPane extends Component {
reader.readAsText(file, 'utf-8');
}
importBtnClickHandler(e) {
function importBtnClickHandler(e) {
var input = document.createElement('input');
input.type = 'file';
input.style.display = 'none';
input.accept = 'accept="application/json';
document.body.appendChild(input);
input.addEventListener('change', this.importFileChangeHandler.bind(this));
input.addEventListener('change', importFileChangeHandler);
input.click();
trackEvent('ui', 'importBtnClicked');
e.preventDefault();
}
searchInputHandler(e) {
const text = e.target.value.toLowerCase();
function searchInputHandler(e) {
const text = e.target.value.toLowerCase().trim();
if (!text) {
this.setState({
filteredItems: this.state.items
});
setFilteredItems(items);
} else {
this.setState({
filteredItems: this.state.items.filter(
item => item.title.toLowerCase().indexOf(text) !== -1
)
});
setFilteredItems(
items.filter(item => item.title.toLowerCase().indexOf(text) !== -1)
);
}
trackEvent('ui', 'searchInputType');
}
render(
{ isOpen, exportBtnClickHandler },
{ filteredItems = this.state.items, items = [] }
) {
return (
<div
id="js-saved-items-pane"
class={`saved-items-pane ${isOpen ? 'is-open' : ''}`}
onKeyDown={this.keyDownHandler.bind(this)}
aria-hidden={isOpen}
>
<button
onClick={this.onCloseIntent.bind(this)}
class="btn saved-items-pane__close-btn"
id="js-saved-items-pane-close-btn"
aria-label="Close saved creations pane"
return (
<I18n>
{({ i18n }) => (
<div
id="js-saved-items-pane"
class={`saved-items-pane ${isOpen ? 'is-open' : ''}`}
onKeyDown={keyDownHandler}
aria-hidden={isOpen}
>
X
</button>
<div class="flex flex-v-center" style="justify-content: space-between;">
<h3>My Library ({filteredItems.length})</h3>
<button
onClick={onCloseIntent}
class="btn saved-items-pane__close-btn"
id="js-saved-items-pane-close-btn"
aria-label={i18n._(t`Close saved creations pane`)}
>
X
</button>
<div
class="flex flex-v-center"
style="justify-content: space-between;"
>
<h3>
<Trans>My Library ({filteredItems.length})</Trans>
</h3>
<div>
<button
onClick={exportBtnClickHandler}
class="btn--dark hint--bottom-left hint--rounded hint--medium"
aria-label="Export all your creations into a single importable file."
>
Export
</button>
<button
onClick={this.importBtnClickHandler.bind(this)}
class="btn--dark hint--bottom-left hint--rounded hint--medium"
aria-label="Import your creations. Only the file that you export through the 'Export' button can be imported."
>
Import
</button>
<div>
<button
onClick={onExport}
class="btn--dark hint--bottom-left hint--rounded hint--medium"
aria-label={i18n._(
t`Export all your creations into a single importable file.`
)}
>
<Trans>Export</Trans>
</button>
<button
onClick={importBtnClickHandler}
class="btn--dark hint--bottom-left hint--rounded hint--medium"
aria-label={i18n._(
t`Import your creations. Only the file that you export through the 'Export' button can be imported.`
)}
>
<Trans>Import</Trans>
</button>
</div>
</div>
<form autoComplete="off" onSubmit={e => e.preventDefault()}>
<input
type="search"
id="searchInput"
ref={searchInputRef}
class="search-input"
onInput={searchInputHandler}
placeholder={i18n._(t`Search your creations here...`)}
/>
</form>
<div id="js-saved-items-wrap" class="saved-items-pane__container">
{!filteredItems.length && items.length ? (
<div class="mt-1">
<Trans>No match found.</Trans>
</div>
) : null}
{filteredItems.map(item => (
<ItemTile
item={item}
onClick={() => itemClickHandler(item)}
onForkBtnClick={e => itemForkBtnClickHandler(item, e)}
onRemoveBtnClick={e => itemRemoveBtnClickHandler(item, e)}
/>
))}
{!items.length ? (
<div class="tac">
<h2 class="opacity--30">
<Trans>Nothing saved here.</Trans>
</h2>
<img
style="max-width: 80%; opacity:0.4"
src="assets/empty.svg"
/>
</div>
) : null}
</div>
</div>
<input
autocomplete="off"
type="search"
id="searchInput"
class="search-input"
onInput={this.searchInputHandler.bind(this)}
placeholder="Search your creations here..."
/>
<div id="js-saved-items-wrap" class="saved-items-pane__container">
{!filteredItems.length && items.length ? (
<div class="mt-1">No match found.</div>
) : null}
{filteredItems.map(item => (
<ItemTile
item={item}
onClick={this.itemClickHandler.bind(this, item)}
onForkBtnClick={this.itemForkBtnClickHandler.bind(this, item)}
onRemoveBtnClick={this.itemRemoveBtnClickHandler.bind(this, item)}
/>
))}
{!items.length ? (
<div class="tac">
<h2 class="opacity--30">Nothing saved here.</h2>
<img style="max-width: 80%; opacity:0.4" src="assets/empty.svg" />
</div>
) : null}
</div>
</div>
);
}
)}
</I18n>
);
}

View File

@ -378,24 +378,24 @@ export default class Settings extends Component {
stopped.
</HelpText>
</div>
{/*
<Divider />
<div>
<Divider />
<div>
<label class="line">
Language
<select
value={prefs.lang}
onChange={e => this.updateSetting(e, 'lang')}
>
<option value="en">English</option>
<option value="hi">Hindi</option>
<option value="sa">Sanskrit</option>
<option value="es">Spanish</option>
</select>
Language
<select
value={prefs.lang}
onChange={e => this.updateSetting(e, 'lang')}
>
<option value="en">English</option>
<option value="hi">ि</option>
<option value="sa">Sanskrit</option>
<option value="es">Español (España)</option>
<option value="zh-Hans">中文(简体)</option>
</select>
</label>
</div>
*/}
</div>
</TabPanel>
</Tabs>
</div>

View File

@ -38,7 +38,11 @@ export class SplitPane extends Component {
options.gutterSize = 6;
/* eslint-disable new-cap */
this.splitInstance = Split([...this.parent.children], options);
this.splitInstance = Split(Array.from(this.parent.children), options);
if (this.parent.children.length >= 5) {
window.splitInstance = this.splitInstance;
}
/* eslint-enable new-cap */

View File

@ -1,4 +1,4 @@
/* global htmlCodeEl, cssCodeEl, jsCodeEl, runBtn
/* global htmlCodeEl, cssCodeEl, jsCodeEl
*/
import { h, Component } from 'preact';
@ -21,7 +21,8 @@ import {
downloadFile,
getCompleteHtml,
getFilenameFromUrl,
prettify
prettify,
sanitizeSplitSizes
} from '../utils';
import {
linearizeFiles,
@ -49,7 +50,7 @@ import { KeyboardShortcutsModal } from './KeyboardShortcutsModal';
import { takeScreenshot } from '../takeScreenshot';
import { AskToImportModal } from './AskToImportModal';
import { Alerts } from './Alerts';
import Portal from 'preact-portal';
import Portal from './Portal';
import { HelpModal } from './HelpModal';
import { OnboardingModal } from './OnboardingModal';
import { Js13KModal } from './Js13KModal';
@ -179,8 +180,7 @@ export default class App extends Component {
if (customUser) {
const prefs = { ...this.state.prefs };
Object.assign(prefs, user.settings);
this.setState({ prefs: prefs });
this.updateSetting();
this.setState({ prefs }, this.updateSetting);
}
});
} else {
@ -230,8 +230,7 @@ export default class App extends Component {
this.createNewItem();
}
Object.assign(this.state.prefs, result);
this.setState({ prefs: { ...this.state.prefs } });
this.updateSetting();
this.setState({ prefs: { ...this.state.prefs } }, this.updateSetting);
});
// Check for new version notifications
@ -270,7 +269,9 @@ export default class App extends Component {
async loadLanguage(lang) {
log('🇯🇲 fetching defninition');
const catalog = await import(/* webpackMode: "lazy", webpackChunkName: "i18n-[index]" */ `../locales/${lang}/messages.js`);
const catalog = await import(
/* webpackMode: "lazy", webpackChunkName: "i18n-[index]" */ `../locales/${lang}/messages.js`
);
this.setState(state => ({
catalogs: {
@ -281,27 +282,34 @@ export default class App extends Component {
}
incrementUnsavedChanges() {
this.setState({ unsavedEditCount: this.state.unsavedEditCount + 1 });
this.setState(prevState => {
const newCount = prevState.unsavedEditCount + 1;
if (
this.state.unsavedEditCount % UNSAVED_WARNING_COUNT === 0 &&
this.state.unsavedEditCount >= UNSAVED_WARNING_COUNT
) {
window.saveBtn.classList.add('animated');
window.saveBtn.classList.add('wobble');
window.saveBtn.addEventListener('animationend', () => {
window.saveBtn.classList.remove('animated');
window.saveBtn.classList.remove('wobble');
});
}
if (
newCount % UNSAVED_WARNING_COUNT === 0 &&
newCount >= UNSAVED_WARNING_COUNT
) {
window.saveBtn.classList.add('animated');
window.saveBtn.classList.add('wobble');
window.saveBtn.addEventListener('animationend', () => {
window.saveBtn.classList.remove('animated');
window.saveBtn.classList.remove('wobble');
});
}
return { unsavedEditCount: newCount };
});
}
updateProfileUi() {
if (this.state.user) {
document.body.classList.add('is-logged-in');
} else {
document.body.classList.remove('is-logged-in');
}
this.setState(prevState => {
if (prevState.user) {
document.body.classList.add('is-logged-in');
} else {
document.body.classList.remove('is-logged-in');
}
return null;
});
}
refreshEditor() {
@ -458,23 +466,27 @@ export default class App extends Component {
populateItemsInSavedPane(items) {
// TODO: sort desc. by updation date
this.setState({
savedItems: { ...this.state.savedItems }
});
// this.setState({
// savedItems: { ...this.state.savedItems }
// });
this.toggleSavedItemsPane();
// HACK: Set overflow after sometime so that the items can animate without getting cropped.
// setTimeout(() => $('#js-saved-items-wrap').style.overflowY = 'auto', 1000);
}
toggleSavedItemsPane(shouldOpen) {
this.setState({
isSavedItemPaneOpen:
shouldOpen === undefined ? !this.state.isSavedItemPaneOpen : shouldOpen
});
this.setState(prevState => {
const isSavedItemPaneOpen =
shouldOpen === undefined ? !prevState.isSavedItemPaneOpen : shouldOpen;
document.body.classList[this.state.isSavedItemPaneOpen ? 'add' : 'remove'](
'overlay-visible'
);
document.body.classList[isSavedItemPaneOpen ? 'add' : 'remove'](
'overlay-visible'
);
return {
isSavedItemPaneOpen
};
});
}
/**
@ -484,17 +496,17 @@ export default class App extends Component {
* @return {promise} Promise.
*/
async fetchItems(shouldSaveGlobally, shouldFetchLocally) {
// HACK: This empty assignment is being used when importing locally saved items
// to cloud, `fetchItems` runs once on account login which clears the
// savedItems object and hence, while merging no saved item matches with itself.
this.state.savedItems = {};
var items = [];
const savedItems = {};
items = await itemService.getAllItems(shouldFetchLocally);
trackEvent('fn', 'fetchItems', items.length);
if (shouldSaveGlobally) {
items.forEach(item => {
this.state.savedItems[item.id] = item;
savedItems[item.id] = item;
});
this.setState({
savedItems
});
}
return items;
@ -723,6 +735,9 @@ export default class App extends Component {
}
layoutBtnClickHandler(layoutId) {
if (layoutId === this.state.currentLayoutMode) {
layoutId = 2;
}
this.saveSetting('layoutMode', layoutId);
trackEvent('ui', 'toggleLayoutClick', layoutId);
this.toggleLayout(layoutId);
@ -744,7 +759,7 @@ export default class App extends Component {
sizes = [33.33, 33.33, 33.33];
} finally {
/* eslint-disable no-unsafe-finally */
return sizes;
return sanitizeSplitSizes(sizes);
/* eslint-enable no-unsafe-finally */
}
@ -780,20 +795,28 @@ export default class App extends Component {
`calc(50% - ${sidebarWidth / 2}px)`
];
}
return sizes;
return sanitizeSplitSizes(sizes);
}
const currentLayoutMode = this.state.currentLayoutMode;
var dimensionProperty = currentLayoutMode === 2 ? 'height' : 'width';
sizes = [
getPercentFromDimension($('#js-code-side'), dimensionProperty),
getPercentFromDimension($('#js-demo-side'), dimensionProperty)
];
try {
sizes = [
getPercentFromDimension($('#js-code-side'), dimensionProperty),
getPercentFromDimension($('#js-demo-side'), dimensionProperty)
];
if (sizes.filter(s => s).length !== 2) {
if (sizes.filter(s => s).length !== 2) {
sizes = [50, 50];
}
} catch (e) {
sizes = [50, 50];
} finally {
/* eslint-disable no-unsafe-finally */
return sanitizeSplitSizes(sizes);
/* eslint-enable no-unsafe-finally */
}
return sizes;
}
saveSetting(setting, value) {
const d = deferred();
@ -917,7 +940,9 @@ export default class App extends Component {
}
titleInputBlurHandler(e) {
this.state.currentItem.title = e.target.value;
this.setState({
currentItem: { ...this.state.currentItem, title: e.target.value }
});
if (this.state.currentItem.id) {
this.saveItem();
@ -929,19 +954,21 @@ export default class App extends Component {
* Handles all user triggered preference changes in the UI.
*/
updateSetting(settingName, value) {
const prefs = { ...this.state.prefs };
// If this was triggered from user interaction, save the setting
if (settingName) {
// var settingName = e.target.dataset.setting;
var obj = {};
log(settingName, value);
const prefs = { ...this.state.prefs };
// const prefs = { ...this.state.prefs };
prefs[settingName] = value;
obj[settingName] = prefs[settingName];
this.setState({ prefs });
// We always save locally so that it gets fetched
// faster on future loads.
db.sync.set(obj, function() {
db.sync.set(obj, function () {
alertsService.add('Setting saved');
});
if (window.user) {
@ -961,15 +988,7 @@ export default class App extends Component {
trackEvent('ui', 'updatePref-' + settingName, prefs[settingName]);
}
const prefs = this.state.prefs;
// Show/hide RUN button based on autoPreview setting.
let autoPreview =
window.forcedSettings.autoPreview !== undefined
? window.forcedSettings
: prefs.autoPreview;
runBtn.classList[autoPreview ? 'add' : 'remove']('hide');
this.contentWrap.applyCodemirrorSettings(this.state.prefs);
this.contentWrap.applyCodemirrorSettings(prefs);
if (prefs.autoSave) {
if (!this.autoSaveInterval) {
@ -1172,7 +1191,7 @@ export default class App extends Component {
}
}
mergeImportedItems(items) {
mergeImportedItems(items, isMergingToCloud = false) {
var existingItemIds = [];
var toMergeItems = {};
const d = deferred();
@ -1181,14 +1200,14 @@ export default class App extends Component {
// We can access `savedItems` here because this gets set when user
// opens the saved creations panel. And import option is available
// inside the saved items panel.
// HACK: Also when this fn is called for importing locally saved items
// to cloud, `fetchItems` runs once on account login which clears the
// savedItems object and hence, no match happens for `existingItemIds`.
if (savedItems[item.id]) {
// When we are merging to cloud, savedItems contains the local items. And if we start matching,
// all items will match with themselves and nothing would import :P
if (!isMergingToCloud && savedItems[item.id]) {
// Item already exists
existingItemIds.push(item.id);
} else {
log('merging', item.id);
// log('merging', item.id);
toMergeItems[item.id] = item;
}
});
@ -1225,7 +1244,7 @@ export default class App extends Component {
* Called from inside ask-to-import-modal
*/
importCreationsAndSettingsIntoApp() {
this.mergeImportedItems(this.oldSavedItems).then(() => {
this.mergeImportedItems(this.oldSavedItems, true).then(() => {
trackEvent('fn', 'oldItemsImported');
this.dontAskToImportAnymore();
});
@ -1238,10 +1257,23 @@ export default class App extends Component {
this.closeAllOverlays();
}
splitUpdateHandler(mainSplitInstance, codeSplitInstance) {
splitUpdateHandler(sizes) {
const { currentItem } = this.state;
if (!sizes) {
currentItem.mainSizes = this.getMainPaneSizes();
currentItem.sizes = this.getCodePaneSizes();
return;
}
// Not using setState to avoid re-render
this.state.currentItem.sizes = this.getCodePaneSizes();
this.state.currentItem.mainSizes = this.getMainPaneSizes();
if (sizes.length === 3) {
if (currentItem.files) {
currentItem.mainSizes = sizes;
} else {
currentItem.sizes = sizes;
}
} else {
currentItem.mainSizes = sizes;
}
}
/**
@ -1257,7 +1289,7 @@ export default class App extends Component {
whitespace = /(\r?\n|\r|\s+)/g;
const ByteSize = {
count: function(text, options) {
count: function (text, options) {
// Set option defaults
options = options || {};
options.lineBreaks = options.lineBreaks || 1;
@ -1281,7 +1313,7 @@ export default class App extends Component {
}
},
format: function(count, plainText) {
format: function (count, plainText) {
var level = 0;
while (count > 1024) {
@ -1490,9 +1522,7 @@ export default class App extends Component {
const { file } = getFileFromPath(currentItem.files, sourceFilePath);
if (doesFileExistInFolder(destinationFolder, file.name)) {
alert(
`File with name "${
file.name
}" already exists in the destination folder.`
`File with name "${file.name}" already exists in the destination folder.`
);
return;
}
@ -1585,6 +1615,7 @@ export default class App extends Component {
title={this.state.currentItem.title}
titleInputBlurHandler={this.titleInputBlurHandler.bind(this)}
user={this.state.user}
isAutoPreviewOn={this.state.prefs.autoPreview}
unsavedEditCount={this.state.unsavedEditCount}
isFileMode={
this.state.currentItem && this.state.currentItem.files
@ -1656,15 +1687,13 @@ export default class App extends Component {
</div>
<SavedItemPane
items={this.state.savedItems}
itemsMap={this.state.savedItems}
isOpen={this.state.isSavedItemPaneOpen}
closeHandler={this.closeSavedItemsPane.bind(this)}
itemClickHandler={this.itemClickHandler.bind(this)}
itemRemoveBtnClickHandler={this.itemRemoveBtnClickHandler.bind(
this
)}
itemForkBtnClickHandler={this.itemForkBtnClickHandler.bind(this)}
exportBtnClickHandler={this.exportBtnClickHandler.bind(this)}
onItemSelect={this.itemClickHandler.bind(this)}
onItemRemove={this.itemRemoveBtnClickHandler.bind(this)}
onItemFork={this.itemForkBtnClickHandler.bind(this)}
onExport={this.exportBtnClickHandler.bind(this)}
mergeImportedItems={this.mergeImportedItems.bind(this)}
/>
@ -1784,7 +1813,7 @@ export default class App extends Component {
closeHandler={() => this.setState({ isCommandPaletteOpen: false })}
/>
<Portal into="body">
<Portal into="#portal">
<div
class="modal-overlay"
onClick={this.modalOverlayClickHandler.bind(this)}

View File

@ -9,7 +9,7 @@ window.addEventListener('message', e => {
frame.contentDocument.close();
}, 10);
}
if (e.data && e.data.url && e.data.url.match(/preview\.html/)) {
if (e.data && e.data.url && e.data.url.match(/index\.html/)) {
document.querySelector('iframe').src = e.data.url;
}

View File

@ -1,83 +1,90 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta charset="utf-8" />
<title>Web Maker</title>
<link rel="shortcut icon" href="icon-128.png">
<meta name=viewport content="width=device-width, initial-scale=1">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<link rel="manifest" href="<%= htmlWebpackPlugin.files.publicPath %>manifest.json">
<link rel="shortcut icon" href="icon-128.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<link
rel="manifest"
href="<%= htmlWebpackPlugin.files.publicPath %>manifest.json"
/>
<% if (htmlWebpackPlugin.options.manifest.theme_color) { %>
<meta name="theme-color" content="<%= htmlWebpackPlugin.options.manifest.theme_color %>">
<% } %>
<meta
name="theme-color"
content="<%= htmlWebpackPlugin.options.manifest.theme_color %>"
/>
<% } %>
<style>
/* Critically acclaimed CSS */
<style>
/* Critically acclaimed CSS */
.saved-items-pane {
position: fixed;
right: 0;
top: 0;
bottom: 0;
width: 450px;
transform: translateX(100%);
}
.saved-items-pane {
position: fixed;
right: 0;
top: 0;
bottom: 0;
width: 450px;
transform: translateX(100%);
}
.modal {
visibility: hidden;
}
.modal {
visibility: hidden;
}
</style>
</style>
<link
rel="stylesheet"
id="editorThemeLinkTag"
href="lib/codemirror/theme/monokai.css"
/>
<!-- build:css vendor.css -->
<link rel="stylesheet" href="lib/codemirror/lib/codemirror.css">
<link rel="stylesheet" href="lib/codemirror/addon/hint/show-hint.css">
<link rel="stylesheet" href="lib/codemirror/addon/fold/foldgutter.css">
<link rel="stylesheet" href="lib/codemirror/addon/dialog/dialog.css">
<link rel="stylesheet" href="lib/hint.min.css">
<link rel="stylesheet" href="lib/inlet.css">
<!-- endbuild -->
<style id="fontStyleTemplate" type="template">
@font-face {
font-family: 'fontname';
font-style: normal;
font-weight: 400;
src: url(fontname.ttf) format('truetype');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC,
U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
}
.CodeMirror pre {
font-family: 'fontname', monospace;
}
</style>
<style type="text/css" id="fontStyleTag">
@font-face {
font-family: 'FiraCode';
font-style: normal;
font-weight: 400;
src: url(FiraCode.ttf) format('truetype');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC,
U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
}
<link rel="stylesheet" id="editorThemeLinkTag" href="lib/codemirror/theme/monokai.css"></link>
<!-- build:css style.css -->
<link rel="stylesheet" href="style.css">
<!-- endbuild -->
<style id="fontStyleTemplate" type="template">
@font-face { font-family: 'fontname'; font-style: normal; font-weight: 400; src: url(fontname.ttf) format('truetype'); unicode-range:
U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD,
U+F000; } .CodeMirror pre { font-family: 'fontname', monospace; }
</style>
<style type="text/css" id="fontStyleTag">
@font-face {
font-family: 'FiraCode';
font-style: normal;
font-weight: 400;
src: url(FiraCode.ttf) format('truetype');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
}
.CodeMirror pre {
font-family: 'FiraCode', monospace;
}
</style>
.CodeMirror pre {
font-family: 'FiraCode', monospace;
}
</style>
</head>
<body>
<!-- SCRIPT-TAGS -->
<%= htmlWebpackPlugin.options.ssr({
url: '/'
}) %>
<script defer src="<%= htmlWebpackPlugin.files.chunks['bundle'].entry %>"></script>
<script>
window.fetch || document.write('<script src="<%= htmlWebpackPlugin.files.chunks["polyfills"].entry %>"><\/script>')
</script>
<!-- END-SCRIPT-TAGS -->
<body>
<div id="root"></div>
<div id="portal"></div>
<!-- SCRIPT-TAGS -->
<%= htmlWebpackPlugin.options.ssr({ url: '/' }) %>
<script
defer
src="<%= htmlWebpackPlugin.files.chunks['bundle'].entry %>"
></script>
<script>
window.fetch ||
document.write(
'<script src="<%= htmlWebpackPlugin.files.chunks["polyfills"].entry %>"><\/script>'
);
</script>
<!-- END-SCRIPT-TAGS -->
</body>
</html>

View File

@ -1,3 +1,11 @@
import App from './components/app.jsx';
import './lib/codemirror/lib/codemirror.css';
import './lib/codemirror/addon/hint/show-hint.css';
import './lib/codemirror/addon/fold/foldgutter.css';
import './lib/codemirror/addon/dialog/dialog.css';
import './lib/hint.min.css';
import './lib/inlet.css';
import './style.css';
export default App;

View File

@ -39,7 +39,7 @@ export const itemService = {
var d = deferred();
let itemIds = await this.getUserItemIds(shouldFetchLocally);
itemIds = Object.getOwnPropertyNames(itemIds || {});
log('itemids', itemIds);
// log('itemids', itemIds);
if (!itemIds.length) {
d.resolve([]);

View File

@ -18,7 +18,7 @@
height: 14px;
box-shadow: inset 0px 0px 5px 0px rgba(4, 4, 4, 0.5);
background-color: #d6d6d6;
background-image: linear-gradient(top, #d6d6d6, #ebebeb);
background-image: linear-gradient(to top, #d6d6d6, #ebebeb);
}
.inlet_slider:hover {
opacity: 0.98;
@ -55,7 +55,7 @@
box-shadow: 0px 0px 3px 0px rgba(4, 4, 4, 0.4);
background-color: #424242;
background-color: crimson;
background-image: linear-gradient(top, #424242, #212121);
background-image: linear-gradient(to top, #424242, #212121);
}
/*
* =========================================================
@ -87,11 +87,11 @@
width: 229px;
z-index: 100;
border-radius: 3px;
-webkit-box-shadow: inset 0px 0px 5px 0px rgba(4, 4, 4, 0.5);
box-shadow: inset 0px 0px 5px 0px rgba(4, 4, 4, 0.5);
background-color: rgba(214, 214, 215, 0.85);
/*
background-image: linear-gradient(top, rgb(214, 214, 214), rgb(235, 235, 235));
background-image: linear-gradient(to top, rgb(214, 214, 214), rgb(235, 235, 235));
*/
}
.ColorPicker br {
@ -104,8 +104,8 @@
color: #aa1212;
}
.ColorPicker input.hexInput {
-webkit-transition-property: color;
-webkit-transition-duration: .5s;
transition-property: color;
transition-duration: .5s;
background: none;
border: 0;
margin: 0;

View File

@ -1,8 +0,0 @@
{
"Console": {
"origin": [
["src/components/Console.jsx", 58],
["src/components/Console.jsx", 58]
]
}
}

View File

@ -1,47 +0,0 @@
{
"Run": {
"origin": [
["src/components/MainHeader.jsx", 32],
["src/components/MainHeader.jsx", 32]
]
},
"Add a JS/CSS library": {
"origin": [["src/components/MainHeader.jsx", 41]]
},
"Add library": {
"origin": [
["src/components/MainHeader.jsx", 43],
["src/components/MainHeader.jsx", 43]
]
},
"New": {
"origin": [
["src/components/MainHeader.jsx", 64],
["src/components/MainHeader.jsx", 64]
]
},
"Save": {
"origin": [
["src/components/MainHeader.jsx", 80],
["src/components/MainHeader.jsx", 80]
]
},
"Open": {
"origin": [
["src/components/MainHeader.jsx", 96],
["src/components/MainHeader.jsx", 96]
]
},
"Login": {
"origin": [
["src/components/MainHeader.jsx", 105],
["src/components/MainHeader.jsx", 105]
]
},
"Signup": {
"origin": [
["src/components/MainHeader.jsx", 105],
["src/components/MainHeader.jsx", 105]
]
}
}

View File

@ -1,6 +1,6 @@
/* eslint-disable */ export default {
languageData: {
plurals: function(n, ord) {
plurals: function (n, ord) {
var s = String(n).split('.'),
v0 = !s[1],
t0 = Number(s[0]) == n,
@ -18,14 +18,112 @@
}
},
messages: {
'"Web Maker" <0>CHill</0>.': '"Web Maker" <0>CHill</0>.',
'\'Oops! Selected file is corrupted. Please select a file that was generated by clicking the "Export" button.':
'\'Oops! Selected file is corrupted. Please select a file that was generated by clicking the "Export" button.',
'Add Library': 'Add Library',
'Add a JS/CSS library': 'Add a JS/CSS library',
'Add library': 'Add library',
Chat: 'Chat',
'Choose from popular libraries': 'Choose from popular libraries',
'Clear console (CTRL + L)': 'Clear console (CTRL + L)',
'Clear console (works when console input is focused)':
'Clear console (works when console input is focused)',
'Close saved creations pane': 'Close saved creations pane',
'Close saved creations panel & modals':
'Close saved creations panel & modals',
Console: 'Console',
'Detach Preview': 'Detach Preview',
'Detach preview': 'Detach preview',
Donate: 'Donate',
'Double click to toggle console': 'Double click to toggle console',
'Download game as zip': 'Download game as zip',
'Edit on CodePen': 'Edit on CodePen',
Editor: 'Editor',
'Emmet code completion': 'Emmet code completion',
Export: 'Export',
'Export all your creations into a single importable file.':
'Export all your creations into a single importable file.',
Find: 'Find',
'Find & replace': 'Find & replace',
Global: 'Global',
Help: 'Help',
Import: 'Import',
"Import your creations. Only the file that you export through the 'Export' button can be imported.":
"Import your creations. Only the file that you export through the 'Export' button can be imported.",
'Indent code left': 'Indent code left',
'Indent code right': 'Indent code right',
'Keyboard Shortcuts': 'Keyboard Shortcuts',
'Keyboard shortcuts': 'Keyboard shortcuts',
License: 'License',
'Like this extension? Please <0>rate it here</0>.':
'Like this extension? Please <0>rate it here</0>.',
Login: 'Login',
'Login/Signup': 'Login/Signup',
'Made with <0>\uD83D\uDC96</0>& <1> \uD83D\uDE4C</1> by <2>Kushagra Gour</2>':
'Made with <0>\uD83D\uDC96</0>& <1> \uD83D\uDE4C</1> by <2>Kushagra Gour</2>',
'My Library ({0})': function (a) {
return ['My Library (', a('0'), ')'];
},
New: 'New',
'No match found.': 'No match found.',
'Note: You can load external scripts from following domains:':
'Note: You can load external scripts from following domains:',
'Note: You can load external scripts only from following domains:':
'Note: You can load external scripts only from following domains:',
'Nothing saved here.': 'Nothing saved here.',
Open: 'Open',
'Open a saved creation (Ctrl/\u2318 + O)':
'Open a saved creation (Ctrl/\u2318 + O)',
'Open list of saved creations': 'Open list of saved creations',
'Powered by cdnjs': 'Powered by cdnjs',
'Put each library in new line': 'Put each library in new line',
'Read more': 'Read more',
'Read the documentation.': 'Read the documentation.',
'Realign code': 'Realign code',
'Refresh preview': 'Refresh preview',
'Report a bug': 'Report a bug',
'Review Web Maker': 'Review Web Maker',
Run: 'Run',
'Run Prettier': 'Run Prettier',
'Run preview (Ctrl/\u2318 + Shift + 5)':
'Run preview (Ctrl/\u2318 + Shift + 5)',
Save: 'Save',
Signup: 'Signup'
'Save as HTML file': 'Save as HTML file',
'Save current creation (Ctrl/\u2318 + S)':
'Save current creation (Ctrl/\u2318 + S)',
'Save current creations': 'Save current creations',
'Search your creations here...': 'Search your creations here...',
'See Changelog': 'See Changelog',
'See awesome libraries used': 'See awesome libraries used',
'See changelog': 'See changelog',
'See profile or Logout': 'See profile or Logout',
'Select next match': 'Select next match',
'Select previous match': 'Select previous match',
Settings: 'Settings',
Signup: 'Signup',
'Single line comment': 'Single line comment',
'Start a new creation': 'Start a new creation',
'Support the developer': 'Support the developer',
'Support the developer by pledging some amount':
'Support the developer by pledging some amount',
'Switch to full screen preview': 'Switch to full screen preview',
'Switch to layout with all vertical panes':
'Switch to layout with all vertical panes',
'Switch to layout with preview on bottom':
'Switch to layout with preview on bottom',
'Switch to layout with preview on left':
'Switch to layout with preview on left',
'Switch to layout with preview on left"':
'Switch to layout with preview on left"',
'Switch to layout with preview on right':
'Switch to layout with preview on right',
'Take screenshot of preview': 'Take screenshot of preview',
'Toggle console': 'Toggle console',
"Tweet about 'Web Maker'": "Tweet about 'Web Maker'",
'Tweet out your feature requests, comments & suggestions to <0>@webmakerApp</0>':
'Tweet out your feature requests, comments & suggestions to <0>@webmakerApp</0>',
'Type here to search libraries': 'Type here to search libraries',
'Upload Image': 'Upload Image'
}
};

View File

@ -13,46 +13,350 @@ msgstr ""
"Language-Team: \n"
"Plural-Forms: \n"
#: src/components/HelpModal.jsx:201
#~ msgid "\"Web Maker\" <0>CHill</0>."
#~ msgstr "\"Web Maker\" <0>CHill</0>."
#: src/components/SavedItemPane.jsx:116
msgid "'Oops! Selected file is corrupted. Please select a file that was generated by clicking the \"Export\" button."
msgstr "'Oops! Selected file is corrupted. Please select a file that was generated by clicking the \"Export\" button."
#: src/components/AddLibrary.jsx:67
msgid "Add Library"
msgstr "Add Library"
#: src/components/MainHeader.jsx:41
msgid "Add a JS/CSS library"
msgstr "Add a JS/CSS library"
#: src/components/MainHeader.jsx:43
#: src/components/MainHeader.jsx:43
msgid "Add library"
msgstr "Add library"
#: src/components/Console.jsx:58
#: src/components/Console.jsx:58
#: src/components/HelpModal.jsx:91
msgid "Chat"
msgstr "Chat"
#: src/components/AddLibrary.jsx:92
msgid "Choose from popular libraries"
msgstr "Choose from popular libraries"
#: src/components/Console.jsx:69
msgid "Clear console (CTRL + L)"
msgstr "Clear console (CTRL + L)"
#: src/components/KeyboardShortcutsModal.jsx:42
msgid "Clear console (works when console input is focused)"
msgstr "Clear console (works when console input is focused)"
#: src/components/SavedItemPane.jsx:170
msgid "Close saved creations pane"
msgstr "Close saved creations pane"
#: src/components/KeyboardShortcutsModal.jsx:48
msgid "Close saved creations panel & modals"
msgstr "Close saved creations panel & modals"
#: src/components/Console.jsx:61
msgid "Console"
msgstr "Console"
#: src/components/MainHeader.jsx:105
#: src/components/MainHeader.jsx:105
msgid "Login"
msgstr "Login"
#: src/components/Footer.jsx:301
#~ msgid "Detach Preview"
#~ msgstr "Detach Preview"
#: src/components/Footer.jsx:297
msgid "Detach preview"
msgstr "Detach preview"
#: src/components/Footer.jsx:142
msgid "Donate"
msgstr "Donate"
#: src/components/Console.jsx:57
msgid "Double click to toggle console"
msgstr "Double click to toggle console"
#: src/components/Footer.jsx:170
msgid "Download game as zip"
msgstr "Download game as zip"
#: src/components/Footer.jsx:225
msgid "Edit on CodePen"
msgstr "Edit on CodePen"
#: src/components/KeyboardShortcutsModal.jsx:54
msgid "Editor"
msgstr "Editor"
#: src/components/KeyboardShortcutsModal.jsx:101
msgid "Emmet code completion"
msgstr "Emmet code completion"
#: src/components/SavedItemPane.jsx:190
msgid "Export"
msgstr "Export"
#: src/components/SavedItemPane.jsx:187
msgid "Export all your creations into a single importable file."
msgstr "Export all your creations into a single importable file."
#: src/components/KeyboardShortcutsModal.jsx:59
msgid "Find"
msgstr "Find"
#: src/components/KeyboardShortcutsModal.jsx:77
msgid "Find & replace"
msgstr "Find & replace"
#: src/components/KeyboardShortcutsModal.jsx:15
msgid "Global"
msgstr "Global"
#: src/components/Footer.jsx:90
#: src/components/Footer.jsx:190
msgid "Help"
msgstr "Help"
#: src/components/SavedItemPane.jsx:199
msgid "Import"
msgstr "Import"
#: src/components/SavedItemPane.jsx:196
msgid "Import your creations. Only the file that you export through the 'Export' button can be imported."
msgstr "Import your creations. Only the file that you export through the 'Export' button can be imported."
#: src/components/KeyboardShortcutsModal.jsx:95
msgid "Indent code left"
msgstr "Indent code left"
#: src/components/KeyboardShortcutsModal.jsx:89
msgid "Indent code right"
msgstr "Indent code right"
#: src/components/KeyboardShortcutsModal.jsx:9
msgid "Keyboard Shortcuts"
msgstr "Keyboard Shortcuts"
#: src/components/Footer.jsx:104
msgid "Keyboard shortcuts"
msgstr "Keyboard shortcuts"
#: src/components/HelpModal.jsx:195
msgid "License"
msgstr "License"
#: src/components/HelpModal.jsx:47
#~ msgid "Like this extension? Please <0>rate it here</0>."
#~ msgstr "Like this extension? Please <0>rate it here</0>."
#: src/components/MainHeader.jsx:105
#: src/components/MainHeader.jsx:105
#~ msgid "Login"
#~ msgstr "Login"
#: src/components/MainHeader.jsx:104
msgid "Login/Signup"
msgstr "Login/Signup"
#: src/components/HelpModal.jsx:16
#~ msgid "Made with <0>💖</0>& <1> 🙌</1> by <2>Kushagra Gour</2>"
#~ msgstr "Made with <0>💖</0>& <1> 🙌</1> by <2>Kushagra Gour</2>"
#: src/components/SavedItemPane.jsx:179
msgid "My Library ({0})"
msgstr "My Library ({0})"
#: src/components/MainHeader.jsx:64
#: src/components/MainHeader.jsx:64
msgid "New"
msgstr "New"
#: src/components/MainHeader.jsx:96
#: src/components/SavedItemPane.jsx:215
msgid "No match found."
msgstr "No match found."
#: src/components/AddLibrary.jsx:125
#~ msgid "Note: You can load external scripts from following domains:"
#~ msgstr "Note: You can load external scripts from following domains:"
#: src/components/AddLibrary.jsx:125
msgid "Note: You can load external scripts only from following domains:"
msgstr "Note: You can load external scripts only from following domains:"
#: src/components/SavedItemPane.jsx:232
msgid "Nothing saved here."
msgstr "Nothing saved here."
#: src/components/MainHeader.jsx:96
msgid "Open"
msgstr "Open"
#: src/components/MainHeader.jsx:32
#: src/components/MainHeader.jsx:87
msgid "Open a saved creation (Ctrl/⌘ + O)"
msgstr "Open a saved creation (Ctrl/⌘ + O)"
#: src/components/KeyboardShortcutsModal.jsx:36
msgid "Open list of saved creations"
msgstr "Open list of saved creations"
#: src/components/AddLibrary.jsx:88
msgid "Powered by cdnjs"
msgstr "Powered by cdnjs"
#: src/components/AddLibrary.jsx:118
#: src/components/AddLibrary.jsx:147
msgid "Put each library in new line"
msgstr "Put each library in new line"
#: src/components/KeyboardShortcutsModal.jsx:107
msgid "Read more"
msgstr "Read more"
#: src/components/HelpModal.jsx:30
msgid "Read the documentation."
msgstr "Read the documentation."
#: src/components/KeyboardShortcutsModal.jsx:83
msgid "Realign code"
msgstr "Realign code"
#: src/components/KeyboardShortcutsModal.jsx:24
msgid "Refresh preview"
msgstr "Refresh preview"
#: src/components/HelpModal.jsx:102
msgid "Report a bug"
msgstr "Report a bug"
#: src/components/HelpModal.jsx:80
msgid "Review Web Maker"
msgstr "Review Web Maker"
#: src/components/MainHeader.jsx:32
msgid "Run"
msgstr "Run"
#: src/components/MainHeader.jsx:80
#: src/components/KeyboardShortcutsModal.jsx:120
msgid "Run Prettier"
msgstr "Run Prettier"
#: src/components/MainHeader.jsx:26
msgid "Run preview (Ctrl/⌘ + Shift + 5)"
msgstr "Run preview (Ctrl/⌘ + Shift + 5)"
#: src/components/MainHeader.jsx:80
msgid "Save"
msgstr "Save"
#: src/components/Footer.jsx:202
msgid "Save as HTML file"
msgstr "Save as HTML file"
#: src/components/MainHeader.jsx:71
msgid "Save current creation (Ctrl/⌘ + S)"
msgstr "Save current creation (Ctrl/⌘ + S)"
#: src/components/KeyboardShortcutsModal.jsx:30
msgid "Save current creations"
msgstr "Save current creations"
#: src/components/SavedItemPane.jsx:209
msgid "Search your creations here..."
msgstr "Search your creations here..."
#: src/components/Footer.jsx:317
#~ msgid "See Changelog"
#~ msgstr "See Changelog"
#: src/components/HelpModal.jsx:110
msgid "See awesome libraries used"
msgstr "See awesome libraries used"
#: src/components/Footer.jsx:313
msgid "See changelog"
msgstr "See changelog"
#: src/components/MainHeader.jsx:110
msgid "See profile or Logout"
msgstr "See profile or Logout"
#: src/components/KeyboardShortcutsModal.jsx:65
msgid "Select next match"
msgstr "Select next match"
#: src/components/KeyboardShortcutsModal.jsx:71
msgid "Select previous match"
msgstr "Select previous match"
#: src/components/Footer.jsx:325
msgid "Settings"
msgstr "Settings"
#: src/components/MainHeader.jsx:105
#: src/components/MainHeader.jsx:105
msgid "Signup"
msgstr "Signup"
#~ msgid "Signup"
#~ msgstr "Signup"
#: src/components/KeyboardShortcutsModal.jsx:114
msgid "Single line comment"
msgstr "Single line comment"
#: src/components/MainHeader.jsx:58
msgid "Start a new creation"
msgstr "Start a new creation"
#: src/components/HelpModal.jsx:69
msgid "Support the developer"
msgstr "Support the developer"
#: src/components/Footer.jsx:139
msgid "Support the developer by pledging some amount"
msgstr "Support the developer by pledging some amount"
#: src/components/Footer.jsx:289
msgid "Switch to full screen preview"
msgstr "Switch to full screen preview"
#: src/components/Footer.jsx:279
msgid "Switch to layout with all vertical panes"
msgstr "Switch to layout with all vertical panes"
#: src/components/Footer.jsx:259
msgid "Switch to layout with preview on bottom"
msgstr "Switch to layout with preview on bottom"
#: src/components/Footer.jsx:269
msgid "Switch to layout with preview on left"
msgstr "Switch to layout with preview on left"
#: src/components/Footer.jsx:273
#~ msgid "Switch to layout with preview on left\""
#~ msgstr "Switch to layout with preview on left\""
#: src/components/Footer.jsx:249
msgid "Switch to layout with preview on right"
msgstr "Switch to layout with preview on right"
#: src/components/Footer.jsx:236
msgid "Take screenshot of preview"
msgstr "Take screenshot of preview"
#: src/components/Console.jsx:78
msgid "Toggle console"
msgstr "Toggle console"
#: src/components/Footer.jsx:118
msgid "Tweet about 'Web Maker'"
msgstr "Tweet about 'Web Maker'"
#: src/components/HelpModal.jsx:34
#~ msgid "Tweet out your feature requests, comments & suggestions to <0>@webmakerApp</0>"
#~ msgstr "Tweet out your feature requests, comments & suggestions to <0>@webmakerApp</0>"
#: src/components/AddLibrary.jsx:82
msgid "Type here to search libraries"
msgstr "Type here to search libraries"
#: src/components/Footer.jsx:183
msgid "Upload Image"
msgstr "Upload Image"

View File

@ -1,19 +1,106 @@
/* eslint-disable */ export default {
languageData: {
plurals: function(n, ord) {
plurals: function (n, ord) {
if (ord) return 'other';
return n == 1 ? 'one' : 'other';
}
},
messages: {
'Add a JS/CSS library': 'Add a JS/CSS library',
'Add library': 'Add library',
Console: 'Console',
Login: 'Login',
New: 'New',
Open: 'Open',
Run: 'Run',
Save: 'Save',
Signup: 'Signup'
'\'Oops! Selected file is corrupted. Please select a file that was generated by clicking the "Export" button.':
'"Oops! El archivo seleccionado est\xE1 da\xF1ado. Seleccione un archivo que se gener\xF3 haciendo clic en el bot\xF3n "Exportar".',
'Add Library': 'A\xF1adir librer\xEDa',
'Add a JS/CSS library': 'A\xF1adir una librer\xEDa JS/CSS',
'Add library': 'A\xF1adir librer\xEDa',
Chat: 'Chat',
'Choose from popular libraries': 'Elija entre las librer\xEDas populares',
'Clear console (CTRL + L)': 'Borrar consola (CTRL + L)',
'Clear console (works when console input is focused)':
'Borrar consola (funciona cuando la entrada de la consola est\xE1 enfocada)',
'Close saved creations pane': 'Cerrar el panel creaciones guardadas',
'Close saved creations panel & modals':
'Cerrar el panel de creaciones guardadas y modales',
Console: 'Consola',
'Detach preview': 'Separar la vista previa',
Donate: 'Donar',
'Double click to toggle console':
'Haga doble clic para alternar la consola',
'Download game as zip': 'Descargar juego como zip',
'Edit on CodePen': 'Editar en CodePen',
Editor: 'Editor',
'Emmet code completion': 'Finalizaci\xF3n del c\xF3digo Emmet',
Export: 'Exportar',
'Export all your creations into a single importable file.':
'Exporta todas tus creaciones en un \xFAnico archivo importable.',
Find: 'Buscar',
'Find & replace': 'Buscar y reemplazar',
Global: 'Global',
Help: 'Ayuda',
Import: 'Importar',
"Import your creations. Only the file that you export through the 'Export' button can be imported.":
'Importa tus creaciones. S\xF3lo se puede importar el archivo que se exporta a trav\xE9s del bot\xF3n "Exportar".',
'Indent code left': 'Indentar c\xF3digo a la izquierda',
'Indent code right': 'Indentar c\xF3digo a la derecha',
'Keyboard Shortcuts': 'Atajos de Teclado',
'Keyboard shortcuts': 'Atajos de teclado',
License: 'Licencia',
'Login/Signup': 'Iniciar sesi\xF3n/Registrarse',
'My Library ({0})': 'Mi biblioteca',
New: 'Nuevo',
'No match found.': 'No se encontr\xF3 ninguna coincidencia.',
'Note: You can load external scripts only from following domains:':
'Nota: Puedes cargar scripts externos s\xF3lo de los siguientes dominios:',
'Nothing saved here.': 'Aqu\xED no hay nada guardado.',
Open: 'Abrir',
'Open a saved creation (Ctrl/\u2318 + O)':
'Abrir una creaci\xF3n guardada (Ctrl/\u2318 + O)',
'Open list of saved creations': 'Abrir lista de creaciones guardadas',
'Powered by cdnjs': 'Impulsado por cdnjs',
'Put each library in new line':
'Poner cada biblioteca en una nueva l\xEDnea',
'Read more': 'Leer m\xE1s',
'Read the documentation.': 'Leer la documentaci\xF3n.',
'Realign code': 'Reajustar el c\xF3digo',
'Refresh preview': 'Actualizar la vista previa',
'Report a bug': 'Reporta un error',
'Review Web Maker': 'Rese\xF1a de Web Maker',
Run: 'Ejecutar',
'Run Prettier': 'Ejecutar Prettier',
'Run preview (Ctrl/\u2318 + Shift + 5)':
'Ejecutar vista previa (Ctrl/\u2318 + Shift + 5)',
Save: 'Guardar',
'Save as HTML file': 'Guardar como archivo HTML',
'Save current creation (Ctrl/\u2318 + S)':
'Guardar la creaci\xF3n actual (Ctrl/\u2318 + S)',
'Save current creations': 'Guardar las creaciones actuales',
'Search your creations here...': 'Busca tus creaciones aqu\xED...',
'See awesome libraries used':
'Vea las incre\xEDbles librer\xEDas utilizadas',
'See changelog': 'Ver registro de cambios',
'See profile or Logout': 'Ver perfil o cerrar sesi\xF3n',
'Select next match': 'Seleccione el siguiente partido',
'Select previous match': 'Seleccione el partido anterior',
Settings: 'Ajustes',
'Single line comment': 'Comentario de una sola l\xEDnea',
'Start a new creation': 'Iniciar una nueva creaci\xF3n',
'Support the developer': 'Apoyar al desarrollador',
'Support the developer by pledging some amount':
'Apoyar al desarrollador donando alguna cantidad',
'Switch to full screen preview':
'Cambiar a vista previa de pantalla completa',
'Switch to layout with all vertical panes':
'Cambiar a la disposici\xF3n con todos los paneles verticales',
'Switch to layout with preview on bottom':
'Cambiar al dise\xF1o con vista previa en la parte inferior',
'Switch to layout with preview on left':
'Cambiar al dise\xF1o con vista previa a la izquierda',
'Switch to layout with preview on right':
'Cambiar al dise\xF1o con vista previa a la derecha',
'Take screenshot of preview':
'Tomar captura de pantalla de la vista previa',
'Toggle console': 'Alternar consola',
"Tweet about 'Web Maker'": "Tuitea sobre 'Web Maker'",
'Type here to search libraries':
'Escriba aqu\xED para buscar en las librer\xEDas',
'Upload Image': 'Cargar imagen'
}
};

View File

@ -4,55 +4,316 @@ msgstr ""
"Mime-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"X-Generator: Poedit 2.3.1\n"
"Language: es\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Last-Translator: Lenin Peña <leninalbertolp@gmail.com>\n"
"Language-Team: \n"
"Plural-Forms: \n"
"MIME-Version: 1.0\n"
#: src/components/SavedItemPane.jsx:116
msgid "'Oops! Selected file is corrupted. Please select a file that was generated by clicking the \"Export\" button."
msgstr "\"Oops! El archivo seleccionado está dañado. Seleccione un archivo que se generó haciendo clic en el botón \"Exportar\"."
#: src/components/AddLibrary.jsx:67
msgid "Add Library"
msgstr "Añadir librería"
#: src/components/MainHeader.jsx:41
msgid "Add a JS/CSS library"
msgstr ""
msgstr "Añadir una librería JS/CSS"
#: src/components/MainHeader.jsx:43
#: src/components/MainHeader.jsx:43
msgid "Add library"
msgstr ""
msgstr "Añadir librería"
#: src/components/Console.jsx:58
#: src/components/Console.jsx:58
#: src/components/HelpModal.jsx:91
msgid "Chat"
msgstr "Chat"
#: src/components/AddLibrary.jsx:92
msgid "Choose from popular libraries"
msgstr "Elija entre las librerías populares"
#: src/components/Console.jsx:69
msgid "Clear console (CTRL + L)"
msgstr "Borrar consola (CTRL + L)"
#: src/components/KeyboardShortcutsModal.jsx:42
msgid "Clear console (works when console input is focused)"
msgstr "Borrar consola (funciona cuando la entrada de la consola está enfocada)"
#: src/components/SavedItemPane.jsx:170
msgid "Close saved creations pane"
msgstr "Cerrar el panel creaciones guardadas"
#: src/components/KeyboardShortcutsModal.jsx:48
msgid "Close saved creations panel & modals"
msgstr "Cerrar el panel de creaciones guardadas y modales"
#: src/components/Console.jsx:61
msgid "Console"
msgstr ""
msgstr "Consola"
#: src/components/MainHeader.jsx:105
#: src/components/MainHeader.jsx:105
msgid "Login"
msgstr ""
#: src/components/Footer.jsx:297
msgid "Detach preview"
msgstr "Separar la vista previa"
#: src/components/Footer.jsx:142
msgid "Donate"
msgstr "Donar"
#: src/components/Console.jsx:57
msgid "Double click to toggle console"
msgstr "Haga doble clic para alternar la consola"
#: src/components/Footer.jsx:170
msgid "Download game as zip"
msgstr "Descargar juego como zip"
#: src/components/Footer.jsx:225
msgid "Edit on CodePen"
msgstr "Editar en CodePen"
#: src/components/KeyboardShortcutsModal.jsx:54
msgid "Editor"
msgstr "Editor"
#: src/components/KeyboardShortcutsModal.jsx:101
msgid "Emmet code completion"
msgstr "Finalización del código Emmet"
#: src/components/SavedItemPane.jsx:190
msgid "Export"
msgstr "Exportar"
#: src/components/SavedItemPane.jsx:187
msgid "Export all your creations into a single importable file."
msgstr "Exporta todas tus creaciones en un único archivo importable."
#: src/components/KeyboardShortcutsModal.jsx:59
msgid "Find"
msgstr "Buscar"
#: src/components/KeyboardShortcutsModal.jsx:77
msgid "Find & replace"
msgstr "Buscar y reemplazar"
#: src/components/KeyboardShortcutsModal.jsx:15
msgid "Global"
msgstr "Global"
#: src/components/Footer.jsx:90 src/components/Footer.jsx:190
msgid "Help"
msgstr "Ayuda"
#: src/components/SavedItemPane.jsx:199
msgid "Import"
msgstr "Importar"
#: src/components/SavedItemPane.jsx:196
msgid "Import your creations. Only the file that you export through the 'Export' button can be imported."
msgstr "Importa tus creaciones. Sólo se puede importar el archivo que se exporta a través del botón \"Exportar\"."
#: src/components/KeyboardShortcutsModal.jsx:95
msgid "Indent code left"
msgstr "Indentar código a la izquierda"
#: src/components/KeyboardShortcutsModal.jsx:89
msgid "Indent code right"
msgstr "Indentar código a la derecha"
#: src/components/KeyboardShortcutsModal.jsx:9
msgid "Keyboard Shortcuts"
msgstr "Atajos de Teclado"
#: src/components/Footer.jsx:104
msgid "Keyboard shortcuts"
msgstr "Atajos de teclado"
#: src/components/HelpModal.jsx:195
msgid "License"
msgstr "Licencia"
#: src/components/MainHeader.jsx:104
msgid "Login/Signup"
msgstr "Iniciar sesión/Registrarse"
#: src/components/SavedItemPane.jsx:179
msgid "My Library ({0})"
msgstr "Mi biblioteca"
#: src/components/MainHeader.jsx:64
#: src/components/MainHeader.jsx:64
msgid "New"
msgstr ""
msgstr "Nuevo"
#: src/components/SavedItemPane.jsx:215
msgid "No match found."
msgstr "No se encontró ninguna coincidencia."
#: src/components/AddLibrary.jsx:125
msgid "Note: You can load external scripts only from following domains:"
msgstr "Nota: Puedes cargar scripts externos sólo de los siguientes dominios:"
#: src/components/SavedItemPane.jsx:232
msgid "Nothing saved here."
msgstr "Aquí no hay nada guardado."
#: src/components/MainHeader.jsx:96
#: src/components/MainHeader.jsx:96
msgid "Open"
msgstr ""
msgstr "Abrir"
#: src/components/MainHeader.jsx:87
msgid "Open a saved creation (Ctrl/⌘ + O)"
msgstr "Abrir una creación guardada (Ctrl/⌘ + O)"
#: src/components/KeyboardShortcutsModal.jsx:36
msgid "Open list of saved creations"
msgstr "Abrir lista de creaciones guardadas"
#: src/components/AddLibrary.jsx:88
msgid "Powered by cdnjs"
msgstr "Impulsado por cdnjs"
#: src/components/AddLibrary.jsx:118 src/components/AddLibrary.jsx:147
msgid "Put each library in new line"
msgstr "Poner cada biblioteca en una nueva línea"
#: src/components/KeyboardShortcutsModal.jsx:107
msgid "Read more"
msgstr "Leer más"
#: src/components/HelpModal.jsx:30
msgid "Read the documentation."
msgstr "Leer la documentación."
#: src/components/KeyboardShortcutsModal.jsx:83
msgid "Realign code"
msgstr "Reajustar el código"
#: src/components/KeyboardShortcutsModal.jsx:24
msgid "Refresh preview"
msgstr "Actualizar la vista previa"
#: src/components/HelpModal.jsx:102
msgid "Report a bug"
msgstr "Reporta un error"
#: src/components/HelpModal.jsx:80
msgid "Review Web Maker"
msgstr "Reseña de Web Maker"
#: src/components/MainHeader.jsx:32
#: src/components/MainHeader.jsx:32
msgid "Run"
msgstr ""
msgstr "Ejecutar"
#: src/components/KeyboardShortcutsModal.jsx:120
msgid "Run Prettier"
msgstr "Ejecutar Prettier"
#: src/components/MainHeader.jsx:26
msgid "Run preview (Ctrl/⌘ + Shift + 5)"
msgstr "Ejecutar vista previa (Ctrl/⌘ + Shift + 5)"
#: src/components/MainHeader.jsx:80
#: src/components/MainHeader.jsx:80
msgid "Save"
msgstr ""
msgstr "Guardar"
#: src/components/MainHeader.jsx:105
#: src/components/MainHeader.jsx:105
msgid "Signup"
msgstr ""
#: src/components/Footer.jsx:202
msgid "Save as HTML file"
msgstr "Guardar como archivo HTML"
#: src/components/MainHeader.jsx:71
msgid "Save current creation (Ctrl/⌘ + S)"
msgstr "Guardar la creación actual (Ctrl/⌘ + S)"
#: src/components/KeyboardShortcutsModal.jsx:30
msgid "Save current creations"
msgstr "Guardar las creaciones actuales"
#: src/components/SavedItemPane.jsx:209
msgid "Search your creations here..."
msgstr "Busca tus creaciones aquí..."
#: src/components/HelpModal.jsx:110
msgid "See awesome libraries used"
msgstr "Vea las increíbles librerías utilizadas"
#: src/components/Footer.jsx:313
msgid "See changelog"
msgstr "Ver registro de cambios"
#: src/components/MainHeader.jsx:110
msgid "See profile or Logout"
msgstr "Ver perfil o cerrar sesión"
#: src/components/KeyboardShortcutsModal.jsx:65
msgid "Select next match"
msgstr "Seleccione el siguiente partido"
#: src/components/KeyboardShortcutsModal.jsx:71
msgid "Select previous match"
msgstr "Seleccione el partido anterior"
#: src/components/Footer.jsx:325
msgid "Settings"
msgstr "Ajustes"
#: src/components/KeyboardShortcutsModal.jsx:114
msgid "Single line comment"
msgstr "Comentario de una sola línea"
#: src/components/MainHeader.jsx:58
msgid "Start a new creation"
msgstr "Iniciar una nueva creación"
#: src/components/HelpModal.jsx:69
msgid "Support the developer"
msgstr "Apoyar al desarrollador"
#: src/components/Footer.jsx:139
msgid "Support the developer by pledging some amount"
msgstr "Apoyar al desarrollador donando alguna cantidad"
#: src/components/Footer.jsx:289
msgid "Switch to full screen preview"
msgstr "Cambiar a vista previa de pantalla completa"
#: src/components/Footer.jsx:279
msgid "Switch to layout with all vertical panes"
msgstr "Cambiar a la disposición con todos los paneles verticales"
#: src/components/Footer.jsx:259
msgid "Switch to layout with preview on bottom"
msgstr "Cambiar al diseño con vista previa en la parte inferior"
#: src/components/Footer.jsx:269
msgid "Switch to layout with preview on left"
msgstr "Cambiar al diseño con vista previa a la izquierda"
#: src/components/Footer.jsx:249
msgid "Switch to layout with preview on right"
msgstr "Cambiar al diseño con vista previa a la derecha"
#: src/components/Footer.jsx:236
msgid "Take screenshot of preview"
msgstr "Tomar captura de pantalla de la vista previa"
#: src/components/Console.jsx:78
msgid "Toggle console"
msgstr "Alternar consola"
#: src/components/Footer.jsx:118
msgid "Tweet about 'Web Maker'"
msgstr "Tuitea sobre 'Web Maker'"
#: src/components/AddLibrary.jsx:82
msgid "Type here to search libraries"
msgstr "Escriba aquí para buscar en las librerías"
#: src/components/Footer.jsx:183
msgid "Upload Image"
msgstr "Cargar imagen"

View File

@ -1,6 +1,6 @@
/* eslint-disable */ export default {
languageData: {
plurals: function(n, ord) {
plurals: function (n, ord) {
if (ord)
return n == 1
? 'one'
@ -15,14 +15,121 @@
}
},
messages: {
'"Web Maker" <0>CHill</0>.': '"Web Maker" <0>CHill</0>.',
'\'Oops! Selected file is corrupted. Please select a file that was generated by clicking the "Export" button.':
'\'Oops! Selected file is corrupted. Please select a file that was generated by clicking the "Export" button.',
'Add Library':
'\u0932\u093E\u0907\u092C\u094D\u0930\u0947\u0930\u0940 \u091C\u094B\u0921\u093C\u0947\u0902',
'Add a JS/CSS library': 'Add a JS/CSS library',
'Add library': 'Add library',
'Add library':
'\u0932\u093E\u0907\u092C\u094D\u0930\u0947\u0930\u0940 \u091C\u094B\u0921\u093C\u0947\u0902',
Chat: 'Chat',
'Choose from popular libraries': 'Choose from popular libraries',
'Clear console (CTRL + L)': 'Clear console (CTRL + L)',
'Clear console (works when console input is focused)':
'Clear console (works when console input is focused)',
'Close saved creations pane': 'Close saved creations pane',
'Close saved creations panel & modals':
'Close saved creations panel & modals',
Console: 'Console',
'Detach Preview': 'Detach Preview',
'Detach preview': 'Detach preview',
Donate: '\u0926\u093E\u0928 \u0915\u0930\u0947\u0902',
'Double click to toggle console': 'Double click to toggle console',
'Download game as zip': 'Download game as zip',
'Edit on CodePen': 'Edit on CodePen',
Editor: 'Editor',
'Emmet code completion': 'Emmet code completion',
Export: 'Export',
'Export all your creations into a single importable file.':
'Export all your creations into a single importable file.',
Find: 'Find',
'Find & replace': 'Find & replace',
Global: 'Global',
Help: 'Help',
Import: 'Import',
"Import your creations. Only the file that you export through the 'Export' button can be imported.":
"Import your creations. Only the file that you export through the 'Export' button can be imported.",
'Indent code left': 'Indent code left',
'Indent code right': 'Indent code right',
'Keyboard Shortcuts': 'Keyboard Shortcuts',
'Keyboard shortcuts': 'Keyboard shortcuts',
License: 'License',
'Like this extension? Please <0>rate it here</0>.':
'Like this extension? Please <0>rate it here</0>.',
Login: '\u0932\u0949\u0917\u093F\u0928',
'Login/Signup':
'\u0932\u0949\u0917\u093F\u0928 / \u0938\u093E\u0907\u0928\u092A',
'Made with <0>\uD83D\uDC96</0>& <1> \uD83D\uDE4C</1> by <2>Kushagra Gour</2>':
'<0>\uD83D\uDC96</0> \u0914\u0930 <1> \uD83D\uDE4C</1> \u0938\u0947 <2>\u0915\u0941\u0936\u093E\u0917\u094D\u0930 \u0917\u094C\u0930</2> \u0926\u094D\u0935\u093E\u0930\u093E \u092C\u0928\u093E\u092F\u093E \u0917\u092F\u093E',
'My Library ({0})': function (a) {
return [
'\u092E\u0947\u0930\u0940 \u0930\u091A\u0928\u093E\u090F\u0901 (',
a('0'),
')'
];
},
New: '\u0928\u092F\u093E \u092C\u0928\u093E\u090F\u0901',
Open: 'Open',
Run: 'Run',
Save: 'Save',
Signup: 'Signup'
'No match found.':
'\u0915\u0941\u091B \u0928\u0939\u0940\u0902 \u092E\u093F\u0932\u093E',
'Note: You can load external scripts from following domains:':
'Note: You can load external scripts from following domains:',
'Note: You can load external scripts only from following domains:':
'Note: You can load external scripts only from following domains:',
'Nothing saved here.': 'Nothing saved here.',
Open: '\u0916\u094B\u0932\u0947\u0902',
'Open a saved creation (Ctrl/\u2318 + O)':
'Open a saved creation (Ctrl/\u2318 + O)',
'Open list of saved creations': 'Open list of saved creations',
'Powered by cdnjs': 'Powered by cdnjs',
'Put each library in new line':
'\u0939\u0930 \u0932\u093E\u0907\u092C\u094D\u0930\u0947\u0930\u0940 \u0928\u0908 \u0932\u093E\u0907\u0928 \u092E\u0948\u0902 \u0932\u093F\u0916\u0947\u0902',
'Read more': '\u0914\u0930 \u091C\u093E\u0928\u0947\u0902',
'Read the documentation.': 'Read the documentation.',
'Realign code': 'Realign code',
'Refresh preview': 'Refresh preview',
'Report a bug': 'Report a bug',
'Review Web Maker': 'Review Web Maker',
Run: '\u091A\u0932\u093E\u090F\u0901',
'Run Prettier': 'Run Prettier',
'Run preview (Ctrl/\u2318 + Shift + 5)':
'Run preview (Ctrl/\u2318 + Shift + 5)',
Save: '\u0938\u0941\u0930\u0915\u094D\u0937\u093F\u0924 \u0915\u0930\u0947\u0902',
'Save as HTML file': 'Save as HTML file',
'Save current creation (Ctrl/\u2318 + S)':
'Save current creation (Ctrl/\u2318 + S)',
'Save current creations': 'Save current creations',
'Search your creations here...': 'Search your creations here...',
'See Changelog': 'See Changelog',
'See awesome libraries used': 'See awesome libraries used',
'See changelog': 'See changelog',
'See profile or Logout': 'See profile or Logout',
'Select next match': 'Select next match',
'Select previous match': 'Select previous match',
Settings: 'Settings',
Signup: 'Signup',
'Single line comment': 'Single line comment',
'Start a new creation': 'Start a new creation',
'Support the developer': 'Support the developer',
'Support the developer by pledging some amount':
'Support the developer by pledging some amount',
'Switch to full screen preview': 'Switch to full screen preview',
'Switch to layout with all vertical panes':
'Switch to layout with all vertical panes',
'Switch to layout with preview on bottom':
'Switch to layout with preview on bottom',
'Switch to layout with preview on left':
'Switch to layout with preview on left',
'Switch to layout with preview on left"':
'Switch to layout with preview on left"',
'Switch to layout with preview on right':
'Switch to layout with preview on right',
'Take screenshot of preview': 'Take screenshot of preview',
'Toggle console': 'Toggle console',
"Tweet about 'Web Maker'": "Tweet about 'Web Maker'",
'Tweet out your feature requests, comments & suggestions to <0>@webmakerApp</0>':
'\u0939\u0932\u0935\u093E \u0939\u093F\u092F\u093E\u0901 \u092F\u0947 \u0924\u094B <0>\u091A\u092E\u092A\u094D\u0930\u0936</0>',
'Type here to search libraries': 'Type here to search libraries',
'Upload Image': 'Upload Image'
}
};

View File

@ -13,46 +13,350 @@ msgstr ""
"Language-Team: \n"
"Plural-Forms: \n"
#: src/components/HelpModal.jsx:201
#~ msgid "\"Web Maker\" <0>CHill</0>."
#~ msgstr ""
#: src/components/SavedItemPane.jsx:116
msgid "'Oops! Selected file is corrupted. Please select a file that was generated by clicking the \"Export\" button."
msgstr ""
#: src/components/AddLibrary.jsx:67
msgid "Add Library"
msgstr "लाइब्रेरी जोड़ें"
#: src/components/MainHeader.jsx:41
msgid "Add a JS/CSS library"
msgstr ""
#: src/components/MainHeader.jsx:43
#: src/components/MainHeader.jsx:43
msgid "Add library"
msgstr "लाइब्रेरी जोड़ें"
#: src/components/HelpModal.jsx:91
msgid "Chat"
msgstr ""
#: src/components/Console.jsx:58
#: src/components/Console.jsx:58
#: src/components/AddLibrary.jsx:92
msgid "Choose from popular libraries"
msgstr ""
#: src/components/Console.jsx:69
msgid "Clear console (CTRL + L)"
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:42
msgid "Clear console (works when console input is focused)"
msgstr ""
#: src/components/SavedItemPane.jsx:170
msgid "Close saved creations pane"
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:48
msgid "Close saved creations panel & modals"
msgstr ""
#: src/components/Console.jsx:61
msgid "Console"
msgstr ""
#: src/components/MainHeader.jsx:105
#: src/components/MainHeader.jsx:105
msgid "Login"
msgstr "लॉगिन"
#: src/components/Footer.jsx:301
#~ msgid "Detach Preview"
#~ msgstr ""
#: src/components/Footer.jsx:297
msgid "Detach preview"
msgstr ""
#: src/components/Footer.jsx:142
msgid "Donate"
msgstr "दान करें"
#: src/components/Console.jsx:57
msgid "Double click to toggle console"
msgstr ""
#: src/components/Footer.jsx:170
msgid "Download game as zip"
msgstr ""
#: src/components/Footer.jsx:225
msgid "Edit on CodePen"
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:54
msgid "Editor"
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:101
msgid "Emmet code completion"
msgstr ""
#: src/components/SavedItemPane.jsx:190
msgid "Export"
msgstr ""
#: src/components/SavedItemPane.jsx:187
msgid "Export all your creations into a single importable file."
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:59
msgid "Find"
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:77
msgid "Find & replace"
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:15
msgid "Global"
msgstr ""
#: src/components/Footer.jsx:90
#: src/components/Footer.jsx:190
msgid "Help"
msgstr ""
#: src/components/SavedItemPane.jsx:199
msgid "Import"
msgstr ""
#: src/components/SavedItemPane.jsx:196
msgid "Import your creations. Only the file that you export through the 'Export' button can be imported."
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:95
msgid "Indent code left"
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:89
msgid "Indent code right"
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:9
msgid "Keyboard Shortcuts"
msgstr ""
#: src/components/Footer.jsx:104
msgid "Keyboard shortcuts"
msgstr ""
#: src/components/HelpModal.jsx:195
msgid "License"
msgstr ""
#: src/components/HelpModal.jsx:47
#~ msgid "Like this extension? Please <0>rate it here</0>."
#~ msgstr ""
#: src/components/MainHeader.jsx:105
#: src/components/MainHeader.jsx:105
#~ msgid "Login"
#~ msgstr "लॉगिन"
#: src/components/MainHeader.jsx:104
msgid "Login/Signup"
msgstr "लॉगिन / साइनप"
#: src/components/HelpModal.jsx:16
#~ msgid "Made with <0>💖</0>& <1> 🙌</1> by <2>Kushagra Gour</2>"
#~ msgstr "<0>💖</0> और <1> 🙌</1> से <2>कुशाग्र गौर</2> द्वारा बनाया गया"
#: src/components/SavedItemPane.jsx:179
msgid "My Library ({0})"
msgstr "मेरी रचनाएँ ({0})"
#: src/components/MainHeader.jsx:64
#: src/components/MainHeader.jsx:64
msgid "New"
msgstr "नया बनाएँ"
#: src/components/MainHeader.jsx:96
#: src/components/SavedItemPane.jsx:215
msgid "No match found."
msgstr "कुछ नहीं मिला"
#: src/components/AddLibrary.jsx:125
#~ msgid "Note: You can load external scripts from following domains:"
#~ msgstr ""
#: src/components/AddLibrary.jsx:125
msgid "Note: You can load external scripts only from following domains:"
msgstr ""
#: src/components/SavedItemPane.jsx:232
msgid "Nothing saved here."
msgstr ""
#: src/components/MainHeader.jsx:96
msgid "Open"
msgstr "खोलें"
#: src/components/MainHeader.jsx:32
#: src/components/MainHeader.jsx:87
msgid "Open a saved creation (Ctrl/⌘ + O)"
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:36
msgid "Open list of saved creations"
msgstr ""
#: src/components/AddLibrary.jsx:88
msgid "Powered by cdnjs"
msgstr ""
#: src/components/AddLibrary.jsx:118
#: src/components/AddLibrary.jsx:147
msgid "Put each library in new line"
msgstr "हर लाइब्रेरी नई लाइन मैं लिखें"
#: src/components/KeyboardShortcutsModal.jsx:107
msgid "Read more"
msgstr "और जानें"
#: src/components/HelpModal.jsx:30
msgid "Read the documentation."
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:83
msgid "Realign code"
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:24
msgid "Refresh preview"
msgstr ""
#: src/components/HelpModal.jsx:102
msgid "Report a bug"
msgstr ""
#: src/components/HelpModal.jsx:80
msgid "Review Web Maker"
msgstr ""
#: src/components/MainHeader.jsx:32
msgid "Run"
msgstr "चलाएँ"
#: src/components/MainHeader.jsx:80
#: src/components/KeyboardShortcutsModal.jsx:120
msgid "Run Prettier"
msgstr ""
#: src/components/MainHeader.jsx:26
msgid "Run preview (Ctrl/⌘ + Shift + 5)"
msgstr ""
#: src/components/MainHeader.jsx:80
msgid "Save"
msgstr "सुरक्षित करें"
#: src/components/Footer.jsx:202
msgid "Save as HTML file"
msgstr ""
#: src/components/MainHeader.jsx:71
msgid "Save current creation (Ctrl/⌘ + S)"
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:30
msgid "Save current creations"
msgstr ""
#: src/components/SavedItemPane.jsx:209
msgid "Search your creations here..."
msgstr ""
#: src/components/Footer.jsx:317
#~ msgid "See Changelog"
#~ msgstr ""
#: src/components/HelpModal.jsx:110
msgid "See awesome libraries used"
msgstr ""
#: src/components/Footer.jsx:313
msgid "See changelog"
msgstr ""
#: src/components/MainHeader.jsx:110
msgid "See profile or Logout"
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:65
msgid "Select next match"
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:71
msgid "Select previous match"
msgstr ""
#: src/components/Footer.jsx:325
msgid "Settings"
msgstr ""
#: src/components/MainHeader.jsx:105
#: src/components/MainHeader.jsx:105
msgid "Signup"
#~ msgid "Signup"
#~ msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:114
msgid "Single line comment"
msgstr ""
#: src/components/MainHeader.jsx:58
msgid "Start a new creation"
msgstr ""
#: src/components/HelpModal.jsx:69
msgid "Support the developer"
msgstr ""
#: src/components/Footer.jsx:139
msgid "Support the developer by pledging some amount"
msgstr ""
#: src/components/Footer.jsx:289
msgid "Switch to full screen preview"
msgstr ""
#: src/components/Footer.jsx:279
msgid "Switch to layout with all vertical panes"
msgstr ""
#: src/components/Footer.jsx:259
msgid "Switch to layout with preview on bottom"
msgstr ""
#: src/components/Footer.jsx:269
msgid "Switch to layout with preview on left"
msgstr ""
#: src/components/Footer.jsx:273
#~ msgid "Switch to layout with preview on left\""
#~ msgstr ""
#: src/components/Footer.jsx:249
msgid "Switch to layout with preview on right"
msgstr ""
#: src/components/Footer.jsx:236
msgid "Take screenshot of preview"
msgstr ""
#: src/components/Console.jsx:78
msgid "Toggle console"
msgstr ""
#: src/components/Footer.jsx:118
msgid "Tweet about 'Web Maker'"
msgstr ""
#: src/components/HelpModal.jsx:34
#~ msgid "Tweet out your feature requests, comments & suggestions to <0>@webmakerApp</0>"
#~ msgstr "हलवा हियाँ ये तो <0>चमप्रश</0>"
#: src/components/AddLibrary.jsx:82
msgid "Type here to search libraries"
msgstr ""
#: src/components/Footer.jsx:183
msgid "Upload Image"
msgstr ""

View File

@ -1,19 +1,117 @@
/* eslint-disable */ export default {
languageData: {
plurals: function(n, ord) {
plurals: function (n, ord) {
if (ord) return 'other';
return 'other';
}
},
messages: {
'"Web Maker" <0>CHill</0>.': '"Web Maker" <0>CHill</0>.',
'\'Oops! Selected file is corrupted. Please select a file that was generated by clicking the "Export" button.':
'\'Oops! Selected file is corrupted. Please select a file that was generated by clicking the "Export" button.',
'Add Library': 'Add Library',
'Add a JS/CSS library': 'Add a JS/CSS library',
'Add library': 'Add library',
Chat: 'Chat',
'Choose from popular libraries': 'Choose from popular libraries',
'Clear console (CTRL + L)': 'Clear console (CTRL + L)',
'Clear console (works when console input is focused)':
'Clear console (works when console input is focused)',
'Close saved creations pane': 'Close saved creations pane',
'Close saved creations panel & modals':
'Close saved creations panel & modals',
Console: 'Console',
'Detach Preview': 'Detach Preview',
'Detach preview': 'Detach preview',
Donate: 'Donate',
'Double click to toggle console': 'Double click to toggle console',
'Download game as zip': 'Download game as zip',
'Edit on CodePen': 'Edit on CodePen',
Editor: 'Editor',
'Emmet code completion': 'Emmet code completion',
Export: 'Export',
'Export all your creations into a single importable file.':
'Export all your creations into a single importable file.',
Find: 'Find',
'Find & replace': 'Find & replace',
Global: 'Global',
Help: 'Help',
Import: 'Import',
"Import your creations. Only the file that you export through the 'Export' button can be imported.":
"Import your creations. Only the file that you export through the 'Export' button can be imported.",
'Indent code left': 'Indent code left',
'Indent code right': 'Indent code right',
'Keyboard Shortcuts': 'Keyboard Shortcuts',
'Keyboard shortcuts': 'Keyboard shortcuts',
License: 'License',
'Like this extension? Please <0>rate it here</0>.':
'Like this extension? Please <0>rate it here</0>.',
Login: 'Login',
'Login/Signup': 'Login/Signup',
'Made with <0>\uD83D\uDC96</0>& <1> \uD83D\uDE4C</1> by <2>Kushagra Gour</2>':
'Made with <0>\uD83D\uDC96</0>& <1> \uD83D\uDE4C</1> by <2>Kushagra Gour</2>',
'My Library ({0})': function (a) {
return ['My Library (', a('0'), ')'];
},
New: 'New',
'No match found.': 'No match found.',
'Note: You can load external scripts from following domains:':
'Note: You can load external scripts from following domains:',
'Note: You can load external scripts only from following domains:':
'Note: You can load external scripts only from following domains:',
'Nothing saved here.': 'Nothing saved here.',
Open: 'Open',
'Open a saved creation (Ctrl/\u2318 + O)':
'Open a saved creation (Ctrl/\u2318 + O)',
'Open list of saved creations': 'Open list of saved creations',
'Powered by cdnjs': 'Powered by cdnjs',
'Put each library in new line': 'Put each library in new line',
'Read more': 'Read more',
'Read the documentation.': 'Read the documentation.',
'Realign code': 'Realign code',
'Refresh preview': 'Refresh preview',
'Report a bug': 'Report a bug',
'Review Web Maker': 'Review Web Maker',
Run: 'Run',
'Run Prettier': 'Run Prettier',
'Run preview (Ctrl/\u2318 + Shift + 5)':
'Run preview (Ctrl/\u2318 + Shift + 5)',
Save: 'Save',
Signup: 'Signup'
'Save as HTML file': 'Save as HTML file',
'Save current creation (Ctrl/\u2318 + S)':
'Save current creation (Ctrl/\u2318 + S)',
'Save current creations': 'Save current creations',
'Search your creations here...': 'Search your creations here...',
'See Changelog': 'See Changelog',
'See awesome libraries used': 'See awesome libraries used',
'See changelog': 'See changelog',
'See profile or Logout': 'See profile or Logout',
'Select next match': 'Select next match',
'Select previous match': 'Select previous match',
Settings: 'Settings',
Signup: 'Signup',
'Single line comment': 'Single line comment',
'Start a new creation': 'Start a new creation',
'Support the developer': 'Support the developer',
'Support the developer by pledging some amount':
'Support the developer by pledging some amount',
'Switch to full screen preview': 'Switch to full screen preview',
'Switch to layout with all vertical panes':
'Switch to layout with all vertical panes',
'Switch to layout with preview on bottom':
'Switch to layout with preview on bottom',
'Switch to layout with preview on left':
'Switch to layout with preview on left',
'Switch to layout with preview on left"':
'Switch to layout with preview on left"',
'Switch to layout with preview on right':
'Switch to layout with preview on right',
'Take screenshot of preview': 'Take screenshot of preview',
'Toggle console': 'Toggle console',
"Tweet about 'Web Maker'": "Tweet about 'Web Maker'",
'Tweet out your feature requests, comments & suggestions to <0>@webmakerApp</0>':
'Tweet out your feature requests, comments & suggestions to <0>@webmakerApp</0>',
'Type here to search libraries': 'Type here to search libraries',
'Upload Image': 'Upload Image'
}
};

View File

@ -13,46 +13,350 @@ msgstr ""
"Language-Team: \n"
"Plural-Forms: \n"
#: src/components/HelpModal.jsx:201
#~ msgid "\"Web Maker\" <0>CHill</0>."
#~ msgstr ""
#: src/components/SavedItemPane.jsx:116
msgid "'Oops! Selected file is corrupted. Please select a file that was generated by clicking the \"Export\" button."
msgstr ""
#: src/components/AddLibrary.jsx:67
msgid "Add Library"
msgstr ""
#: src/components/MainHeader.jsx:41
msgid "Add a JS/CSS library"
msgstr ""
#: src/components/MainHeader.jsx:43
#: src/components/MainHeader.jsx:43
msgid "Add library"
msgstr ""
#: src/components/Console.jsx:58
#: src/components/Console.jsx:58
#: src/components/HelpModal.jsx:91
msgid "Chat"
msgstr ""
#: src/components/AddLibrary.jsx:92
msgid "Choose from popular libraries"
msgstr ""
#: src/components/Console.jsx:69
msgid "Clear console (CTRL + L)"
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:42
msgid "Clear console (works when console input is focused)"
msgstr ""
#: src/components/SavedItemPane.jsx:170
msgid "Close saved creations pane"
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:48
msgid "Close saved creations panel & modals"
msgstr ""
#: src/components/Console.jsx:61
msgid "Console"
msgstr ""
#: src/components/MainHeader.jsx:105
#: src/components/MainHeader.jsx:105
msgid "Login"
#: src/components/Footer.jsx:301
#~ msgid "Detach Preview"
#~ msgstr ""
#: src/components/Footer.jsx:297
msgid "Detach preview"
msgstr ""
#: src/components/Footer.jsx:142
msgid "Donate"
msgstr ""
#: src/components/Console.jsx:57
msgid "Double click to toggle console"
msgstr ""
#: src/components/Footer.jsx:170
msgid "Download game as zip"
msgstr ""
#: src/components/Footer.jsx:225
msgid "Edit on CodePen"
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:54
msgid "Editor"
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:101
msgid "Emmet code completion"
msgstr ""
#: src/components/SavedItemPane.jsx:190
msgid "Export"
msgstr ""
#: src/components/SavedItemPane.jsx:187
msgid "Export all your creations into a single importable file."
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:59
msgid "Find"
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:77
msgid "Find & replace"
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:15
msgid "Global"
msgstr ""
#: src/components/Footer.jsx:90
#: src/components/Footer.jsx:190
msgid "Help"
msgstr ""
#: src/components/SavedItemPane.jsx:199
msgid "Import"
msgstr ""
#: src/components/SavedItemPane.jsx:196
msgid "Import your creations. Only the file that you export through the 'Export' button can be imported."
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:95
msgid "Indent code left"
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:89
msgid "Indent code right"
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:9
msgid "Keyboard Shortcuts"
msgstr ""
#: src/components/Footer.jsx:104
msgid "Keyboard shortcuts"
msgstr ""
#: src/components/HelpModal.jsx:195
msgid "License"
msgstr ""
#: src/components/HelpModal.jsx:47
#~ msgid "Like this extension? Please <0>rate it here</0>."
#~ msgstr ""
#: src/components/MainHeader.jsx:105
#: src/components/MainHeader.jsx:105
#~ msgid "Login"
#~ msgstr ""
#: src/components/MainHeader.jsx:104
msgid "Login/Signup"
msgstr ""
#: src/components/HelpModal.jsx:16
#~ msgid "Made with <0>💖</0>& <1> 🙌</1> by <2>Kushagra Gour</2>"
#~ msgstr ""
#: src/components/SavedItemPane.jsx:179
msgid "My Library ({0})"
msgstr ""
#: src/components/MainHeader.jsx:64
#: src/components/MainHeader.jsx:64
msgid "New"
msgstr ""
#: src/components/MainHeader.jsx:96
#: src/components/SavedItemPane.jsx:215
msgid "No match found."
msgstr ""
#: src/components/AddLibrary.jsx:125
#~ msgid "Note: You can load external scripts from following domains:"
#~ msgstr ""
#: src/components/AddLibrary.jsx:125
msgid "Note: You can load external scripts only from following domains:"
msgstr ""
#: src/components/SavedItemPane.jsx:232
msgid "Nothing saved here."
msgstr ""
#: src/components/MainHeader.jsx:96
msgid "Open"
msgstr ""
#: src/components/MainHeader.jsx:32
#: src/components/MainHeader.jsx:87
msgid "Open a saved creation (Ctrl/⌘ + O)"
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:36
msgid "Open list of saved creations"
msgstr ""
#: src/components/AddLibrary.jsx:88
msgid "Powered by cdnjs"
msgstr ""
#: src/components/AddLibrary.jsx:118
#: src/components/AddLibrary.jsx:147
msgid "Put each library in new line"
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:107
msgid "Read more"
msgstr ""
#: src/components/HelpModal.jsx:30
msgid "Read the documentation."
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:83
msgid "Realign code"
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:24
msgid "Refresh preview"
msgstr ""
#: src/components/HelpModal.jsx:102
msgid "Report a bug"
msgstr ""
#: src/components/HelpModal.jsx:80
msgid "Review Web Maker"
msgstr ""
#: src/components/MainHeader.jsx:32
msgid "Run"
msgstr ""
#: src/components/MainHeader.jsx:80
#: src/components/KeyboardShortcutsModal.jsx:120
msgid "Run Prettier"
msgstr ""
#: src/components/MainHeader.jsx:26
msgid "Run preview (Ctrl/⌘ + Shift + 5)"
msgstr ""
#: src/components/MainHeader.jsx:80
msgid "Save"
msgstr ""
#: src/components/MainHeader.jsx:105
#: src/components/MainHeader.jsx:105
msgid "Signup"
#: src/components/Footer.jsx:202
msgid "Save as HTML file"
msgstr ""
#: src/components/MainHeader.jsx:71
msgid "Save current creation (Ctrl/⌘ + S)"
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:30
msgid "Save current creations"
msgstr ""
#: src/components/SavedItemPane.jsx:209
msgid "Search your creations here..."
msgstr ""
#: src/components/Footer.jsx:317
#~ msgid "See Changelog"
#~ msgstr ""
#: src/components/HelpModal.jsx:110
msgid "See awesome libraries used"
msgstr ""
#: src/components/Footer.jsx:313
msgid "See changelog"
msgstr ""
#: src/components/MainHeader.jsx:110
msgid "See profile or Logout"
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:65
msgid "Select next match"
msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:71
msgid "Select previous match"
msgstr ""
#: src/components/Footer.jsx:325
msgid "Settings"
msgstr ""
#: src/components/MainHeader.jsx:105
#: src/components/MainHeader.jsx:105
#~ msgid "Signup"
#~ msgstr ""
#: src/components/KeyboardShortcutsModal.jsx:114
msgid "Single line comment"
msgstr ""
#: src/components/MainHeader.jsx:58
msgid "Start a new creation"
msgstr ""
#: src/components/HelpModal.jsx:69
msgid "Support the developer"
msgstr ""
#: src/components/Footer.jsx:139
msgid "Support the developer by pledging some amount"
msgstr ""
#: src/components/Footer.jsx:289
msgid "Switch to full screen preview"
msgstr ""
#: src/components/Footer.jsx:279
msgid "Switch to layout with all vertical panes"
msgstr ""
#: src/components/Footer.jsx:259
msgid "Switch to layout with preview on bottom"
msgstr ""
#: src/components/Footer.jsx:269
msgid "Switch to layout with preview on left"
msgstr ""
#: src/components/Footer.jsx:273
#~ msgid "Switch to layout with preview on left\""
#~ msgstr ""
#: src/components/Footer.jsx:249
msgid "Switch to layout with preview on right"
msgstr ""
#: src/components/Footer.jsx:236
msgid "Take screenshot of preview"
msgstr ""
#: src/components/Console.jsx:78
msgid "Toggle console"
msgstr ""
#: src/components/Footer.jsx:118
msgid "Tweet about 'Web Maker'"
msgstr ""
#: src/components/HelpModal.jsx:34
#~ msgid "Tweet out your feature requests, comments & suggestions to <0>@webmakerApp</0>"
#~ msgstr ""
#: src/components/AddLibrary.jsx:82
msgid "Type here to search libraries"
msgstr ""
#: src/components/Footer.jsx:183
msgid "Upload Image"
msgstr ""

View File

@ -1,6 +1,6 @@
{
"name": "Web Maker",
"version": "4.2.0",
"version": "5.0.0",
"manifest_version": 2,
"description": "Blazing fast & offline playground for your web experiments",
"homepage_url": "https://webmaker.app",

View File

@ -35,7 +35,7 @@
<body>
<h3>
Settings
<span style="opacity: 0.6;font-size:0.7em;"> v4.0.3</span>
<span style="opacity: 0.6; font-size: 0.7em"> v5.0.0</span>
</h3>
<form name="optionsForm">
<label>

View File

@ -1226,6 +1226,7 @@ body > #demo-frame {
.saved-item-tile__btn {
padding: 7px 10px;
color: white;
border: 0;
border-radius: 20px;
margin-left: 2px;
background: rgba(255, 255, 255, 0.1);
@ -1254,6 +1255,7 @@ body > #demo-frame {
overflow-y: auto;
overflow-x: hidden;
max-height: calc(100vh - 90px);
scroll-behavior: smooth;
}
.notifications-btn {
@ -1697,8 +1699,8 @@ body:not(.is-app) .show-when-app {
width: 80px;
height: 80px;
border-radius: 50%;
background: white
url('data:image/svg+xml;charset=UTF-8,<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="width:32px;height:32px" viewBox="0 0 24 24"><path fill="limegreen" d="M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M11,16.5L18,9.5L16.59,8.09L11,13.67L7.91,10.59L6.5,12L11,16.5Z" /></svg>');
background-color: white;
/* background-image: url('data:image/svg+xml;charset=UTF-8,<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="width:32px;height:32px" viewBox="0 0 24 24"><path fill="limegreen" d="M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M11,16.5L18,9.5L16.59,8.09L11,13.67L7.91,10.59L6.5,12L11,16.5Z" /></svg>'); */
}
.bookmarklet {

View File

@ -1,7 +1,7 @@
import { trackEvent } from './analytics';
import { computeHtml, computeCss, computeJs } from './computes';
import { JsModes } from './codeModes';
import { modes, HtmlModes, CssModes, JsModes } from './codeModes';
import { deferred } from './deferred';
import { getExtensionFromFileName } from './fileUtils';
const esprima = require('esprima');
@ -394,9 +394,7 @@ export function getCompleteHtml(html, css, js, item, isForExport) {
'<script src="' +
(chrome.extension
? chrome.extension.getURL('lib/transpilers/babel-polyfill.min.js')
: `${
location.origin
}${BASE_PATH}/lib/transpilers/babel-polyfill.min.js`) +
: `${location.origin}${BASE_PATH}/lib/transpilers/babel-polyfill.min.js`) +
'"></script>';
}
@ -513,6 +511,80 @@ export function prettify({ file, content, type }) {
return d.promise;
}
/**
* Loaded the code comiler based on the mode selected
*/
export function handleModeRequirements(mode) {
const baseTranspilerPath = 'lib/transpilers';
// Exit if already loaded
var d = deferred();
if (modes[mode].hasLoaded) {
d.resolve();
return d.promise;
}
function setLoadedFlag() {
modes[mode].hasLoaded = true;
d.resolve();
}
if (mode === HtmlModes.JADE) {
loadJS(`${baseTranspilerPath}/jade.js`).then(setLoadedFlag);
} else if (mode === HtmlModes.MARKDOWN) {
loadJS(`${baseTranspilerPath}/marked.js`).then(setLoadedFlag);
} else if (mode === CssModes.LESS) {
loadJS(`${baseTranspilerPath}/less.min.js`).then(setLoadedFlag);
} else if (mode === CssModes.SCSS || mode === CssModes.SASS) {
loadJS(`${baseTranspilerPath}/sass.js`).then(function() {
window.sass = new Sass(`${baseTranspilerPath}/sass.worker.js`);
setLoadedFlag();
});
} else if (mode === CssModes.STYLUS) {
loadJS(`${baseTranspilerPath}/stylus.min.js`).then(setLoadedFlag);
} else if (mode === CssModes.ACSS) {
loadJS(`${baseTranspilerPath}/atomizer.browser.js`).then(setLoadedFlag);
} else if (mode === JsModes.COFFEESCRIPT) {
loadJS(`${baseTranspilerPath}/coffee-script.js`).then(setLoadedFlag);
} else if (mode === JsModes.ES6) {
loadJS(`${baseTranspilerPath}/babel.min.js`).then(setLoadedFlag);
} else if (mode === JsModes.TS) {
loadJS(`${baseTranspilerPath}/typescript.js`).then(setLoadedFlag);
} else {
d.resolve();
}
return d.promise;
}
export function sanitizeSplitSizes(sizes) {
// console.log('got', sizes);
let hasAllNumbers = !sizes.some(size => !Number(size));
if (hasAllNumbers) return sizes;
// Get just the perentage values from expressions like calc(93.34% - 3px)
const newSizes = sizes.map(size => {
if (typeof size.match !== 'function') return size;
const match = size.match(/([\d.]*)%/);
if (match) return parseInt(match[1], 10);
return size;
});
// console.log('percents ', newSizes);
// Do we still have any non-number?
hasAllNumbers = !newSizes.some(size => !Number(size));
// console.log('hasAllnumbers? ', hasAllNumbers);
// Make the sum 100
if (hasAllNumbers) {
const sum = newSizes.reduce((sum, val) => sum + val, 0);
// console.log('sum ', sum);
newSizes[newSizes.length - 1] += 100 - sum;
}
return newSizes;
}
if (window.IS_EXTENSION) {
document.body.classList.add('is-extension');
} else {

View File

@ -2,11 +2,13 @@ import { h, Component } from 'preact';
import Footer from '../src/components/Footer';
import { Link } from 'preact-router/match';
// See: https://github.com/mzgoddard/preact-render-spy
import { shallow, deep } from 'preact-render-spy';
// import { shallow, deep } from 'preact-render-spy';
describe('Initial Test of the Footer', () => {
test('Footer renders 1 link with an ID of notificationsBtn', () => {
const context = shallow(<Footer prefs={{}} />);
expect(context.find('#notificationsBtn').exists()).toBeTruthy();
// const context = shallow(<Footer prefs={{}} />);
// expect(context.find('#notificationsBtn').exists()).toBeTruthy();
expect(true).toBeTruthy();
});
});

11788
yarn.lock

File diff suppressed because it is too large Load Diff