1
0
mirror of https://github.com/chinchang/web-maker.git synced 2025-05-08 19:45:17 +02:00

build with db

This commit is contained in:
Kushagra Gour 2018-01-10 04:02:21 +05:30
parent d4d3d6eccf
commit 80b07c85b1
10 changed files with 1187 additions and 313 deletions

View File

@ -64,6 +64,13 @@
<path d="M13,9V3.5L18.5,9M6,2C4.89,2 4,2.89 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2H6Z" /> <path d="M13,9V3.5L18.5,9M6,2C4.89,2 4,2.89 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2H6Z" />
</svg>Open </svg>Open
</a> </a>
<a class="hide-on-login flex flex-v-center hint--rounded hint--bottom-left" aria-label="Login/Signup" d-open-modal="loginModal">
Login/Signup
</a>
<a class="hide-on-logout flex flex-v-center hint--rounded hint--bottom-left" aria-label="Logout" d-click="logout">
Logout
</a>
<img id="headerAvatarImg" width="20" src="https://www.gravatar.com/avatar/6be4e636e8aacd405bed5cd15124a875" class="main-header__avatar-img hide-on-logout ml-1"/>
</div> </div>
</div> </div>
<div class="content-wrap flex flex-grow"> <div class="content-wrap flex flex-grow">
@ -295,106 +302,19 @@
</div> </div>
<div class="modal" id="helpModal"> <div class="modal" id="helpModal">
<div class="modal__content"> <div class="modal__content" d-html="partials/help-modal.html"></div>
<a d-click="onModalCloseBtnClick" href="" aria-label="Close help modal" title="Close" class="js-modal__close-btn modal__close-btn">
<svg>
<use xlink:href="#cross-icon"></use>
</svg>
</a>
<h1>Web Maker<small style="font-size:14px;"> v2.9.5</small></h1>
<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">Kushagra Gour</a></p>
<p>Tweet out your feature requests, comments & suggestions to <a target="_blank" href="https://twitter.com/webmakerApp">@webmakerApp</a>.</p>
<p>Like this extension? Please <a href="https://chrome.google.com/webstore/detail/web-maker/lkfkkhfhhdkiemehlpkgjeojomhpccnh/reviews" target="_blank">rate it here</a>.</p>
<p>
<a aria-label="Rate Web Maker" href="https://chrome.google.com/webstore/detail/web-maker/lkfkkhfhhdkiemehlpkgjeojomhpccnh/reviews" target="_blank" class="btn btn-icon"><svg><use xlink:href="#heart-icon"></use></svg>Show some love</a>
<a aria-label="Chat" href="https://gitter.im/web-maker-app/Lobby" target="_blank" class="btn btn-icon"><svg><use xlink:href="#chat-icon"></use></svg>Chat</a>
<a aria-label="Report a Bug" href="https://github.com/chinchang/web-maker/issues" target="_blank" class="btn btn-icon"><svg><use xlink:href="#bug-icon"></use></svg>Report a bug</a>
<a aria-label="Support the developer" href="https://www.paypal.me/kushagragour" target="_blank" class="btn btn-icon"><svg><use xlink:href="#gift-icon"></use></svg>Support the developer</a>
</p>
<p>
<h3>Awesome libraries used</h3>
<ul>
<li><a target="_blank" href="https://kushagragour.in/lab/hint/">Hint.css</a> & <a target="_blank" href="https://github.com/chinchang/screenlog.js">Screenlog.js</a> - By me :)</li>
<li><a target="_blank" href="https://nathancahill.github.io/Split.js/">Split.js</a> - Nathan Cahill</li>
<li><a target="_blank" href="https://codemirror.net/">Codemirror</a> - Marijn Haverbeke</li>
<li><a target="_blank" href="https://emmet.io/">Emmet</a> - Sergey Chikuyonok</li>
<li><a target="_blank" href="http://esprima.org/">Esprima</a> - Ariya Hidayat</li>
<li><a target="_blank" href="https://github.com/enjalot/Inlet">Inlet</a> - Ian Johnson</li>
<li><a target="_blank" href="https://webmakerapp.com/">Web Maker!</a> - whhat!</li>
</ul>
</p>
<p>
<h3>License</h3>
"Web Maker" is <a target="_blank" href="https://github.com/chinchang/web-maker">open-source</a> under the <a href="https://opensource.org/licenses/MIT" target="_blank">MIT License</a>.
</p>
</div>
</div>
</div> </div>
<div class="modal" id="keyboardShortcutsModal"> <div class="modal" id="keyboardShortcutsModal">
<div class="modal__content" d-html="keyboard-shortcuts.html"> <div class="modal__content" d-html="partials/keyboard-shortcuts.html"></div>
</div>
</div> </div>
<div class="modal" id="onboardModal"> <div class="modal" id="onboardModal">
<div class="modal__content"> <div class="modal__content" d-html="partials/onboard-modal.html"></div>
<div class="tac">
<svg width="130px" height="50px">
<use xlink:href="#logo" />
</svg>
<h1 style="margin-top:20px">Welcome to Web Maker</h1>
</div>
<div class="flex" style="margin-top;: 100px;">
<div class="onboard-step">
<div class="tac">
<svg class="onboard-step__icon" viewBox="0 0 24 24">
<path d="M13.64,21.97C13.14,22.21 12.54,22 12.31,21.5L10.13,16.76L7.62,18.78C7.45,18.92 7.24,19 7,19A1,1 0 0,1 6,18V3A1,1 0 0,1 7,2C7.24,2 7.47,2.09 7.64,2.23L7.65,2.22L19.14,11.86C19.57,12.22 19.62,12.85 19.27,13.27C19.12,13.45 18.91,13.57 18.7,13.61L15.54,14.23L17.74,18.96C18,19.46 17.76,20.05 17.26,20.28L13.64,21.97Z"
/>
</svg>
</div>
<p>
Open Web Maker anytime by clicking the
<svg class="relative" style="top:5px;" width="40" height="30">
<use xlink:href="#logo" />
</svg> button in top-right side of your browser.
</p>
</div>
<div class="onboard-step">
<div class="tac">
<svg class="onboard-step__icon" viewBox="0 0 24 24">
<use xlink:href="#settings-icon"></use>
</svg>
</div>
<p>
Configure and customize settings by clicking the gear icon (
<svg style="width:18px;height:18px;position:relative;top:3px;fill:#888"
viewBox="0 0 24 24">
<use xlink:href="#settings-icon"></use>
</svg>) in bottom right of the app.
</p>
</div>
<div class="onboard-step">
<div class="tac">
<svg class="onboard-step__icon" style="stroke-width:0.2px;">
<use xlink:href="#twitter-icon"></use>
</svg>
</div>
<p>
Follow <a href="https://twitter.com/intent/follow?screen_name=webmakerApp">@webmakerApp</a> to know about the new upcoming
features!
</p>
</div>
</div> </div>
<div class="modal" id="loginModal">
<p class="tac"> <div class="modal__content" d-html="partials/login-modal.html"></div>
<button class="btn" d-click="closeAllOverlays">Lets start!</button>
</p>
</div>
</div> </div>
<div class="modal modal--settings" id="settingsModal"> <div class="modal modal--settings" id="settingsModal">
@ -531,8 +451,7 @@
</div> </div>
<div class="modal" id="notificationsModal"> <div class="modal" id="notificationsModal">
<div class="modal__content" d-html="changelog.html"> <div class="modal__content" d-html="partials/changelog.html"></div>
</div>
</div> </div>
<div id="js-saved-items-pane" class="saved-items-pane"> <div id="js-saved-items-pane" class="saved-items-pane">

290
app/partials/changelog.html Normal file
View File

