mirror of
https://github.com/chinchang/web-maker.git
synced 2025-07-16 19:46:19 +02:00
add prettier support for js,css,markdown fixes #234
This commit is contained in:
@@ -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 (
|
||||
<SplitPane
|
||||
@@ -600,6 +616,12 @@ export default class ContentWrapFiles extends Component {
|
||||
{this.state.selectedFile ? this.state.selectedFile.name : ''}
|
||||
</label>
|
||||
<div class="code-wrap__header-right-options">
|
||||
<button
|
||||
class="btn btn--dark"
|
||||
onClick={this.prettifyBtnClickHandler.bind(this)}
|
||||
>
|
||||
Prettify
|
||||
</button>
|
||||
<a
|
||||
class="js-code-collapse-btn code-wrap__header-btn code-wrap__collapse-btn"
|
||||
title="Toggle code pane"
|
||||
@@ -607,6 +629,9 @@ export default class ContentWrapFiles extends Component {
|
||||
</div>
|
||||
</div>
|
||||
<UserCodeMirror
|
||||
value={
|
||||
this.state.selectedFile ? this.state.selectedFile.content : ''
|
||||
}
|
||||
options={this.state.editorOptions}
|
||||
prefs={this.props.prefs}
|
||||
onChange={this.onHtmlCodeChange.bind(this)}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import { h } from 'preact';
|
||||
import { getExtensionFromFileName } from '../fileUtils';
|
||||
|
||||
export function FileIcon({ file }) {
|
||||
let path;
|
||||
@@ -24,7 +25,7 @@ export function FileIcon({ file }) {
|
||||
);
|
||||
}
|
||||
} else {
|
||||
const type = file.name.match(/.(\w+)$/)[1];
|
||||
const type = getExtensionFromFileName(file.name);
|
||||
switch (type) {
|
||||
case 'html':
|
||||
path = (
|
||||
|
@@ -20,7 +20,8 @@ import {
|
||||
handleDownloadsPermission,
|
||||
downloadFile,
|
||||
getCompleteHtml,
|
||||
getFilenameFromUrl
|
||||
getFilenameFromUrl,
|
||||
prettify
|
||||
} from '../utils';
|
||||
import {
|
||||
linearizeFiles,
|
||||
@@ -29,6 +30,7 @@ import {
|
||||
removeFileAtPath,
|
||||
doesFileExistInFolder
|
||||
} from '../fileUtils';
|
||||
|
||||
import { itemService } from '../itemService';
|
||||
import '../db';
|
||||
import { Notifications } from './Notifications';
|
||||
@@ -740,7 +742,7 @@ export default class App extends Component {
|
||||
onCodeChange(type, code, isUserChange) {
|
||||
if (this.state.currentItem.files) {
|
||||
linearizeFiles(this.state.currentItem.files).map(file => {
|
||||
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 (
|
||||
<div class={this.getRootClasses()}>
|
||||
@@ -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)}
|
||||
/>
|
||||
) : (
|
||||
<ContentWrap
|
||||
|
@@ -1,6 +1,15 @@
|
||||
import { deferred } from './deferred';
|
||||
const esprima = require('esprima');
|
||||
|
||||
/**
|
||||
* Returns the extension from the file name.
|
||||
* @param {dtring} fileName File name
|
||||
*/
|
||||
export function getExtensionFromFileName(fileName) {
|
||||
const type = fileName.match(/\.(\w+)$/);
|
||||
return type ? type[1] : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a linear file list from a nested file strcuture.
|
||||
* It excludes the folders from the returned list.
|
||||
|
@@ -4,7 +4,8 @@ import {
|
||||
assignFilePaths,
|
||||
getFileFromPath,
|
||||
removeFileAtPath,
|
||||
getParentPath
|
||||
getParentPath,
|
||||
getExtensionFromFileName
|
||||
} from '../fileUtils';
|
||||
|
||||
function getNestedFiles() {
|
||||
@@ -18,6 +19,17 @@ function getNestedFiles() {
|
||||
{ name: 'script.js' }
|
||||
];
|
||||
}
|
||||
describe('getExtensionFromFileName', () => {
|
||||
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' }];
|
||||
|
32
src/utils.js
32
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
|
||||
});
|
||||
}
|
||||
|
Reference in New Issue
Block a user