From 41ae269d9b263e64dda134fbc72d8ab0d2925c6f Mon Sep 17 00:00:00 2001 From: Kushagra Gour Date: Sun, 14 Oct 2018 16:30:28 +0530 Subject: [PATCH 1/6] add prettier support for js,css,markdown fixes #234 --- src/components/ContentWrapFiles.jsx | 35 ++++++++++++++++++++++++----- src/components/FileIcon.jsx | 3 ++- src/components/app.jsx | 20 +++++++++++++++-- src/fileUtils.js | 9 ++++++++ src/tests/fileUtils.test.js | 14 +++++++++++- src/utils.js | 32 ++++++++++++++++++++++++++ 6 files changed, 104 insertions(+), 9 deletions(-) diff --git a/src/components/ContentWrapFiles.jsx b/src/components/ContentWrapFiles.jsx index dc8751b..67a06c3 100644 --- a/src/components/ContentWrapFiles.jsx +++ b/src/components/ContentWrapFiles.jsx @@ -3,7 +3,7 @@ import UserCodeMirror from './UserCodeMirror'; import { modes, HtmlModes, CssModes, JsModes } from '../codeModes'; import { log, loadJS } from '../utils'; -import { linearizeFiles, assignFilePaths } from '../fileUtils'; +import { linearizeFiles, assignFilePaths, getFileFromPath } from '../fileUtils'; import { SplitPane } from './SplitPane'; import { trackEvent } from '../analytics'; @@ -58,6 +58,19 @@ export default class ContentWrapFiles extends Component { this.fileBuffers = {}; this.state.selectedFile = null; } + + if ( + nextProps.currentItem.files !== this.props.currentItem.files && + this.state.selectedFile && + this.fileBuffers[this.state.selectedFile.path] + ) { + this.fileBuffers[this.state.selectedFile.path].setValue( + getFileFromPath( + nextProps.currentItem.files, + this.state.selectedFile.path + ).file.content + ); + } } componentDidUpdate() { const { currentItem } = this.props; @@ -72,6 +85,7 @@ export default class ContentWrapFiles extends Component { ) { this.fileSelectHandler(linearFiles[0]); } + // HACK: becuase its a DOM manipulation // window.logCountEl.textContent = this.logCount; // log('🚀', 'didupdate', this.props.currentItem); @@ -125,7 +139,7 @@ export default class ContentWrapFiles extends Component { CodeMirror.autoLoadMode(this.cm, mode.cmPath || mode.cmMode); - this.fileBuffers[file.name] = CodeMirror.Doc( + this.fileBuffers[file.path] = CodeMirror.Doc( file.content || '', mode.cmMode ); @@ -259,7 +273,6 @@ export default class ContentWrapFiles extends Component { return !!item.title; } refreshEditor() { - this.cmCodes.html = this.props.currentItem.html; if (this.state.selectedFile) { this.cm.setValue(this.state.selectedFile.content); } @@ -458,10 +471,10 @@ export default class ContentWrapFiles extends Component { editorOptions: this.getEditorOptions(file.name), selectedFile: file }); - if (!this.fileBuffers[file.name]) { + if (!this.fileBuffers[file.path]) { this.createEditorDoc(file); } - this.cm.swapDoc(this.fileBuffers[file.name]); + this.cm.swapDoc(this.fileBuffers[file.path]); // var cmMode = 'html'; // if (file.name.match(/\.css$/)) { @@ -561,6 +574,9 @@ export default class ContentWrapFiles extends Component { } } + prettifyBtnClickHandler() { + this.props.onPrettifyBtnClick(this.state.selectedFile); + } render() { return (
+
{ - if (file.name === type.name) { + if (file.path === type.path) { file.content = code; } }); @@ -1291,6 +1293,19 @@ export default class App extends Component { return classes.join(' '); } + prettify(selectedFile) { + const currentItem = { + ...this.state.currentItem, + files: [...this.state.currentItem.files] + }; + const formattedContent = prettify(selectedFile); + if (formattedContent !== selectedFile.content) { + selectedFile.content = formattedContent; + this.incrementUnsavedChanges(); + this.setState({ currentItem }); + } + } + render() { return (
@@ -1327,6 +1342,7 @@ export default class App extends Component { onRenameFile={this.renameFileHandler.bind(this)} onFileDrop={this.fileDropHandler.bind(this)} onFolderSelect={this.folderSelectHandler.bind(this)} + onPrettifyBtnClick={this.prettify.bind(this)} /> ) : ( { + test('should return correct extension', () => { + expect(getExtensionFromFileName('test.js')).toBe('js'); + expect(getExtensionFromFileName('test.css')).toBe('css'); + expect(getExtensionFromFileName('test.main.css')).toBe('css'); + }); + test('should return empty string when no extension is found', () => { + expect(getExtensionFromFileName('hello')).toBe(''); + }); +}); + describe('assignFilePaths', () => { test('should assign path on linear file system', () => { const files = [{ name: 'index.html' }, { name: 'main.css' }]; diff --git a/src/utils.js b/src/utils.js index 4f5e495..58b895a 100644 --- a/src/utils.js +++ b/src/utils.js @@ -3,6 +3,7 @@ import { trackEvent } from './analytics'; import { computeHtml, computeCss, computeJs } from './computes'; import { JsModes } from './codeModes'; import { deferred } from './deferred'; +import { getExtensionFromFileName } from './fileUtils'; const esprima = require('esprima'); window.DEBUG = document.cookie.indexOf('wmdebug') > -1; @@ -465,3 +466,34 @@ if (window.IS_EXTENSION) { } else { document.body.classList.add('is-app'); } + +export function prettify(file) { + const prettier = require('prettier/standalone'); + const fileExtension = getExtensionFromFileName(file.name); + + let plugins, parser; + switch (fileExtension) { + case 'js': + parser = 'babylon'; + plugins = [require('prettier/parser-babylon')]; + break; + case 'css': + parser = 'css'; + plugins = [require('prettier/parser-postcss')]; + break; + case 'md': + case 'markdown': + parser = 'markdown'; + plugins = [require('prettier/parser-markdown')]; + break; + } + + if (!parser) { + return file.content; + } + + return prettier.format(file.content, { + parser, + plugins + }); +} From c371409d26d3317a76312f235c50d4bf14128e6e Mon Sep 17 00:00:00 2001 From: Kushagra Gour Date: Mon, 15 Oct 2018 15:39:00 +0530 Subject: [PATCH 2/6] ContentFileWrap: add comments --- src/components/ContentWrapFiles.jsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/ContentWrapFiles.jsx b/src/components/ContentWrapFiles.jsx index 67a06c3..8f310b0 100644 --- a/src/components/ContentWrapFiles.jsx +++ b/src/components/ContentWrapFiles.jsx @@ -51,6 +51,7 @@ export default class ContentWrapFiles extends Component { ); } componentWillUpdate(nextProps) { + // If we get a new Item, clear file buffers and currently selected file. if ( this.props.currentItem.createdOn !== nextProps.currentItem.createdOn || this.props.currentItem.id !== nextProps.currentItem.id @@ -59,6 +60,8 @@ export default class ContentWrapFiles extends Component { this.state.selectedFile = null; } + // If the files have changed and we have a selected file (even after previous condition), + // update the buffer with new file content (may be it got prettified?) if ( nextProps.currentItem.files !== this.props.currentItem.files && this.state.selectedFile && From f341488c17bd7cce72fb70923c9dd0907cdf38f5 Mon Sep 17 00:00:00 2001 From: Kushagra Gour Date: Mon, 15 Oct 2018 15:42:32 +0530 Subject: [PATCH 3/6] move prettier from devdep to dep --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 62f7b62..ac496b6 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,6 @@ "merge-stream": "^1.0.1", "preact-cli": "^2.1.0", "preact-render-spy": "^1.2.1", - "prettier": "^1.10.2", "run-sequence": "^2.2.1", "sw-precache": "^5.2.0" }, @@ -66,7 +65,8 @@ "preact-compat": "^3.17.0", "preact-portal": "^1.1.3", "preact-router": "^2.5.7", - "split.js": "1.3.4" + "split.js": "1.3.4", + "prettier": "^1.10.2" }, "jest": { "verbose": true, From ad210d0b25ed25cdc365377e40260e67a5fbcf2a Mon Sep 17 00:00:00 2001 From: Kushagra Gour Date: Mon, 15 Oct 2018 16:25:13 +0530 Subject: [PATCH 4/6] refactor mode detection to support more modes --- src/components/ContentWrapFiles.jsx | 35 ++++++++++++++--------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/components/ContentWrapFiles.jsx b/src/components/ContentWrapFiles.jsx index 8f310b0..eda83e7 100644 --- a/src/components/ContentWrapFiles.jsx +++ b/src/components/ContentWrapFiles.jsx @@ -3,11 +3,17 @@ import UserCodeMirror from './UserCodeMirror'; import { modes, HtmlModes, CssModes, JsModes } from '../codeModes'; import { log, loadJS } from '../utils'; -import { linearizeFiles, assignFilePaths, getFileFromPath } from '../fileUtils'; +import { + linearizeFiles, + assignFilePaths, + getFileFromPath, + getExtensionFromFileName +} from '../fileUtils'; 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'; @@ -125,26 +131,19 @@ export default class ContentWrapFiles extends Component { } createEditorDoc(file) { - let mode; - if (file.name.match(/\.css$/)) { - mode = modes[CssModes.CSS]; - } else if (file.name.match(/\.js$/)) { - mode = modes[JsModes.JS]; - } else if (file.name.match(/\.html$/)) { - mode = modes[HtmlModes.HTML]; - } else if (file.name.match(/\.md$/) || file.name.match(/\.markdown$/)) { - mode = modes[HtmlModes.MARKDOWN]; - } else if (file.name.match(/\.sass$/)) { - mode = modes[CssModes.SASS]; - } else if (file.name.match(/\.scss$/)) { - mode = modes[CssModes.SCSS]; + const detectedMode = CodeMirror.findModeByExtension( + getExtensionFromFileName(file.name) + ); + let mode, mime; + if (detectedMode) { + mode = detectedMode.mode; + mime = detectedMode.mimes ? detectedMode.mimes[0] : detectedMode.mime; + + CodeMirror.autoLoadMode(this.cm, mode); } - - CodeMirror.autoLoadMode(this.cm, mode.cmPath || mode.cmMode); - this.fileBuffers[file.path] = CodeMirror.Doc( file.content || '', - mode.cmMode + detectedMode ? mime : 'text/plain' ); } From 2b737bb5b453850d9612d7dfc16ed9192687f51e Mon Sep 17 00:00:00 2001 From: Kushagra Gour Date: Mon, 15 Oct 2018 16:53:38 +0530 Subject: [PATCH 5/6] support json mode and prettifying --- src/components/ContentWrapFiles.jsx | 3 +++ src/utils.js | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/src/components/ContentWrapFiles.jsx b/src/components/ContentWrapFiles.jsx index eda83e7..faa0d03 100644 --- a/src/components/ContentWrapFiles.jsx +++ b/src/components/ContentWrapFiles.jsx @@ -141,6 +141,9 @@ export default class ContentWrapFiles extends Component { CodeMirror.autoLoadMode(this.cm, mode); } + if (mime === 'application/json') { + mime = 'application/ld+json'; + } this.fileBuffers[file.path] = CodeMirror.Doc( file.content || '', detectedMode ? mime : 'text/plain' diff --git a/src/utils.js b/src/utils.js index 58b895a..469a3e2 100644 --- a/src/utils.js +++ b/src/utils.js @@ -477,6 +477,10 @@ export function prettify(file) { parser = 'babylon'; plugins = [require('prettier/parser-babylon')]; break; + case 'json': + parser = 'json'; + plugins = [require('prettier/parser-babylon')]; + break; case 'css': parser = 'css'; plugins = [require('prettier/parser-postcss')]; From 662cea4db18d335248fec4c5f12576be679bade1 Mon Sep 17 00:00:00 2001 From: Kushagra Gour Date: Mon, 15 Oct 2018 16:57:55 +0530 Subject: [PATCH 6/6] support sass/less prettifying --- src/utils.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/utils.js b/src/utils.js index 469a3e2..326b6f8 100644 --- a/src/utils.js +++ b/src/utils.js @@ -482,6 +482,9 @@ export function prettify(file) { plugins = [require('prettier/parser-babylon')]; break; case 'css': + case 'scss': + case 'sass': + case 'less': parser = 'css'; plugins = [require('prettier/parser-postcss')]; break;