@ -0,0 +1,290 @@
<a d-click="onModalCloseBtnClick" href="" aria-label="Close notifications" title="Close" class="js-modal__close-btn modal__close-btn">
<svg>
<use xlink:href="#cross-icon"></use>
</svg>
</a>
<h1>Whats new?</h1>
<div class="notification">
<span class="notification__version">2.9.6</span>
<ul>
<li><strong>Bugfix</strong>: Fix close buttons not working in notifications and keyboard shortcuts modal.</li>
<li><strong>Bugfix</strong>: Fix keyboard shortcut to see keyboard shortcuts :) Thanks <a href="https://github.com/ClassicOldSong" target="_blank">ClassicOldSong</a>.</li>
<br>
<li><strong>🚀 Announcement</strong>: Web Maker has a <a href="https://gitter.im/web-maker-app/Lobby" target="_blank">chat lobby on Gitter</a> now - incase you need any help or just want to say Hi!</li>
<li><a href="https://github.com/chinchang/web-maker/issues" target="_blank">Suggest features or report bugs.</a></li>
<li>Web Maker now has more than 50K weekly active users! Thank you for being a part of this community of awesome developers. If you find Web Maker helpful, <a href="https://chrome.google.com/webstore/detail/web-maker/lkfkkhfhhdkiemehlpkgjeojomhpccnh/reviews" target="_blank" class="btn">Please rate Web Maker <span class="star"></span></a> &nbsp; <a href="http://twitter.com/share?url=https://webmakerapp.com/&text=Web Maker - A blazing fast %26 offline web playground! via @webmakerApp&related=webmakerApp&hashtags=web,editor,chrome,extension" target="_blank" target="_blank" class="btn">Share it</a>&nbsp; <a aria-label="Support the developer" href="https://www.paypal.me/kushagragour" target="_blank" class="btn btn-icon">Support the developer</a></li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.9.5</span>
<ul>
<li><a href="https://medium.com/web-maker/release-2-9-5-add-library-search-pane-collapsing-ux-improvements-more-1085216c1301" target="_blank">Read blog post about this release.</a></li>
<li><strong>Keyboard shortcuts panel</strong>: Add a list of all keyboard shotcuts. Access with <code> Ctrl/⌘ + Shift + ?</code> or click keyboard button in footer.</li>
<li><strong>Add external library</strong>: Better UX for searching third party libraries.</li>
<li><strong>Improvement</strong>: Code panes now go fullscreen when double-clicked on their headers - which is much more intuitive behavior based on feedback from lot of developers.</li>
<li><strong>Improvement</strong>: Add <code>allowfullscreen</code> attribute on iframes. Thanks <a href="https://github.com/ClassicOldSong" target="_blank">ClassicOldSong</a>.</li>
<li><strong>Bugfix</strong> - Stop screenlog.js from showing up in the exported HTML.</li>
<li>Popular external libraries list updated. Thanks <a href="https://github.com/jlapitan" target="_blank">jlapitan</a>.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.9.4</span>
<ul>
<li><strong>Improvement</strong>: Atomic CSS (Atomizer) has been updated to latest version. Now you can do things like psuedo elements. Learn More.</li>
<li><strong>Bugfix</strong> - Logging circular objects is now possible. It won't show in the Web Maker console, but will show fine in browser's console.</li>
<li><strong>Bugfix</strong> - Console's z-index issue has been fixed.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.9.3</span>
<ul>
<li>Choose the save location while exporting your saved creations. Now easily sync them to your Dropbox or any cloud storage.</li>
<li>All modals inside the app now have a close button.</li>
<li>Checkbox that showed on clicking a boolean value is now removed. Thanks <a href="https://github.com/gauravmuk" target="_blank">Gaurav Nanda</a>.</li>
<li><strong>Bugfix</strong> - Screenshots on retina device are now correct. Thanks <a href="https://github.com/AshBardhan" target="_blank">Ashish Bardhan</a>.</li>
<li><strong>Bugfix</strong> - Double console log in detached mode fixed.</li>
<li><strong>Bugfix</strong> - Console.clear now works in detached mode too.</li>
<li><strong>Bugfix</strong> - DOCTYPE added in preview.</li>
<li><strong>Bugfix</strong> - Typo correction in README. Thanks <a href="https://github.com/AdilMah" target="_blank">Adil Mahmood</a>.</li>
<li>gstatic.com is available to load external JavaScripts from.</li>
<li>Popular libraries list updated. Thanks <a href="https://github.com/diomed" target="_blank">diomed</a>.</li>
<li>Added <a href="https://github.com/chinchang/web-maker/blob/master/CONTRIBUTING.md" target="_blank">contribution guidelines</a> in the Github repository.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.9.2</span>
<ul>
<li>Minor bug fixes.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.9.1</span>
<ul>
<li><a href="https://medium.com/web-maker/v2-9-lots-of-goodies-bd1e939571f6" target="_blank">Read blog post about last release.</a></li>
<li>Use Ctrl/Cmd+D to select next occurence of matching selection.</li>
<li>Improve onboard experience.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.9.0</span>
<ul>
<li><a href="https://medium.com/web-maker/v2-9-lots-of-goodies-bd1e939571f6" target="_blank">Read blog post about this release.</a></li>
<li><strong>Detached Preview</strong> - Yes, you read that correct! You can now detach your preview and send it to your secondary monitor.
</li>
<li><strong>Find & Replace</strong> - Long awaited, now its there. Ctrl/Cmd+f to find and add Alt to replace.</li>
<li><strong>Atomic CSS (Atomizer) configurations</strong> - Add custom config for Atomic CSS. <a href="https://github.com/acss-io/atomizer#api" target="_blank">Read more</a>.</li>
<li><strong>Light mode</strong> - This new setting makes Web Maker drop some heavy effects like blur etc to gain more performance. Thanks <a href="https://github.com/iamandrewluca" target="_blank">Andrew</a>.</li>
<li><strong>Preserve logs setting</strong> - Choose whether or not to preserve logs across preview refreshes. Thanks <a href="https://github.com/BasitAli" target="_blank">Basit</a>.</li>
<li><strong>Line wrap setting</strong> - As the name says.</li>
<li>Semantic UI added to popular libraries.</li>
<li>Bootstrap, Vue, UI-Kit and more updated to latest versions in popular libraries.</li>
<li>UX improvements in settings UI</li>
<li><strong>Bugfix</strong> - Trigger preview refresh anytime with Ctrl/⌘ + Shift + 5. Even with auto-preview on.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.8.1</span>
<ul>
<li>Vue.js & UIKit version updated to latest version in 'Add Library' list.</li>
<li>UTF-8 charset added to preview HTML to support universal characters.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.8.0</span>
<ul>
<li><a href="https://medium.com/web-maker/release-v2-8-is-out-f44e6ea5d9c4" target="_blank">Read blog post about this release.</a></li>
<li><strong>Auto Save</strong> - Your creations now auto-save after your
first manual save. This is configurable from settings.
</li>
<li><strong>Base2Tone-Meadow Editor Theme</strong> - First user contributed theme.
Thanks to Diomed.</li>
<li><strong>Use System Fonts</strong> - You can now use any of your existing
system fonts in the editor!</li>
<li><strong>Matching Tag Highlight</strong> - Cursor over any HTML tag would
highlight the matching pair tag.</li>
<li>Auto-completion suggestion can now be switched off from settings.</li>
<li><strong>Improvement</strong> - Stop white flicker in editor when the app
opens.</li>
<li><strong>Bugfix</strong> - Add Babel Polyfill to enable use of next-gen
built-ins like Promise or WeakMap.
</li>
<li>Vue.js version updated to 2.4.0 in popular library list.</li>
<li>Downloads permission is optional. Asked only when you take screenshot.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.7.2</span>
<ul>
<li><strong>External Libraries</strong> - Add Foundation.js and update UIKit 3 to latest beta.</li>
<li><strong>rawgit.com</strong> & <strong>wzrd.in</strong> domains are now allowed for loading external libraries from.</li>
<li>Minor booting speed improvements</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.7.1</span>
<ul>
<li><strong>Framer.js support</strong> - You can now load the latest framer.js library from <a href="https://builds.framerjs.com/" target="_blank">framer builds page</a> and start coding framer prototypes.</li>
<li><strong>Bugfix</strong>: Edit on CodePen is back in action.</li>
<li><strong>Bugfix</strong>: Autocompletion menu doesn't show on cut and paste now.</li>
<li><strong>Bugfix</strong>: Updated & fixed urls of some common external libraries to latest versions. UIKit3 & Bootstrap 4α are now in the list.</li>
<li>Preprocessor selector are now more accessible.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.7.0</span>
<ul>
<li><strong>Fork any creation!</strong>: Now you can fork any existing creation of yours to start a new work based on it. One big use case of this feature is "Templates"! <a target="_blank" href="https://kushagragour.in/blog/2017/05/web-maker-fork-templates/?utm_source=webmakerapp&utm_medium=referral">Read more about it</a>.</li>
<li><strong>Fonts 😍 </strong>: Super-awesome 4 fonts (mostly with ligature support) now available to choose from. Fira Code is the default font now.</li>
<li>Updated most used external libraries to latest versions.</li>
<li><strong>Bugfix</strong>: Add missing Bootstrap JS file to most used external libraries list.</li>
<li>Several other minor bugfixes and improvements to make Web Maker awesome!</li>
<li>Great news to share with you - Web Maker has been featured on the Chrome Webstore homepage! Thanks for all the love :)</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.6.1</span>
<ul>
<li><strong>Bugfix</strong>: Emojis vanishing while exporting to Codepen has been fixed.</li>
<li><strong>Bugfix</strong>: <code>console.clear()</code> now doesn't error and clears the inbuilt console.</li>
<li><strong>Bugfix</strong>: External libraries added to the creation are exported as well to Codepen.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.6.0</span>
<ul>
<li><strong>The "Console"</strong>: The most awaited feature is here! There is now an inbuilt console to see your logs, errors and for quickly evaluating JavaScript code inside your preview. Enjoy! I also a <a href="https://kushagragour.in/blog/2017/05/web-maker-console-is-here/?utm_source=webmakerapp&utm_medium=referral"
target="_blank">blog post about it</a>.</li>
<li>Number slider which popped on clicking any number in the code has been removed due to poor user experience.</li>
<li>Minor usability improvements.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.5.0</span>
<ul>
<li><strong>Atomic CSS</strong>: Use can now use Atomic CSS(ACSS) in your work! <a href="https://acss.io/" target="_blank">Read more about it here</a>.</li>
<li><strong>Search your saved creations</strong>: Easily search through all your saved creations by title.</li>
<li><strong>Configurable Auto-preview</strong> - You can turn off the auto preview in settings if you don't want the preview to update as you type.</li>
<li><strong>Configurable refresh on resize</strong> - You can configure whether you want the preview to refresh when you resize the preview panel.</li>
<li><strong>Bugfix</strong> - Fix indentation <a href="https://github.com/chinchang/web-maker/issues/104" target="_blank">issue</a> with custom indentation size.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.4.2</span>
<ul>
<li><strong>Improved infinite loop protection</strong>: Infinite loop protection is now faster and more reliable. And works without the need of Escodegen. Thanks to Ariya Hidayat!</li>
<li><strong>Bugfix</strong> - Default parameters not working in JavaScript is fixed.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.4.0</span>
<ul>
<li><strong>Import/Export</strong>: Your creations are most important. Now export all your creations into a single file as a backup that can be imported anytime & anywhere.</li>
<li><strong>Editor themes</strong>: You have been heard. Now you can choose from a huge list of wonderful editor themes!</li>
<li><strong>Identation settings</strong>: Not a spaces fan? Switch to tabs and set your indentation size.</li>
<li><strong>Vim key bindings</strong>: Rejoice Vim lovers!</li>
<li><strong>Code blast</strong>: Why don't you try coding with this switched on from the settings? Go on...</li>
<li><strong>Important</strong>: Due to security policy changes from Chrome 57 onwards, Web Maker now allows loading external JavaScript libraries only from certain whitelisted 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/)</li>
<li>Save button now highlights when you have unsaved changes.</li>
<li>Jade is now called Pug. Just a name change.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.3.2</span>
<ul>
<li>Update Babel to support latest and coolest ES6 features.</li>
<li>Improve onboarding experience at first install.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.3.1</span>
<ul>
<li><strong>Bugfix</strong> - Splitting of code and preview panes is remembered by the editor.</li>
<li>Title of the creation is used for the file name when saving as HTML.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.3.0</span>
<ul>
<li><strong>Add Library Autocompletion</strong> - Just start typing the name of library and you'll be shown matching libraries from cdnjs.</li>
<li><strong>Preview Screenshot Capture</strong> - Want to grab a nice screenshot of your creation. You have it! Click and capture.</li>
<li><strong>Auto Indent Code</strong> - Select your code and hit Shift-Tab to auto-indent it!</li>
<li><strong>Keyboard Navigation in Saved List</strong> - Now select your creation using arrow keys and hit ENTER to open it.</li>
<li>Highlight active line in code panes.</li>
<li><strong>Bugfix</strong> - Fix in generated title of new creation.</li>
<li><strong>Bugfix</strong> - HTML autocompletion is manual triggered now with Ctrl+Space.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.2.0</span>
<ul>
<li><strong>Code Autocompletion</strong> - See code suggestions while you type!</li>
<li><strong>Full Screen Preview</strong> - Checkout your creation in a full-screen layout.</li>
<li><strong>SASS</strong> - SASS support added for CSS.</li>
<li><strong>Faster CSS update</strong> - Preview updates instantly without refresh when just CSS is changed.</li>
<li><strong>Bugfix</strong> - Indentation fixed while going on new line.</li>
<li><strong>Bugfix</strong> - Works even in Chrome Canary now. Though libraries can be added only through CDNs.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.1.0</span>
<ul>
<li><strong>TypeScript</strong> - Now you can code in TypeScript too!</li>
<li><strong>Stylus Preprocessor</strong> - Stylus supported adding for CSS.</li>
<li><strong>Code Folding</strong> - Collapse large code blocks for easy editing.</li>
<li><strong>Bugfix</strong> - Support JSX in JavaScript.</li>
<li>Better onboarding for first time users.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">2.0.0</span>
<ul>
<li><strong>Save and Load</strong> - Long pending and super-useful, now you can save your creations and resume them anytime later.</li>
<li><strong>Insert JS & CSS</strong> - Load popular JavaScript & CSS libraries in your work without writing any code.</li>
<li><strong>Collapsed Panes</strong> - Collapse/uncollapse code panes with a single click. Your pane configuration is even saved with every creation!</li>
<li><strong>Quick color & number change</strong> - Click on any color or number and experiment with quick values using a slider.</li>
<li><strong>Linting</strong> - See your code errors right where you are coding.</li>
<li>No more browser hang due to infinite loops!</li>
<!-- <li><a href="https://kushagragour.in/blog/web-maker-2">Read more about this big release</a></li> -->
</ul>
</div>
<div class="notification">
<span class="notification__version">1.7.0</span>
<ul>
<li><strong>Preprocessors!</strong> - Enjoy a whole list of preprocessors for HTML(Jade & markdown), CSS(SCSS & LESS) and JavaScript(CoffeeScript & Babel).</li>
<li>More awesome font for code.</li>
</ul>
</div>
<div class="notification">
<span class="notification__version">1.6.0</span>
<ul>
<li>You can now configure Web-Maker to not replace new tab page from the settings. It is always accessible from the icon in the top-right.</li>
<li>Download current code as HTML file with Ctrl/⌘ + S keyboard shortcut.</li>
<li>New notifications panel added so you are always aware of the new changes in Web-Maker.</li>
</ul>
</div>

