mirror of
https://github.com/chinchang/web-maker.git
synced 2025-07-29 09:40:10 +02:00
port saveAsHtml
This commit is contained in:
@@ -2,7 +2,7 @@ import { h, Component } from 'preact';
|
|||||||
import UserCodeMirror from './UserCodeMirror.jsx';
|
import UserCodeMirror from './UserCodeMirror.jsx';
|
||||||
import { computeHtml, computeCss, computeJs } from '../computes';
|
import { computeHtml, computeCss, computeJs } from '../computes';
|
||||||
import { modes, HtmlModes, CssModes, JsModes } from '../codeModes';
|
import { modes, HtmlModes, CssModes, JsModes } from '../codeModes';
|
||||||
import { log, writeFile, loadJS } from '../utils';
|
import { log, writeFile, loadJS, getCompleteHtml } from '../utils';
|
||||||
import { SplitPane } from './SplitPane.jsx';
|
import { SplitPane } from './SplitPane.jsx';
|
||||||
import { trackEvent } from '../analytics';
|
import { trackEvent } from '../analytics';
|
||||||
import CodeMirror from '../CodeMirror';
|
import CodeMirror from '../CodeMirror';
|
||||||
@@ -76,78 +76,15 @@ export default class ContentWrap extends Component {
|
|||||||
}
|
}
|
||||||
clearConsole() {}
|
clearConsole() {}
|
||||||
|
|
||||||
/* eslint max-params: ["error", 4] */
|
|
||||||
getCompleteHtml(html, css, js, isForExport) {
|
|
||||||
if (!this.props.currentItem) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
var externalJs = this.props.currentItem.externalLibs.js
|
|
||||||
.split('\n')
|
|
||||||
.reduce(function(scripts, url) {
|
|
||||||
return scripts + (url ? '\n<script src="' + url + '"></script>' : '');
|
|
||||||
}, '');
|
|
||||||
var externalCss = this.props.currentItem.externalLibs.css
|
|
||||||
.split('\n')
|
|
||||||
.reduce(function(links, url) {
|
|
||||||
return (
|
|
||||||
links +
|
|
||||||
(url ? '\n<link rel="stylesheet" href="' + url + '"></link>' : '')
|
|
||||||
);
|
|
||||||
}, '');
|
|
||||||
var contents =
|
|
||||||
'<!DOCTYPE html>\n' +
|
|
||||||
'<html>\n<head>\n' +
|
|
||||||
'<meta charset="UTF-8" />\n' +
|
|
||||||
externalCss +
|
|
||||||
'\n' +
|
|
||||||
'<style id="webmakerstyle">\n' +
|
|
||||||
css +
|
|
||||||
'\n</style>\n' +
|
|
||||||
'</head>\n' +
|
|
||||||
'<body>\n' +
|
|
||||||
html +
|
|
||||||
'\n' +
|
|
||||||
externalJs +
|
|
||||||
'\n';
|
|
||||||
|
|
||||||
if (!isForExport) {
|
|
||||||
contents +=
|
|
||||||
'<script src="' +
|
|
||||||
(chrome.extension
|
|
||||||
? chrome.extension.getURL('lib/screenlog.js')
|
|
||||||
: `${location.origin}${BASE_PATH}/lib/screenlog.js`) +
|
|
||||||
'"></script>';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.jsMode === JsModes.ES6) {
|
|
||||||
contents +=
|
|
||||||
'<script src="' +
|
|
||||||
(chrome.extension
|
|
||||||
? chrome.extension.getURL('lib/transpilers/babel-polyfill.min.js')
|
|
||||||
: `${
|
|
||||||
location.origin
|
|
||||||
}${BASE_PATH}/lib/transpilers/babel-polyfill.min.js`) +
|
|
||||||
'"></script>';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof js === 'string') {
|
|
||||||
contents += '<script>\n' + js + '\n//# sourceURL=userscript.js';
|
|
||||||
} else {
|
|
||||||
var origin = chrome.i18n.getMessage()
|
|
||||||
? `chrome-extension://${chrome.i18n.getMessage('@@extension_id')}`
|
|
||||||
: `${location.origin}`;
|
|
||||||
contents +=
|
|
||||||
'<script src="' + `filesystem:${origin}/temporary/script.js` + '">';
|
|
||||||
}
|
|
||||||
contents += '\n</script>\n</body>\n</html>';
|
|
||||||
|
|
||||||
return contents;
|
|
||||||
}
|
|
||||||
|
|
||||||
createPreviewFile(html, css, js) {
|
createPreviewFile(html, css, js) {
|
||||||
const shouldInlineJs =
|
const shouldInlineJs =
|
||||||
!window.webkitRequestFileSystem || !window.IS_EXTENSION;
|
!window.webkitRequestFileSystem || !window.IS_EXTENSION;
|
||||||
var contents = this.getCompleteHtml(html, css, shouldInlineJs ? js : null);
|
var contents = getCompleteHtml(
|
||||||
|
html,
|
||||||
|
css,
|
||||||
|
shouldInlineJs ? js : null,
|
||||||
|
this.props.currentItem
|
||||||
|
);
|
||||||
var blob = new Blob([contents], { type: 'text/plain;charset=UTF-8' });
|
var blob = new Blob([contents], { type: 'text/plain;charset=UTF-8' });
|
||||||
var blobjs = new Blob([js], { type: 'text/plain;charset=UTF-8' });
|
var blobjs = new Blob([js], { type: 'text/plain;charset=UTF-8' });
|
||||||
|
|
||||||
|
@@ -17,6 +17,7 @@ export default class Footer extends Component {
|
|||||||
<div id="footer" class="footer">
|
<div id="footer" class="footer">
|
||||||
<div class="footer__right fr">
|
<div class="footer__right fr">
|
||||||
<a
|
<a
|
||||||
|
onClick={this.props.saveHtmlBtnClickHandler}
|
||||||
id="saveHtmlBtn"
|
id="saveHtmlBtn"
|
||||||
class="mode-btn hint--rounded hint--top-left hide-on-mobile"
|
class="mode-btn hint--rounded hint--top-left hide-on-mobile"
|
||||||
data-hint="Save as HTML file"
|
data-hint="Save as HTML file"
|
||||||
|
@@ -9,7 +9,7 @@ import AddLibrary from './AddLibrary.jsx';
|
|||||||
import Modal from './Modal.jsx';
|
import Modal from './Modal.jsx';
|
||||||
import HelpModal from './HelpModal.jsx';
|
import HelpModal from './HelpModal.jsx';
|
||||||
import Login from './Login.jsx';
|
import Login from './Login.jsx';
|
||||||
import { log, generateRandomId, semverCompare } from '../utils';
|
import { log, generateRandomId, semverCompare, saveAsHtml } from '../utils';
|
||||||
import { itemService } from '../itemService';
|
import { itemService } from '../itemService';
|
||||||
import '../db';
|
import '../db';
|
||||||
import Notifications from './Notifications';
|
import Notifications from './Notifications';
|
||||||
@@ -446,40 +446,6 @@ export default class App extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
saveFile() {
|
|
||||||
var htmlPromise = computeHtml();
|
|
||||||
var cssPromise = computeCss();
|
|
||||||
var jsPromise = computeJs(false);
|
|
||||||
Promise.all([htmlPromise, cssPromise, jsPromise]).then(function(result) {
|
|
||||||
var html = result[0],
|
|
||||||
css = result[1],
|
|
||||||
js = result[2];
|
|
||||||
|
|
||||||
var fileContent = getCompleteHtml(html, css, js, true);
|
|
||||||
|
|
||||||
var d = new Date();
|
|
||||||
var fileName = [
|
|
||||||
'web-maker',
|
|
||||||
d.getFullYear(),
|
|
||||||
d.getMonth() + 1,
|
|
||||||
d.getDate(),
|
|
||||||
d.getHours(),
|
|
||||||
d.getMinutes(),
|
|
||||||
d.getSeconds()
|
|
||||||
].join('-');
|
|
||||||
|
|
||||||
if (this.state.currentItem.title) {
|
|
||||||
fileName = this.state.currentItem.title;
|
|
||||||
}
|
|
||||||
fileName += '.html';
|
|
||||||
|
|
||||||
var blob = new Blob([fileContent], { type: 'text/html;charset=UTF-8' });
|
|
||||||
utils.downloadFile(fileName, blob);
|
|
||||||
|
|
||||||
trackEvent('fn', 'saveFileComplete');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
closeAllOverlays() {
|
closeAllOverlays() {
|
||||||
if (this.state.isSavedItemPaneOpen) {
|
if (this.state.isSavedItemPaneOpen) {
|
||||||
this.setState({ isSavedItemPaneOpen: false });
|
this.setState({ isSavedItemPaneOpen: false });
|
||||||
@@ -833,6 +799,11 @@ export default class App extends Component {
|
|||||||
trackEvent('ui', 'openInCodepen');
|
trackEvent('ui', 'openInCodepen');
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
|
saveHtmlBtnClickHandler(e) {
|
||||||
|
saveAsHtml(this.state.currentItem);
|
||||||
|
trackEvent('ui', 'saveHtmlClick');
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
@@ -880,6 +851,7 @@ export default class App extends Component {
|
|||||||
this
|
this
|
||||||
)}
|
)}
|
||||||
codepenBtnClickHandler={this.codepenBtnClickHandler.bind(this)}
|
codepenBtnClickHandler={this.codepenBtnClickHandler.bind(this)}
|
||||||
|
saveHtmlBtnClickHandler={this.saveHtmlBtnClickHandler.bind(this)}
|
||||||
hasUnseenChangelog={this.state.hasUnseenChangelog}
|
hasUnseenChangelog={this.state.hasUnseenChangelog}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -2,15 +2,24 @@
|
|||||||
trackEvent
|
trackEvent
|
||||||
} from './analytics';
|
} from './analytics';
|
||||||
|
|
||||||
|
import {
|
||||||
|
computeHtml,
|
||||||
|
computeCss,
|
||||||
|
computeJs
|
||||||
|
} from './computes';
|
||||||
|
import {
|
||||||
|
JsModes
|
||||||
|
} from './codeModes';
|
||||||
import {
|
import {
|
||||||
deferred
|
deferred
|
||||||
} from './deferred';
|
} from './deferred';
|
||||||
window.DEBUG = document.cookie.indexOf('wmdebug') > -1;
|
|
||||||
|
|
||||||
|
window.DEBUG = document.cookie.indexOf('wmdebug') > -1;
|
||||||
window.$ = document.querySelector.bind(document);
|
window.$ = document.querySelector.bind(document);
|
||||||
window.$all = selector => [...document.querySelectorAll(selector)];
|
window.$all = selector => [...document.querySelectorAll(selector)];
|
||||||
var alphaNum =
|
const BASE_PATH = chrome.extension || window.DEBUG ? '/' : '/app';
|
||||||
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
|
||||||
|
var alphaNum = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The following 2 functions are supposed to find the next/previous sibling until the
|
* The following 2 functions are supposed to find the next/previous sibling until the
|
||||||
@@ -102,13 +111,13 @@
|
|||||||
var varStr = 'var %d = Date.now();\n';
|
var varStr = 'var %d = Date.now();\n';
|
||||||
var checkStr = `\nif (Date.now() - %d > ${timeout}) { window.top.previewException(new Error("Infinite loop")); break;}\n`;
|
var checkStr = `\nif (Date.now() - %d > ${timeout}) { window.top.previewException(new Error("Infinite loop")); break;}\n`;
|
||||||
|
|
||||||
esprima.parse(code, {
|
esprima.parse(
|
||||||
|
code, {
|
||||||
tolerant: true,
|
tolerant: true,
|
||||||
range: true,
|
range: true,
|
||||||
jsx: true
|
jsx: true
|
||||||
}, function (
|
},
|
||||||
node
|
function (node) {
|
||||||
) {
|
|
||||||
switch (node.type) {
|
switch (node.type) {
|
||||||
case 'DoWhileStatement':
|
case 'DoWhileStatement':
|
||||||
case 'ForStatement':
|
case 'ForStatement':
|
||||||
@@ -145,7 +154,8 @@
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
/* eslint-disable no-param-reassign */
|
/* eslint-disable no-param-reassign */
|
||||||
patches
|
patches
|
||||||
@@ -288,7 +298,110 @@
|
|||||||
d.resolve();
|
d.resolve();
|
||||||
};
|
};
|
||||||
return d.promise;
|
return d.promise;
|
||||||
};
|
}
|
||||||
|
|
||||||
|
export function getCompleteHtml(html, css, js, item, isForExport) {
|
||||||
|
if (!item) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
var externalJs = item.externalLibs.js
|
||||||
|
.split('\n')
|
||||||
|
.reduce(function (scripts, url) {
|
||||||
|
return scripts + (url ? '\n<script src="' + url + '"></script>' : '');
|
||||||
|
}, '');
|
||||||
|
var externalCss = item.externalLibs.css
|
||||||
|
.split('\n')
|
||||||
|
.reduce(function (links, url) {
|
||||||
|
return (
|
||||||
|
links +
|
||||||
|
(url ? '\n<link rel="stylesheet" href="' + url + '"></link>' : '')
|
||||||
|
);
|
||||||
|
}, '');
|
||||||
|
var contents =
|
||||||
|
'<!DOCTYPE html>\n' +
|
||||||
|
'<html>\n<head>\n' +
|
||||||
|
'<meta charset="UTF-8" />\n' +
|
||||||
|
externalCss +
|
||||||
|
'\n' +
|
||||||
|
'<style id="webmakerstyle">\n' +
|
||||||
|
css +
|
||||||
|
'\n</style>\n' +
|
||||||
|
'</head>\n' +
|
||||||
|
'<body>\n' +
|
||||||
|
html +
|
||||||
|
'\n' +
|
||||||
|
externalJs +
|
||||||
|
'\n';
|
||||||
|
|
||||||
|
if (!isForExport) {
|
||||||
|
contents +=
|
||||||
|
'<script src="' +
|
||||||
|
(chrome.extension ?
|
||||||
|
chrome.extension.getURL('lib/screenlog.js') :
|
||||||
|
`${location.origin}${BASE_PATH}/lib/screenlog.js`) +
|
||||||
|
'"></script>';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.jsMode === JsModes.ES6) {
|
||||||
|
contents +=
|
||||||
|
'<script src="' +
|
||||||
|
(chrome.extension ?
|
||||||
|
chrome.extension.getURL('lib/transpilers/babel-polyfill.min.js') :
|
||||||
|
`${
|
||||||
|
location.origin
|
||||||
|
}${BASE_PATH}/lib/transpilers/babel-polyfill.min.js`) +
|
||||||
|
'"></script>';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof js === 'string') {
|
||||||
|
contents += '<script>\n' + js + '\n//# sourceURL=userscript.js';
|
||||||
|
} else {
|
||||||
|
var origin = chrome.i18n.getMessage() ?
|
||||||
|
`chrome-extension://${chrome.i18n.getMessage('@@extension_id')}` :
|
||||||
|
`${location.origin}`;
|
||||||
|
contents +=
|
||||||
|
'<script src="' + `filesystem:${origin}/temporary/script.js` + '">';
|
||||||
|
}
|
||||||
|
contents += '\n</script>\n</body>\n</html>';
|
||||||
|
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function saveAsHtml(item) {
|
||||||
|
var htmlPromise = computeHtml(item.html, item.htmlMode);
|
||||||
|
var cssPromise = computeCss(item.css, item.cssMode);
|
||||||
|
var jsPromise = computeJs(item.js, item.jsMode, false);
|
||||||
|
Promise.all([htmlPromise, cssPromise, jsPromise]).then(function (result) {
|
||||||
|
var html = result[0],
|
||||||
|
css = result[1],
|
||||||
|
js = result[2];
|
||||||
|
|
||||||
|
var fileContent = getCompleteHtml(html, css, js, item, true);
|
||||||
|
|
||||||
|
var d = new Date();
|
||||||
|
var fileName = [
|
||||||
|
'web-maker',
|
||||||
|
d.getFullYear(),
|
||||||
|
d.getMonth() + 1,
|
||||||
|
d.getDate(),
|
||||||
|
d.getHours(),
|
||||||
|
d.getMinutes(),
|
||||||
|
d.getSeconds()
|
||||||
|
].join('-');
|
||||||
|
|
||||||
|
if (item.title) {
|
||||||
|
fileName = item.title;
|
||||||
|
}
|
||||||
|
fileName += '.html';
|
||||||
|
|
||||||
|
var blob = new Blob([fileContent], {
|
||||||
|
type: 'text/html;charset=UTF-8'
|
||||||
|
});
|
||||||
|
downloadFile(fileName, blob);
|
||||||
|
|
||||||
|
trackEvent('fn', 'saveFileComplete');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
window.chrome = window.chrome || {};
|
window.chrome = window.chrome || {};
|
||||||
window.chrome.i18n = {
|
window.chrome.i18n = {
|
||||||
|
Reference in New Issue
Block a user