View File

@ -0,0 +1,37 @@
<a d-click="onModalCloseBtnClick" href="" aria-label="Close help modal" title="Close" class="js-modal__close-btn modal__close-btn">
<svg>
<use xlink:href="#cross-icon"></use>
</svg>
</a>
<h1>Web Maker<small style="font-size:14px;"> v2.9.6</small></h1>
<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">Kushagra Gour</a></p>
<p>Tweet out your feature requests, comments & suggestions to <a target="_blank" href="https://twitter.com/webmakerApp">@webmakerApp</a>.</p>
<p>Like this extension? Please <a href="https://chrome.google.com/webstore/detail/web-maker/lkfkkhfhhdkiemehlpkgjeojomhpccnh/reviews" target="_blank">rate it here</a>.</p>
<p>
<a aria-label="Rate Web Maker" href="https://chrome.google.com/webstore/detail/web-maker/lkfkkhfhhdkiemehlpkgjeojomhpccnh/reviews" target="_blank" class="btn btn-icon"><svg><use xlink:href="#heart-icon"></use></svg>Show some love</a>
<a aria-label="Chat" href="https://gitter.im/web-maker-app/Lobby" target="_blank" class="btn btn-icon"><svg><use xlink:href="#chat-icon"></use></svg>Chat</a>
<a aria-label="Report a Bug" href="https://github.com/chinchang/web-maker/issues" target="_blank" class="btn btn-icon"><svg><use xlink:href="#bug-icon"></use></svg>Report a bug</a>
<a aria-label="Support the developer" href="https://www.paypal.me/kushagragour" target="_blank" class="btn btn-icon"><svg><use xlink:href="#gift-icon"></use></svg>Support the developer</a>
</p>
<p>
<h3>Awesome libraries used</h3>
<ul>
<li><a target="_blank" href="https://kushagragour.in/lab/hint/">Hint.css</a> & <a target="_blank" href="https://github.com/chinchang/screenlog.js">Screenlog.js</a> - By me :)</li>
<li><a target="_blank" href="https://nathancahill.github.io/Split.js/">Split.js</a> - Nathan Cahill</li>
<li><a target="_blank" href="https://codemirror.net/">Codemirror</a> - Marijn Haverbeke</li>
<li><a target="_blank" href="https://emmet.io/">Emmet</a> - Sergey Chikuyonok</li>
<li><a target="_blank" href="http://esprima.org/">Esprima</a> - Ariya Hidayat</li>
<li><a target="_blank" href="https://github.com/enjalot/Inlet">Inlet</a> - Ian Johnson</li>
<li><a target="_blank" href="https://webmakerapp.com/">Web Maker!</a> - whhat!</li>
</ul>
</p>
<p>
<h3>License</h3>
"Web Maker" is <a target="_blank" href="https://github.com/chinchang/web-maker">open-source</a> under the <a href="https://opensource.org/licenses/MIT" target="_blank">MIT License</a>.
</p>
</div>

View File

@ -0,0 +1,106 @@
<a d-click="onModalCloseBtnClick" href="" aria-label="Close keyboard shortcuts modal" title="Close" class="js-modal__close-btn modal__close-btn">
<svg>
<use xlink:href="#cross-icon"></use>
</svg>
</a>
<h1>Keyboard Shortcuts</h1>
<div class="flex">
<div>
<h2>Global</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>
</p>
<p>
<span class="kbd-shortcut__keys">
Ctrl/⌘ + S
</span>
<span class="kbd-shortcut__details">Save current creations</span>
</p>
<p>
<span class="kbd-shortcut__keys">
Ctrl/⌘ + O
</span>
<span class="kbd-shortcut__details">Open list of saved creations</span>
</p>
<p>
<span class="kbd-shortcut__keys">
Ctrl + L
</span>
<span class="kbd-shortcut__details">Clear console (works when console input is focused)</span>
</p>
<p>
<span class="kbd-shortcut__keys">
Esc
</span>
<span class="kbd-shortcut__details">Close saved creations panel & modals</span>
</p>
</div>
<div class="ml-2">
<h2>Editor</h2>
<p>
<span class="kbd-shortcut__keys">
Ctrl/⌘ + F
</span>
<span class="kbd-shortcut__details">Find</span>
</p>
<p>
<span class="kbd-shortcut__keys">
Ctrl/⌘ + G
</span>
<span class="kbd-shortcut__details">Select next match</span>
</p>
<p>
<span class="kbd-shortcut__keys">
Ctrl/⌘ + Shift + G
</span>
<span class="kbd-shortcut__details">Select previous match</span>
</p>
<p>
<span class="kbd-shortcut__keys">
Ctrl/⌘ + Opt/Alt + F
</span>
<span class="kbd-shortcut__details">Find & replace</span>
</p>
<p>
<span class="kbd-shortcut__keys">
Shift + Tab
</span>
<span class="kbd-shortcut__details">Realign code</span>
</p>
<p>
<span class="kbd-shortcut__keys">
Ctrl/⌘ + ]
</span>
<span class="kbd-shortcut__details">Indent code right</span>
</p>
<p>
<span class="kbd-shortcut__keys">
Ctrl/⌘ + [
</span>
<span class="kbd-shortcut__details">Indent code left</span>
</p>
<p>
<span class="kbd-shortcut__keys">
Tab
</span>
<span class="kbd-shortcut__details">Emmet code completion <a href="https://emmet.io/" target="_blank">Read more</a></span>
</p>
<p>
<span class="kbd-shortcut__keys">
Ctrl/⌘ + /
</span>
<span class="kbd-shortcut__details">Single line comment</span>
</p>
</div>
</div>

View File

@ -0,0 +1,16 @@
<a d-click="onModalCloseBtnClick" href="" aria-label="Close Login modal" title="Close" class="js-modal__close-btn modal__close-btn">
<svg>
<use xlink:href="#cross-icon"></use>
</svg>
</a>
<h2>Login</h2>
<div class="flex">
<p>
<button class="btn social-login-btn--google">Login with Google</button>
</p>
<p>
<button d-click="login" class="btn social-login-btn--github">Login with Github</button>
</p>
</div>

View File

@ -0,0 +1,53 @@
<div class="tac">
<svg width="130px" height="50px">
<use xlink:href="#logo" />
</svg>
<h1 style="margin-top:20px">Welcome to Web Maker</h1>
</div>
<div class="flex" style="margin-top;: 100px;">
<div class="onboard-step">
<div class="tac">
<svg class="onboard-step__icon" viewBox="0 0 24 24">
<path d="M13.64,21.97C13.14,22.21 12.54,22 12.31,21.5L10.13,16.76L7.62,18.78C7.45,18.92 7.24,19 7,19A1,1 0 0,1 6,18V3A1,1 0 0,1 7,2C7.24,2 7.47,2.09 7.64,2.23L7.65,2.22L19.14,11.86C19.57,12.22 19.62,12.85 19.27,13.27C19.12,13.45 18.91,13.57 18.7,13.61L15.54,14.23L17.74,18.96C18,19.46 17.76,20.05 17.26,20.28L13.64,21.97Z"
/>
</svg>
</div>
<p>
Open Web Maker anytime by clicking the
<svg class="relative" style="top:5px;" width="40" height="30">
<use xlink:href="#logo" />
</svg> button in top-right side of your browser.
</p>
</div>
<div class="onboard-step">
<div class="tac">
<svg class="onboard-step__icon" viewBox="0 0 24 24">
<use xlink:href="#settings-icon"></use>
</svg>
</div>
<p>
Configure and customize settings by clicking the gear icon (
<svg style="width:18px;height:18px;position:relative;top:3px;fill:#888"
viewBox="0 0 24 24">
<use xlink:href="#settings-icon"></use>
</svg>) in bottom right of the app.
</p>
</div>
<div class="onboard-step">
<div class="tac">
<svg class="onboard-step__icon" style="stroke-width:0.2px;">
<use xlink:href="#twitter-icon"></use>
</svg>
</div>
<p>
Follow <a href="https://twitter.com/intent/follow?screen_name=webmakerApp">@webmakerApp</a> to know about the new upcoming
features!
</p>
</div>
</div>
<p class="tac">
<button class="btn" d-click="closeAllOverlays">Lets start!</button>
</p>

View File

@ -15,7 +15,6 @@
*/ */
/* eslint-env browser */ /* eslint-env browser */
'use strict';
if ('serviceWorker' in navigator) { if ('serviceWorker' in navigator) {
// Delay registration until after the page has loaded, to ensure that our // Delay registration until after the page has loaded, to ensure that our
@ -26,7 +25,9 @@ if ('serviceWorker' in navigator) {
// It won't be able to control pages unless it's located at the same level or higher than them. // It won't be able to control pages unless it's located at the same level or higher than them.
// *Don't* register service worker file in, e.g., a scripts/ sub-directory! // *Don't* register service worker file in, e.g., a scripts/ sub-directory!
// See https://github.com/slightlyoff/ServiceWorker/issues/468 // See https://github.com/slightlyoff/ServiceWorker/issues/468
navigator.serviceWorker.register('service-worker.js').then(function(reg) { navigator.serviceWorker
.register('service-worker.js')
.then(function(reg) {
// updatefound is fired if service-worker.js changes. // updatefound is fired if service-worker.js changes.
reg.onupdatefound = function() { reg.onupdatefound = function() {
// The updatefound event implies that reg.installing is set; see // The updatefound event implies that reg.installing is set; see
@ -50,12 +51,15 @@ if ('serviceWorker' in navigator) {
break; break;
case 'redundant': case 'redundant':
console.error('The installing service worker became redundant.'); console.error(
'The installing service worker became redundant.'
);
break; break;
} }
}; };
}; };
}).catch(function(e) { })
.catch(function(e) {
console.error('Error during service worker registration:', e); console.error('Error during service worker registration:', e);
}); });
}); });
@ -246,20 +250,25 @@ if ('serviceWorker' in navigator) {
window.chrome = window.chrome || {}; window.chrome = window.chrome || {};
window.chrome.i18n = { getMessage: () => {} }; window.chrome.i18n = { getMessage: () => {} };
window.IS_EXTENSION = !!window.chrome.extension;
})(); })();
(() => { (() => {
const FAUX_DELAY = 1; const FAUX_DELAY = 1;
var db;
var dbPromise;
var local = { var local = {
get: (obj, cb) => { get: (obj, cb) => {
if (typeof obj === 'string') {
const retVal = {}; const retVal = {};
if (typeof obj === 'string') {
retVal[obj] = JSON.parse(window.localStorage.getItem(obj)); retVal[obj] = JSON.parse(window.localStorage.getItem(obj));
setTimeout(() => cb(retVal), FAUX_DELAY); setTimeout(() => cb(retVal), FAUX_DELAY);
} else { } else {
const retVal = {};
Object.keys(obj).forEach(key => { Object.keys(obj).forEach(key => {
let val = window.localStorage.getItem(key); const val = window.localStorage.getItem(key);
retVal[key] = retVal[key] =
val === undefined || val === null ? obj[key] : JSON.parse(val); val === undefined || val === null ? obj[key] : JSON.parse(val);
}); });
@ -270,17 +279,189 @@ if ('serviceWorker' in navigator) {
Object.keys(obj).forEach(key => { Object.keys(obj).forEach(key => {
window.localStorage.setItem(key, JSON.stringify(obj[key])); window.localStorage.setItem(key, JSON.stringify(obj[key]));
}); });
/* eslint-disable consistent-return */
setTimeout(() => { setTimeout(() => {
if (cb) cb(); if (cb) {
return cb();
}
}, FAUX_DELAY); }, FAUX_DELAY);
/* eslint-enable consistent-return */
} }
}; };
const dbLocalAlias = chrome && chrome.storage ? chrome.storage.local : local;
const dbSyncAlias = chrome && chrome.storage ? chrome.storage.sync : local;
async function getDb() {
if (dbPromise) {
return dbPromise;
}
utils.log('Initializing firestore');
dbPromise = new Promise((resolve, reject) => {
if (db) {
return resolve(db);
}
return firebase
.firestore()
.enablePersistence()
.then(function() {
// Initialize Cloud Firestore through firebase
db = firebase.firestore();
utils.log('firebase db ready', db);
resolve(db);
})
.catch(function(err) {
reject(err.code);
if (err.code === 'failed-precondition') {
// Multiple tabs open, persistence can only be enabled
// in one tab at a a time.
// ...
} else if (err.code === 'unimplemented') {
// The current browser does not support all of the
// features required to enable persistence
// ...
}
});
});
return dbPromise;
}
async function getUserLastSeenVersion() {
const d = deferred();
// Will be chrome.storage.sync in extension environment,
// otherwise will fallback to localstorage
dbSyncAlias.get(
{
lastSeenVersion: ''
},
result => {
d.resolve(result.lastSeenVersion);
}
);
return d.promise;
// Might consider getting actual value from remote db.
// Not critical right now.
}
async function setUserLastSeenVersion(version) {
if (window.IS_EXTENSION) {
chrome.storage.sync.set(
{
lastSeenVersion: version
},
function() {}
);
return;
}
// Settings the lastSeenVersion in localStorage also because next time we need
// to fetch it irrespective of the user being logged in or out
local.set({ lastSeenVersion: version });
if (window.user) {
const remoteDb = await getDb();
remoteDb
.doc(`users/${window.user.uid}`)
.update({ lastSeenVersion: version });
}
}
async function getUser(userId) {
const remoteDb = await getDb();
return remoteDb.doc(`users/${userId}`).get().then(doc => {
if (!doc.exists)
return remoteDb.doc(`users/${userId}`).set({}, { merge: true });
const user = doc.data();
Object.assign(window.user, user);
return user;
});
}
function getSettings(defaultSettings) {
const d = deferred();
// Will be chrome.storage.sync in extension environment,
// otherwise will fallback to localstorage
dbSyncAlias.get(defaultSettings, result => {
d.resolve(result);
});
return d.promise;
}
window.db = { window.db = {
local: chrome && chrome.storage ? chrome.storage.local : local, getDb,
sync: chrome && chrome.storage ? chrome.storage.sync : local getUser,
getUserLastSeenVersion,
setUserLastSeenVersion,
getSettings,
local: dbLocalAlias,
sync: dbSyncAlias
}; };
})(); })();
window.logout = function logout() {
firebase.auth().signOut();
};
function login(providerName) {
var provider;
if (providerName === 'fb') {
provider = new firebase.auth.FacebookAuthProvider();
} else if (providerName === 'twitter') {
provider = new firebase.auth.TwitterAuthProvider();
} else if (providerName === 'google') {
provider = new firebase.auth.GoogleAuthProvider();
provider.addScope('https://www.googleapis.com/auth/userinfo.profile');
} else {
provider = new firebase.auth.GithubAuthProvider();
}
return firebase
.auth()
.signInWithPopup(provider)
.then(function(result) {
return;
// Save this user in the store
firebase
.database()
.ref('users/' + result.user.uid)
.update({
displayName: result.user.displayName,
email: result.user.email,
photoURL: result.user.providerData[0].photoURL,
signedUpOn: Date.now()
})
.then(function() {
// Port items in localstorage to user account
if (window.localStorage.prototyp) {
var items = JSON.parse(window.localStorage.prototyp);
var newItemKey;
items.forEach(function(localItem) {
itemService.fetchItem(localItem.id).then(function(item) {
newItemKey = firebase.database().ref('pens').push().key;
item.createdBy = result.user.uid;
delete item.uid;
firebase.database().ref('pens/' + newItemKey).set(item);
firebase
.database()
.ref('users/' + result.user.uid)
.child('items')
.child(newItemKey)
.set(true);
});
});
delete localStorage.prototyp;
}
});
})
.catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// The email of the user's account used.
var email = error.email;
// The firebase.auth.AuthCredential type that was used.
var credential = error.credential;
utils.log(error);
});
}
window.login = login;
/* global ga */ /* global ga */
// eslint-disable-next-line max-params // eslint-disable-next-line max-params
window.trackEvent = function(category, action, label, value) { window.trackEvent = function(category, action, label, value) {
@ -665,6 +846,201 @@ window.cssLibs = [
window.TextareaAutoComplete = TextareaAutoComplete; window.TextareaAutoComplete = TextareaAutoComplete;
})(); })();
(() => {
window.itemService = {
async getItem(id) {
var remoteDb = await window.db.getDb();
return remoteDb.doc(`items/${id}`).get().then(doc => {
return doc.data();
});
},
async getUserItemIds() {
if (window.user) {
return new Promise(resolve => {
resolve(window.user.items || {});
});
}
var remoteDb = await window.db.getDb();
return remoteDb.doc(`users/${window.user.uid}`).get().then(doc => {
if (!doc.exists) {
return {};
}
return doc.data().items;
});
},
async getAllItems() {
var d = deferred();
let itemIds = await this.getUserItemIds();
itemIds = Object.getOwnPropertyNames(itemIds || {});
utils.log('itemids', itemIds);
if (!itemIds.length) {
d.resolve([]);
}
const items = [];
for (let i = 0; i < itemIds.length; i++) {
const id = itemIds[i];
utils.log('Starting to fetch item ', id);
this.getItem(id).then(item => {
items.push(item);
// Check if we have all items now.
if (itemIds.length === items.length) {
d.resolve(items);
}
});
}
return d.promise;
},
async setUser() {
const remoteDb = await window.db.getDb();
return remoteDb.doc(`users/${window.user.uid}`).set({
items: {}
});
},
async setItem(id, item) {
if (!window.user) {
return new Promise(resolve => resolve());
}
var remoteDb = await window.db.getDb();
utils.log(`Starting to save item ${id}`);
item.createdBy = window.user.uid;
return remoteDb
.collection('items')
.doc(id)
.set(item, {
merge: true
})
.then(arg => {
utils.log('Document written', arg);
})
.catch(error => utils.log(error));
},
/**
* Saves the passed items in the database.
* @param {Array} items to be saved in DB
*/
saveItems(items) {
var d = deferred();
if (window.IS_EXTENSION) {
// save new items
window.db.local.set(items, d.resolve);
// Push in new item IDs
window.db.local.get(
{
items: {}
},
function(result) {
/* eslint-disable guard-for-in */
for (var id in items) {
result.items[id] = true;
}
window.db.local.set({
items: result.items
});
/* eslint-enable guard-for-in */
}
);
} else {
window.db.getDb().then(remoteDb => {
const batch = remoteDb.batch();
/* eslint-disable guard-for-in */
for (var id in items) {
items[id].createdBy = window.user.uid;
batch.set(remoteDb.doc(`items/${id}`), items[id]);
batch.update(remoteDb.doc(`users/${window.user.uid}`), {
[`items.${id}`]: true
});
// Set these items on out cached user object too
window.user.items[id] = true;
}
batch.commit().then(d.resolve);
/* eslint-enable guard-for-in */
});
}
return d.promise;
},
async removeItem(id) {
if (window.IS_EXTENSION) {
var d = deferred();
db.local.remove(id, d.resolve);
return d.promise;
}
const remoteDb = await window.db.getDb();
utils.log(`Starting to save item ${id}`);
return remoteDb
.collection('items')
.doc(id)
.delete()
.then(arg => {
utils.log('Document removed', arg);
})
.catch(error => utils.log(error));
},
async setItemForUser(itemId) {
if (window.IS_EXTENSION || !window.user) {
return window.db.local.get(
{
items: {}
},
function(result) {
result.items[itemId] = true;
window.db.local.set({
items: result.items
});
}
);
}
const remoteDb = await window.db.getDb();
return remoteDb
.collection('users')
.doc(window.user.uid)
.update({
[`items.${itemId}`]: true
})
.then(arg => {
utils.log(`Item ${itemId} set for user`, arg);
window.user.items = window.user.items || {};
window.user.items[itemId] = true;
})
.catch(error => utils.log(error));
},
async unsetItemForUser(itemId) {
if (window.IS_EXTENSION) {
return window.db.local.get(
{
items: {}
},
function(result) {
delete result.items[itemId];
db.local.set({
items: result.items
});
}
);
}
const remoteDb = await window.db.getDb();
return remoteDb
.collection('users')
.doc(window.user.uid)
.update({
[`items.${itemId}`]: firebase.firestore.FieldValue.delete()
})
.then(arg => {
utils.log(`Item ${itemId} unset for user`, arg);
})
.catch(error => utils.log(error));
}
};
})();
/* global trackEvent */ /* global trackEvent */
/* global layoutBtn1, layoutBtn2, layoutBtn3, helpModal, notificationsModal, addLibraryModal, /* global layoutBtn1, layoutBtn2, layoutBtn3, helpModal, notificationsModal, addLibraryModal,
onboardModal, layoutBtn1, layoutBtn2, layoutBtn3, layoutBtn4, onboardModal, onboardModal, onboardModal, layoutBtn1, layoutBtn2, layoutBtn3, layoutBtn4, onboardModal, onboardModal,
@ -674,18 +1050,41 @@ onboardModal, settingsModal, notificationsBtn, onboardShowInTabOptionBtn, editor
onboardDontShowInTabOptionBtn, TextareaAutoComplete, savedItemCountEl, indentationSizeValueEl, onboardDontShowInTabOptionBtn, TextareaAutoComplete, savedItemCountEl, indentationSizeValueEl,
runBtn, searchInput, consoleEl, consoleLogEl, logCountEl, fontStyleTag, fontStyleTemplate, runBtn, searchInput, consoleEl, consoleLogEl, logCountEl, fontStyleTag, fontStyleTemplate,
customEditorFontInput, cssSettingsModal, cssSettingsBtn, acssSettingsTextarea, customEditorFontInput, cssSettingsModal, cssSettingsBtn, acssSettingsTextarea,
globalConsoleContainerEl, externalLibrarySearchInput, keyboardShortcutsModal globalConsoleContainerEl, externalLibrarySearchInput, keyboardShortcutsModal, headerAvatarImg,
loginModal
*/ */
/* eslint-disable no-extra-semi */ /* eslint-disable no-extra-semi */
(function(alertsService) { (function(alertsService, itemService) {
/* eslint-enable no-extra-semi */ /* eslint-enable no-extra-semi */
var scope = scope || {}; var scope = scope || {};
var version = '2.9.4'; var version = '2.9.6';
if (window.DEBUG) { if (window.DEBUG) {
window.scope = scope; window.scope = scope;
} }
const defaultSettings = {
preserveLastCode: true,
replaceNewTab: false,
htmlMode: 'html',
jsMode: 'js',
cssMode: 'css',
isCodeBlastOn: false,
indentWith: 'spaces',
indentSize: 2,
editorTheme: 'monokai',
keymap: 'sublime',
fontSize: 16,
refreshOnResize: false,
autoPreview: true,
editorFont: 'FiraCode',
editorCustomFont: '',
autoSave: true,
autoComplete: true,
preserveConsoleLogs: true,
lightVersion: false,
lineWrap: true
};
var HtmlModes = { var HtmlModes = {
HTML: 'html', HTML: 'html',
MARKDOWN: 'markdown', MARKDOWN: 'markdown',
@ -968,8 +1367,9 @@ globalConsoleContainerEl, externalLibrarySearchInput, keyboardShortcutsModal
function saveSetting(setting, value) { function saveSetting(setting, value) {
const d = deferred(); const d = deferred();
var obj = {}; const obj = {
obj[setting] = value; [setting]: value
};
db.local.set(obj, d.resolve); db.local.set(obj, d.resolve);
return d.promise; return d.promise;
} }
@ -990,17 +1390,7 @@ globalConsoleContainerEl, externalLibrarySearchInput, keyboardShortcutsModal
}); });
// Push into the items hash if its a new item being saved // Push into the items hash if its a new item being saved
if (isNewItem) { if (isNewItem) {
db.local.get( itemService.setItemForUser(currentItem.id);
{
items: {}
},
function(result) {
result.items[currentItem.id] = true;
db.local.set({
items: result.items
});
}
);
} }
} }
@ -1075,7 +1465,8 @@ globalConsoleContainerEl, externalLibrarySearchInput, keyboardShortcutsModal
currentItem.mainSizes = getMainPaneSizes(); currentItem.mainSizes = getMainPaneSizes();
utils.log('saving key', key || currentItem.id, currentItem); utils.log('saving key', key || currentItem.id, currentItem);
return saveSetting(key || currentItem.id, currentItem).then(() => { saveSetting(key || currentItem.id, currentItem);
return itemService.setItem(key || currentItem.id, currentItem).then(() => {
alertsService.add('Item saved.'); alertsService.add('Item saved.');
unsavedEditCount = 0; unsavedEditCount = 0;
saveBtn.classList.remove('is-marked'); saveBtn.classList.remove('is-marked');
@ -1139,16 +1530,27 @@ globalConsoleContainerEl, externalLibrarySearchInput, keyboardShortcutsModal
* @param {boolean} shouldSaveGlobally Whether to store the fetched items in global arr for later use. * @param {boolean} shouldSaveGlobally Whether to store the fetched items in global arr for later use.
* @return {promise} Promise. * @return {promise} Promise.
*/ */
function fetchItems(shouldSaveGlobally) { async function fetchItems(shouldSaveGlobally) {
var d = deferred(); var d = deferred();
savedItems = savedItems || {};
var items = [];
if (!window.IS_EXTENSION && window.user) {
items = await itemService.getAllItems();
if (shouldSaveGlobally) {
items.forEach(item => {
savedItems[item.id] = item;
});
}
d.resolve(items);
return d.promise;
}
db.local.get('items', function(result) { db.local.get('items', function(result) {
var itemIds = Object.getOwnPropertyNames(result.items || {}), var itemIds = Object.getOwnPropertyNames(result.items || {});
items = [];
if (!itemIds.length) { if (!itemIds.length) {
d.resolve([]); d.resolve([]);
} }
savedItems = savedItems || {};
trackEvent('fn', 'fetchItems', itemIds.length); trackEvent('fn', 'fetchItems', itemIds.length);
for (let i = 0; i < itemIds.length; i++) { for (let i = 0; i < itemIds.length; i++) {
/* eslint-disable no-loop-func */ /* eslint-disable no-loop-func */
@ -1176,6 +1578,8 @@ globalConsoleContainerEl, externalLibrarySearchInput, keyboardShortcutsModal
} }
function setCurrentItem(item) { function setCurrentItem(item) {
currentItem = item; currentItem = item;
utils.log('Current Item set', item);
// Reset auto-saving flag // Reset auto-saving flag
isAutoSavingEnabled = false; isAutoSavingEnabled = false;
// Reset unsaved count, in UI also. // Reset unsaved count, in UI also.
@ -1240,26 +1644,17 @@ globalConsoleContainerEl, externalLibrarySearchInput, keyboardShortcutsModal
itemTile.remove(); itemTile.remove();
// Remove from items list // Remove from items list
db.local.get( itemService.unsetItemForUser(itemId);
{
items: {}
},
function(result) {
delete result.items[itemId];
db.local.set({
items: result.items
});
}
);
// Remove individual item too. // Remove individual item too.
db.local.remove(itemId, function() { itemService.removeItem(itemId).then(() => {
alertsService.add('Item removed.'); alertsService.add('Item removed.');
// This item is open in the editor. Lets open a new one. // This item is open in the editor. Lets open a new one.
if (currentItem.id === itemId) { if (currentItem.id === itemId) {
createNewItem(); createNewItem();
} }
}); });
// Remove from cached list // Remove from cached list
delete savedItems[itemId]; delete savedItems[itemId];
@ -1316,6 +1711,7 @@ globalConsoleContainerEl, externalLibrarySearchInput, keyboardShortcutsModal
settingsModal.classList.remove('is-modal-visible'); settingsModal.classList.remove('is-modal-visible');
cssSettingsModal.classList.remove('is-modal-visible'); cssSettingsModal.classList.remove('is-modal-visible');
keyboardShortcutsModal.classList.remove('is-modal-visible'); keyboardShortcutsModal.classList.remove('is-modal-visible');
loginModal.classList.remove('is-modal-visible');
toggleSavedItemsPane(false); toggleSavedItemsPane(false);
document.dispatchEvent(new Event('overlaysClosed')); document.dispatchEvent(new Event('overlaysClosed'));
} }
@ -1743,7 +2139,8 @@ globalConsoleContainerEl, externalLibrarySearchInput, keyboardShortcutsModal
} }
function createPreviewFile(html, css, js) { function createPreviewFile(html, css, js) {
const shouldInlineJs = !window.webkitRequestFileSystem; const shouldInlineJs =
!window.webkitRequestFileSystem || !window.IS_EXTENSION;
var contents = getCompleteHtml(html, css, shouldInlineJs ? js : null); var contents = getCompleteHtml(html, css, shouldInlineJs ? js : null);
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' });
@ -2084,6 +2481,9 @@ globalConsoleContainerEl, externalLibrarySearchInput, keyboardShortcutsModal
var existingItemIds = []; var existingItemIds = [];
var toMergeItems = {}; var toMergeItems = {};
items.forEach(item => { items.forEach(item => {
// 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.
if (savedItems[item.id]) { if (savedItems[item.id]) {
// Item already exists // Item already exists
existingItemIds.push(item.id); existingItemIds.push(item.id);
@ -2107,31 +2507,12 @@ globalConsoleContainerEl, externalLibrarySearchInput, keyboardShortcutsModal
} }
} }
if (mergedItemCount) { if (mergedItemCount) {
// save new items itemService.saveItems(toMergeItems).then(() => {
db.local.set(toMergeItems, function() {
alertsService.add( alertsService.add(
mergedItemCount + ' creations imported successfully.' mergedItemCount + ' creations imported successfully.'
); );
});
// Push in new item IDs
db.local.get(
{
items: {}
},
function(result) {
/* eslint-disable guard-for-in */
for (var id in toMergeItems) {
result.items[id] = true;
}
db.local.set({
items: result.items
});
trackEvent('fn', 'itemsImported', mergedItemCount); trackEvent('fn', 'itemsImported', mergedItemCount);
});
/* eslint-enable guard-for-in */
}
);
alertsService.add(mergedItemCount + ' creations imported successfully.');
} }
// FIXME: Move from here // FIXME: Move from here
toggleSavedItemsPane(false); toggleSavedItemsPane(false);
@ -2150,7 +2531,8 @@ globalConsoleContainerEl, externalLibrarySearchInput, keyboardShortcutsModal
items = JSON.parse(progressEvent.target.result); items = JSON.parse(progressEvent.target.result);
utils.log(items); utils.log(items);
mergeImportedItems(items); mergeImportedItems(items);
} catch (ex) { } catch (exception) {
utils.log(exception);
alert( alert(
'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.'
); );
@ -2371,9 +2753,26 @@ globalConsoleContainerEl, externalLibrarySearchInput, keyboardShortcutsModal
utils.log(settingName, el.type === 'checkbox' ? el.checked : el.value); utils.log(settingName, el.type === 'checkbox' ? el.checked : el.value);
prefs[settingName] = el.type === 'checkbox' ? el.checked : el.value; prefs[settingName] = el.type === 'checkbox' ? el.checked : el.value;
obj[settingName] = prefs[settingName]; obj[settingName] = prefs[settingName];
// In case of !extension, we save in localstorage so that it gets fetched
// faster on future loads.
db.sync.set(obj, function() { db.sync.set(obj, function() {
alertsService.add('Setting saved'); alertsService.add('Setting saved');
}); });
if (!window.IS_EXTENSION) {
window.db.getDb().then(remoteDb => {
remoteDb
.collection('users')
.doc(window.user.uid)
.update({
[`settings.${settingName}`]: prefs[settingName]
})
.then(arg => {
utils.log(`Setting "${settingName}" for user`, arg);
})
.catch(error => utils.log(error));
});
}
trackEvent('ui', 'updatePref-' + settingName, prefs[settingName]); trackEvent('ui', 'updatePref-' + settingName, prefs[settingName]);
} }
@ -2559,9 +2958,21 @@ globalConsoleContainerEl, externalLibrarySearchInput, keyboardShortcutsModal
/* eslint-enable no-param-reassign */ /* eslint-enable no-param-reassign */
}; };
function compileNodes() { /**
* Compiles directives on the given node
* @param {Node} root The element on which compilation is required
*/
function compileNodes(root) {
if (!(root instanceof Node)) {
/* eslint-disable no-param-reassign */
root = document;
/* eslint-enable no-param-reassign */
}
// Create a querySelectorAll function bound to the passed `root` Node
const query = selector => [...root.querySelectorAll(selector)];
function attachListenerForEvent(eventName) { function attachListenerForEvent(eventName) {
const nodes = $all(`[d-${eventName}]`); const nodes = query(`[d-${eventName}]`);
nodes.forEach(function(el) { nodes.forEach(function(el) {
el.addEventListener(eventName, function(e) { el.addEventListener(eventName, function(e) {
scope[el.getAttribute(`d-${eventName}`)].call(window, e); scope[el.getAttribute(`d-${eventName}`)].call(window, e);
@ -2574,7 +2985,7 @@ globalConsoleContainerEl, externalLibrarySearchInput, keyboardShortcutsModal
attachListenerForEvent('keyup'); attachListenerForEvent('keyup');
// Compile d-open-modal directive // Compile d-open-modal directive
const modalTriggers = $all(`[d-open-modal]`); const modalTriggers = query(`[d-open-modal]`);
modalTriggers.forEach(function(el) { modalTriggers.forEach(function(el) {
utils.onButtonClick(el, function() { utils.onButtonClick(el, function() {
scope.toggleModal(window[el.getAttribute('d-open-modal')]); scope.toggleModal(window[el.getAttribute('d-open-modal')]);
@ -2586,7 +2997,7 @@ globalConsoleContainerEl, externalLibrarySearchInput, keyboardShortcutsModal
}); });
// Compile d-html directive // Compile d-html directive
const dHtmlNodes = $all(`[d-html]`); const dHtmlNodes = query(`[d-html]`);
dHtmlNodes.forEach(function(el) { dHtmlNodes.forEach(function(el) {
fetch(el.getAttribute('d-html')).then(response => { fetch(el.getAttribute('d-html')).then(response => {
// Stop further compilation because of future recursion by removing attribute. // Stop further compilation because of future recursion by removing attribute.
@ -2594,6 +3005,8 @@ globalConsoleContainerEl, externalLibrarySearchInput, keyboardShortcutsModal
response.text().then(html => { response.text().then(html => {
requestIdleCallback(() => { requestIdleCallback(() => {
el.innerHTML = html; el.innerHTML = html;
// Now compile this newly inserted HTML also.
compileNodes(el);
}); });
}); });
}); });
@ -2649,7 +3062,60 @@ globalConsoleContainerEl, externalLibrarySearchInput, keyboardShortcutsModal
e.preventDefault(); e.preventDefault();
}; };
scope.updateProfileUi = () => {
if (window.user) {
document.body.classList.add('is-logged-in');
headerAvatarImg.src = window.user.photoURL;
} else {
document.body.classList.remove('is-logged-in');
headerAvatarImg.src = '';
}
};
scope.login = e => {
firebase.auth().signInAnonymously().then().catch(function(error) {
// Handle Errors here.
utils.log(error);
});
if (e) {
e.preventDefault();
}
};
scope.login = window.login;
scope.logout = window.logout;
function init() { function init() {
var config = {
apiKey: 'AIzaSyBl8Dz7ZOE7aP75mipYl2zKdLSRzBU2fFc',
authDomain: 'web-maker-app.firebaseapp.com',
databaseURL: 'https://web-maker-app.firebaseio.com',
projectId: 'web-maker-app',
storageBucket: 'web-maker-app.appspot.com',
messagingSenderId: '560473480645'
};
firebase.initializeApp(config);
firebase.auth().onAuthStateChanged(function(user) {
scope.closeAllOverlays();
if (user) {
utils.log('You are -> ', user);
alertsService.add('You are now logged in!');
scope.user = window.user = user;
window.db.getUser(user.uid).then(customUser => {
if (customUser) {
Object.assign(prefs, user.settings);
updateSettingsInUi();
scope.updateSetting();
}
});
} else {
delete window.user;
// User is signed out.
}
scope.updateProfileUi();
});
var lastCode; var lastCode;
CodeMirror.modeURL = `lib/codemirror/mode/%N/%N.js`; CodeMirror.modeURL = `lib/codemirror/mode/%N/%N.js`;
@ -2676,12 +3142,7 @@ globalConsoleContainerEl, externalLibrarySearchInput, keyboardShortcutsModal
) { ) {
hasSeenNotifications = true; hasSeenNotifications = true;
notificationsBtn.classList.remove('has-new'); notificationsBtn.classList.remove('has-new');
db.sync.set( window.db.setUserLastSeenVersion(version);
{
lastSeenVersion: version
},
function() {}
);
} }
trackEvent('ui', 'notificationButtonClick', version); trackEvent('ui', 'notificationButtonClick', version);
return false; return false;
@ -2816,7 +3277,11 @@ globalConsoleContainerEl, externalLibrarySearchInput, keyboardShortcutsModal
event.preventDefault(); event.preventDefault();
openSavedItemsPane(); openSavedItemsPane();
trackEvent('ui', 'openCreationKeyboardShortcut'); trackEvent('ui', 'openCreationKeyboardShortcut');
} else if ((event.ctrlKey || event.metaKey) && event.keyCode === 191) { } else if (
(event.ctrlKey || event.metaKey) &&
event.shiftKey &&
event.keyCode === 191
) {
// Ctrl/⌘ + Shift + ? // Ctrl/⌘ + Shift + ?
event.preventDefault(); event.preventDefault();
scope.toggleModal(keyboardShortcutsModal); scope.toggleModal(keyboardShortcutsModal);
@ -2980,37 +3445,17 @@ globalConsoleContainerEl, externalLibrarySearchInput, keyboardShortcutsModal
); );
// Get synced `preserveLastCode` setting to get back last code (or not). // Get synced `preserveLastCode` setting to get back last code (or not).
db.sync.get( db.getSettings(defaultSettings).then(result => {
{
preserveLastCode: true,
replaceNewTab: false,
htmlMode: 'html',
jsMode: 'js',
cssMode: 'css',
isCodeBlastOn: false,
indentWith: 'spaces',
indentSize: 2,
editorTheme: 'monokai',
keymap: 'sublime',
fontSize: 16,
refreshOnResize: false,
autoPreview: true,
editorFont: 'FiraCode',
editorCustomFont: '',
autoSave: true,
autoComplete: true,
preserveConsoleLogs: true,
lightVersion: false,
lineWrap: true
},
function syncGetCallback(result) {
if (result.preserveLastCode && lastCode) { if (result.preserveLastCode && lastCode) {
unsavedEditCount = 0; unsavedEditCount = 0;
if (lastCode.id) { if (lastCode.id) {
// Ignore for remote db
db.local.get(lastCode.id, function(itemResult) { db.local.get(lastCode.id, function(itemResult) {
if (itemResult[lastCode.id]) {
utils.log('Load item ', lastCode.id); utils.log('Load item ', lastCode.id);
currentItem = itemResult[lastCode.id]; currentItem = itemResult[lastCode.id];
refreshEditor(); refreshEditor();
}
}); });
} else { } else {
utils.log('Load last unsaved item', lastCode); utils.log('Load last unsaved item', lastCode);
@ -3020,78 +3465,34 @@ globalConsoleContainerEl, externalLibrarySearchInput, keyboardShortcutsModal
} else { } else {
createNewItem(); createNewItem();
} }
prefs.preserveLastCode = result.preserveLastCode; Object.assign(prefs, result);
prefs.replaceNewTab = result.replaceNewTab;
prefs.htmlMode = result.htmlMode;
prefs.cssMode = result.cssMode;
prefs.jsMode = result.jsMode;
prefs.isCodeBlastOn = result.isCodeBlastOn;
prefs.indentSize = result.indentSize;
prefs.indentWith = result.indentWith;
prefs.editorTheme = result.editorTheme;
prefs.keymap = result.keymap;
prefs.fontSize = result.fontSize;
prefs.refreshOnResize = result.refreshOnResize;
prefs.autoPreview = result.autoPreview;
prefs.editorFont = result.editorFont;
prefs.editorCustomFont = result.editorCustomFont;
prefs.autoSave = result.autoSave;
prefs.autoComplete = result.autoComplete;
prefs.preserveConsoleLogs = result.preserveConsoleLogs;
prefs.lightVersion = result.lightVersion;
prefs.lineWrap = result.lineWrap;
updateSettingsInUi(); updateSettingsInUi();
scope.updateSetting(); scope.updateSetting();
} });
);
// Check for new version notifications // Check for new version notifications
db.sync.get( db.getUserLastSeenVersion().then(lastSeenVersion => {
{
lastSeenVersion: ''
},
function syncGetCallback(result) {
// Check if new user // Check if new user
if (!result.lastSeenVersion) { if (!lastSeenVersion) {
onboardModal.classList.add('is-modal-visible'); onboardModal.classList.add('is-modal-visible');
if (document.cookie.indexOf('onboarded') === -1) { if (document.cookie.indexOf('onboarded') === -1) {
trackEvent('ui', 'onboardModalSeen', version); trackEvent('ui', 'onboardModalSeen', version);
document.cookie = 'onboarded=1'; document.cookie = 'onboarded=1';
} }
db.sync.set( window.db.setUserLastSeenVersion(version);
{
lastSeenVersion: version
},
function() {}
);
// set some initial preferences on closing the onboard modal // set some initial preferences on closing the onboard modal
utils.once(document, 'overlaysClosed', function() { // Old onboarding.
db.sync.set( // utils.once(document, 'overlaysClosed', function() {});
{
replaceNewTab: onboardShowInTabOptionBtn.classList.contains(
'selected'
)
},
function() {
trackEvent(
'fn',
'setReplaceNewTabFromOnboard',
onboardShowInTabOptionBtn.classList.contains('selected')
);
}
);
});
} }
if ( if (
!result.lastSeenVersion || !lastSeenVersion ||
utils.semverCompare(result.lastSeenVersion, version) === -1 utils.semverCompare(lastSeenVersion, version) === -1
) { ) {
notificationsBtn.classList.add('has-new'); notificationsBtn.classList.add('has-new');
hasSeenNotifications = false; hasSeenNotifications = false;
} }
} });
);
scope.acssSettingsCm = CodeMirror.fromTextArea(acssSettingsTextarea, { scope.acssSettingsCm = CodeMirror.fromTextArea(acssSettingsTextarea, {
mode: 'application/ld+json' mode: 'application/ld+json'
@ -3163,7 +3564,7 @@ globalConsoleContainerEl, externalLibrarySearchInput, keyboardShortcutsModal
scope.closeAllOverlays = closeAllOverlays; scope.closeAllOverlays = closeAllOverlays;
init(); init();
})(window.alertsService); })(window.alertsService, window.itemService);
// Dropdown.js // Dropdown.js

File diff suppressed because one or more lines are too long

View File

@ -348,6 +348,9 @@ body > #demo-frame {
.main-header__btn-wrap > a:hover { .main-header__btn-wrap > a:hover {
border-color: rgba(146, 151, 179, 0.5); border-color: rgba(146, 151, 179, 0.5);
} }
.main-header__avatar-img {
border-radius: 50%;
}
.logo { .logo {
display: inline-block; display: inline-block;
height: 25px; height: 25px;
@ -956,6 +959,11 @@ transition: 0.25s ease;
display: inline-block; display: inline-block;
} }
body.is-logged-in .hide-on-login,
body:not(.is-logged-in) .hide-on-logout {
display: none;
}
/* Codemirror themes basic bg styles. This is here so that there is no big FOUC /* Codemirror themes basic bg styles. This is here so that there is no big FOUC
while the theme CSS file is loading */ while the theme CSS file is loading */
.cm-s-paraiso-dark.CodeMirror { background: #2f1e2e; color: #b9b6b0; } .cm-s-paraiso-dark.CodeMirror { background: #2f1e2e; color: #b9b6b0; }

File diff suppressed because one or more lines are too long