Some refactoring and tidying

This commit is contained in:
Alex Hunt 2018-04-29 13:39:43 -04:00
parent dac188adf7
commit a6cf429335
35 changed files with 3367 additions and 394 deletions

View File

@ -25,9 +25,7 @@
TODAY:
- Light Refactoring
- Implement React-Router
- Review dependencies
@ -42,6 +40,7 @@ SHORT LIST:
- ES API Tests?
- Figure out Editor focus() with Redux
- Create Tags and Note Tagging
- Review dependencies
- v0.2 Reader
- Reader UX

View File

@ -1,52 +0,0 @@
from elasticsearch import Elasticsearch
from elasticsearch.helpers import bulk
# Elasticsearch index setup
#Elasticsearch local connection
#TODO: Extract to config
ELASTICSEARCH_HOST = '127.0.0.1:9200'
es = Elasticsearch(ELASTICSEARCH_HOST)
# DELETE ES INDEX:
es.indices.delete(index='joyce', ignore=[400, 404])
create_index_settings = {
'settings' : {
'index': {
'number_of_shards' : 1,
'number_of_replicas' : 0
},
'analysis': {
'analyzer': {
'html_analyzer': {
'type': 'custom',
'tokenizer': 'standard',
'char_filter': ['html_strip']
}
}
}
},
'mappings': {
'chapter': {
'properties': {
'number': {'type': 'integer'},
'title': {'type': 'keyword'},
'text': {
'type': 'text',
}
}
},
'note': {
'properties': {
'title': {'type': 'keyword'},
'text': {
'type': 'text',
}
}
}
}
}
es.indices.create(index='joyce', body=create_index_settings)
print 'Elasticsearch index created!'

Binary file not shown.

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 434 KiB

Binary file not shown.

Binary file not shown.

96
dist/js/editor.js vendored Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

96
dist/js/notes.js vendored Normal file

File diff suppressed because one or more lines are too long

96
dist/js/reader.js vendored Normal file

File diff suppressed because one or more lines are too long

96
dist/js/search.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -4,27 +4,23 @@
"description": "Reader and Editor for Hypertext",
"main": "app.js",
"scripts": {
"build": "webpack --config webpack.prod.js --mode=production",
"watch": "webpack --config webpack.dev.js --watch --mode=development",
"build": "webpack-cli --config webpack.prod.js --mode=production",
"watch": "webpack-cli --config webpack.dev.js --watch --mode=development",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Alex Hunt",
"license": "ISC",
"dependencies": {
"bootstrap": "^4.1.0",
"draft-js": "^0.10.4",
"draft-js-export-html": "^1.2.0",
"draft-js-export-markdown": "^1.2.0",
"draft-js-import-html": "^1.2.1",
"file-loader": "^1.1.11",
"font-awesome": "^4.7.0",
"object-assign": "^4.1.1",
"popper.js": "^1.12.6",
"react": "^16.0.0",
"react-dom": "^16.0.0",
"react-fontawesome": "^1.6.1",
"react-redux": "^5.0.6",
"redux": "^3.7.2"
"redux": "^3.7.2",
"draft-js": "^0.10.4",
"draft-js-export-html": "^1.2.0",
"draft-js-import-html": "^1.2.1",
"bootstrap": "^4.1.0",
"popper.js": "^1.12.6",
"font-awesome": "^4.7.0"
},
"devDependencies": {
"babel-core": "^6.26.0",
@ -34,7 +30,7 @@
"clean-webpack-plugin": "^0.1.17",
"css-loader": "^0.28.7",
"extract-text-webpack-plugin": "^3.0.2",
"file-loader": "^1.1.5",
"file-loader": "^1.1.11",
"manifest-revision-webpack-plugin": "^0.4.1",
"node-sass": "^4.6.0",
"postcss-loader": "^2.0.8",
@ -44,7 +40,6 @@
"sync-exec": "^0.6.2",
"webpack": "^4.6.0",
"webpack-bundle-analyzer": "^2.11.1",
"webpack-bundle-size-analyzer": "^2.7.0",
"webpack-cli": "^2.0.15",
"webpack-merge": "^4.1.2"
}

55
src/actions/apiActions.js Normal file
View File

@ -0,0 +1,55 @@
//
// API Request Actions
//
// These actions are handled by middleware and initiate
// an API request.
// Requesting the list of documents without complete text
export const getDocumentList = (response = {}) =>
({
type: 'GET_DOCUMENT_LIST',
docType: response.docType,
status: response.status ? response.status : 'request',
data: response.data,
state: response.state
})
// Requesting the full text of a given document
export const getDocumentText = (response = {}) =>
({
type: 'GET_DOCUMENT_TEXT',
id: response.id,
docType: response.docType,
status: response.status ? response.status : 'request',
data: response.data,
state: response.state,
})
// Deleting a given document
export const deleteDocument = (response = {}) =>
({
type: 'DELETE_DOCUMENT',
id: response.id,
docType: response.docType,
status: response.status ? response.status : 'request',
data: response.data
})
// Saving a document, create or update depending on if it receives an id
export const saveDocument = (response = {}) =>
({
type: 'SAVE_DOCUMENT',
id: response.id ? response.id : null,
docType: response.docType,
status: response.status ? response.status : 'request',
data: response.data
})
// Requesting search results with a search input
export const getSearchResults = (response={}) => {
return ({
type: 'GET_SEARCH_RESULTS',
data: response.data,
status: response.status ? response.status : 'request'
})
}

View File

@ -0,0 +1,27 @@
//
// EditorState Actions
//
// These actions handle state changes for the DraftJS editor
// Update EditorState on change
export const updateEditorState = editorState =>
({
type: 'UPDATE_EDITOR_STATE',
data: editorState
})
// Handle Editor inline style buttons
export const applyInlineStyles = (editorState, style) =>
({
type: 'APPLY_INLINE_STYLE',
editorState: editorState,
style: style
})
// Handle key commands to apply inline styles
export const handleEditorKeyCommand = (editorState, command) =>
({
type: 'HANDLE_EDITOR_KEY_COMMAND',
editorState: editorState,
command: command
})

View File

@ -1,194 +0,0 @@
// API Request Actions
export const getDocumentList = (response = {}) =>
({
type: 'GET_DOCUMENT_LIST',
docType: response.docType,
status: response.status ? response.status : 'request',
data: response.data,
state: response.state
})
export const getDocumentText = (response = {}) =>
({
type: 'GET_DOCUMENT_TEXT',
id: response.id,
docType: response.docType,
status: response.status ? response.status : 'request',
data: response.data,
state: response.state,
})
export const deleteDocument = (response = {}) =>
({
type: 'DELETE_DOCUMENT',
id: response.id,
docType: response.docType,
status: response.status ? response.status : 'request',
data: response.data
})
export const saveDocument = (response = {}) =>
({
type: 'SAVE_DOCUMENT',
id: response.id ? response.id : null,
docType: response.docType,
status: response.status ? response.status : 'request',
data: response.data
})
export const editTextReceived = data =>
({
type: 'UPDATE_EDITED_CHAPTER',
data: data
})
// Document Actions
export const setCurrentDocument = (id, docType) =>
({
type: 'SET_CURRENT_DOCUMENT',
id: id,
docType: docType
})
export const createNewDocument = docType =>
({
type: 'CREATE_DOCUMENT',
docType: docType
})
export const submitDocumentEdit = (currentDocument, editorState, documentTitleInput, docType) =>
({
type: 'SUBMIT_DOCUMENT_EDIT',
currentDocument: currentDocument,
editorState: editorState,
documentTitleInput: documentTitleInput,
docType: docType
})
export const deleteCurrentDocument = (id, docType) =>
({
type: 'DELETE_CURRENT_DOCUMENT',
id: id,
docType: docType
})
// Mode Actions
export const setMode = mode =>
({
type: 'SET_MODE',
mode: mode
})
export const cancelEdit = () =>
({
type: 'CANCEL_EDIT'
})
// EditorState Actions
export const updateEditorState = editorState =>
({
type: 'UPDATE_EDITOR_STATE',
data: editorState
})
export const applyInlineStyles = (editorState, style) =>
({
type: 'APPLY_INLINE_STYLE',
editorState: editorState,
style: style
})
export const handleEditorKeyCommand = (editorState, command) =>
({
type: 'HANDLE_EDITOR_KEY_COMMAND',
editorState: editorState,
command: command
})
// Note Highlight Actions
export const toggleHighlight = () =>
({
type: 'TOGGLE_HIGHLIGHT'
})
export const updateDocumentTitleChange = documentTitleInput => {
return ({
type: 'UPDATE_DOCUMENT_TITLE',
data: documentTitleInput.target.value
})
}
// DocType Actions
export const setDocType = docType =>
({
type: 'SET_DOC_TYPE',
docType: docType
})
// Annotation Actions
export const addAnnotation = data =>
({
type: 'ADD_ANNOTATION',
data: data
})
export const submitAnnotation = (annotationNote, selectionState, editorState) =>
({
type: 'SUBMIT_ANNOTATION',
annotationNote: annotationNote,
selectionState: selectionState,
editorState: editorState
})
export const removeAnnotation = (editorState) =>
({
type: 'REMOVE_ANNOTATION',
editorState: editorState,
selectionState: editorState.getSelection()
})
export const selectAnnotationNote = id =>
({
type: 'SELECT_ANNOTATION_NOTE',
id: id
})
// Search
export const updateSearchInput = searchInput => {
return ({
type: 'UPDATE_SEARCH_INPUT',
data: searchInput.target.value
})
}
// export const updateSearchResults = searchResults => {
// return ({
// type: 'UPDATE_SEARCH_RESULTS',
// data: searchResults
// })
// }
export const clickSearch = searchInput => {
console.log('click action gets ', searchInput)
return ({
type: 'CLICK_SEARCH',
data: searchInput
})
}
export const getSearchResults = (response={}) => {
return ({
type: 'GET_SEARCH_RESULTS',
data: response.data,
status: response.status ? response.status : 'request'
})
}

View File

@ -0,0 +1,20 @@
//
// Input Actions
//
// These actions handle states for the non-DraftJS input elements
// Handle changes to the document title input box
export const updateDocumentTitleChange = documentTitleInput => {
return ({
type: 'UPDATE_DOCUMENT_TITLE',
data: documentTitleInput.target.value
})
}
// Handle changes to the search input box
export const updateSearchInput = searchInput => {
return ({
type: 'UPDATE_SEARCH_INPUT',
data: searchInput.target.value
})
}

104
src/actions/userActions.js Normal file
View File

@ -0,0 +1,104 @@
//
// User Actions
//
// These actions are initiated by user action
// Select a document to read or edit
export const setCurrentDocument = (id, docType) =>
({
type: 'SET_CURRENT_DOCUMENT',
id: id,
docType: docType
})
// Click the 'New' button in the Editor
export const createNewDocument = docType =>
({
type: 'CREATE_DOCUMENT',
docType: docType
})
// Click 'Submit' to save a document edit
export const submitDocumentEdit = (currentDocument, editorState, documentTitleInput, docType) =>
({
type: 'SUBMIT_DOCUMENT_EDIT',
currentDocument: currentDocument,
editorState: editorState,
documentTitleInput: documentTitleInput,
docType: docType
})
// Click 'Cancel' to discard document changes
export const cancelEdit = () =>
({
type: 'CANCEL_EDIT'
})
// Click 'Delete' and confirm to delete a document
export const deleteCurrentDocument = (id, docType) =>
({
type: 'DELETE_CURRENT_DOCUMENT',
id: id,
docType: docType
})
// Toggle the button to hide or display note highlights
export const toggleHighlight = () => {
return ({
type: 'TOGGLE_HIGHLIGHT'
})
}
// Select 'Read', 'Edit' or 'Annotate' modes in the Editor
export const setMode = mode =>
({
type: 'SET_MODE',
mode: mode
})
// Click 'Search' to request search results
export const clickSearch = searchInput => {
return ({
type: 'CLICK_SEARCH',
data: searchInput
})
}
// Set the DocType to choose from in the Editor
export const setDocType = docType =>
({
type: 'SET_DOC_TYPE',
docType: docType
})
// Click 'Add Annotation' to enter 'Annotate' mode
export const addAnnotation = data =>
({
type: 'ADD_ANNOTATION',
data: data
})
// Click 'Submit' to save annotation
export const submitAnnotation = (annotationNote, selectionState, editorState) =>
({
type: 'SUBMIT_ANNOTATION',
annotationNote: annotationNote,
selectionState: selectionState,
editorState: editorState
})
// Click to remove selected Annotation
export const removeAnnotation = (editorState) =>
({
type: 'REMOVE_ANNOTATION',
editorState: editorState,
selectionState: editorState.getSelection()
})
// Click a link to choose the note that will be displayed in the modal
export const selectAnnotationNote = id =>
({
type: 'SELECT_ANNOTATION_NOTE',
id: id
})

View File

@ -6,7 +6,17 @@ import { ReadModeTopBar, EditModeTopBar, AnnotateModeTopBar } from '../componen
import { EditModeBottomBar } from '../components/contentBottomBar'
import DocumentTitle from '../components/documentTitle'
import LoadingSpinner from '../components/loadingSpinner'
import { updateEditorState, handleEditorKeyCommand, applyInlineStyles, setMode, cancelEdit, submitDocumentEdit, updateDocumentTitleChange, addAnnotation, removeAnnotation } from '../actions'
import {
setMode,
cancelEdit,
submitDocumentEdit,
addAnnotation,
removeAnnotation } from '../actions/userActions'
import {
updateEditorState,
handleEditorKeyCommand,
applyInlineStyles } from '../actions/editorStateActions'
import { updateDocumentTitleChange } from '../actions/inputActions'
const JoyceEditorContent = ({currentDocument, editorState, mode, handleKeyCommand, onChangeEditorState, onToolButtonClick, setMode, cancelEdit, onSubmitClick, documentTitleInput, onDocumentTitleChange, onNewAnnotationClick, annotateKeyBindings, onRemoveAnnotationClick, docType, loadingToggle}) =>
<div>

View File

@ -2,7 +2,7 @@ import React from 'react'
import { connect } from 'react-redux'
import { EditorState } from 'draft-js'
import { deleteCurrentDocument, submitAnnotation, selectAnnotationNote } from '../actions'
import { deleteCurrentDocument, submitAnnotation, selectAnnotationNote } from '../actions/userActions'
import Navbar from '../components/navbar'
import Content from '../components/content'
import DeleteConfirmModal from '../components/deleteConfirmModal'

View File

@ -1,6 +1,6 @@
import React from 'react'
import { connect } from 'react-redux'
import { setCurrentDocument, createNewDocument, setDocType } from '../actions'
import { setCurrentDocument, createNewDocument, setDocType } from '../actions/userActions'
import { DocumentList } from '../components/list'
import { NewDocumentButton } from '../components/button'
import { DocTypeDropdown } from '../components/dropdown'

View File

@ -2,7 +2,7 @@ import React from 'react'
import { connect } from 'react-redux'
import { Editor } from 'draft-js'
import { setCurrentChapter, setAnnotationNote, toggleLoading } from '../actions'
import { setCurrentChapter, setAnnotationNote, toggleLoading } from '../actions/userActions'
import DocumentTitle from '../components/documentTitle'
import LoadingSpinner from '../components/loadingSpinner'

View File

@ -1,6 +1,6 @@
import React from 'react'
import { connect } from 'react-redux'
import { setCurrentDocument, toggleHighlight } from '../actions'
import { setCurrentDocument, toggleHighlight } from '../actions/userActions'
import { DocumentList } from '../components/list'
import { HighlightButton } from '../components/button'
import SidebarSpacer from '../components/sidebarSpacer'
@ -8,7 +8,7 @@ import SidebarSpacer from '../components/sidebarSpacer'
const JoyceReaderSidebar = ({chapters, notes, currentDocument, onDocumentClick, highlightToggle, onHighlightClick, docType}) =>
<div className='col-md-3 d-none d-md-block' id='sidebar'>
<div>
<HighlightButton highlightToggle={highlightToggle} onHighlightClick={onHighlightClick}/>
<HighlightButton highlightToggle={highlightToggle} onClick={onHighlightClick}/>
<SidebarSpacer />
<DocumentList chapters={chapters} notes={notes} currentDocument={currentDocument} onDocumentClick={onDocumentClick} docType={docType} />
</div>

View File

@ -4,11 +4,12 @@ import { Editor } from 'draft-js'
import { SearchButton } from '../components/button'
import SearchResultsBox from '../components/searchResultsBox'
import { updateSearchInput, clickSearch } from '../actions'
import { clickSearch } from '../actions/userActions'
import { updateSearchInput } from '../actions/inputActions'
const JoyceSearchContent = ({searchResults, searchInput, onSearchInputChange, onSearchClick}) =>
<div id='joyce_search' className='container-fluid'>
<div id='search_content' className='row'>
<div id='content_window' className='row'>
<div className='container'>
<div className='row'>
<div className='col-sm-2'>

View File

@ -1,5 +1,5 @@
import React from 'react'
import { selectAnnotationNote } from '../actions'
import { selectAnnotationNote } from '../actions/userActions'
import { connect } from 'react-redux'
const Link = (props) => {

View File

@ -5,7 +5,8 @@ import { Provider } from 'react-redux'
import 'bootstrap'
import reduceEditor from './reducers/reduceEditor'
import { getDocumentList, setCurrentDocument, setDocType } from './actions'
import { getDocumentList } from './actions/apiActions'
import { setCurrentDocument, setDocType } from './actions/userActions'
import { joyceAPI, logger } from './middleware/'
import { getFirstDocument } from './mixins/firstDocument'
import JoyceEditorPageContainer from './containers/joyceEditorPageContainer'

View File

@ -8,10 +8,11 @@ import {
getDocumentText,
deleteDocument,
saveDocument,
setCurrentDocument,
createNewChapter,
getSearchResults
} from '../actions'
} from '../actions/apiActions'
import { setCurrentDocument } from '../actions/userActions'
import {
HTTPGetDocumentList,

View File

@ -5,7 +5,8 @@ import { Provider } from 'react-redux'
import 'bootstrap'
import reduceReader from './reducers/reduceReader'
import { getDocumentList, setCurrentDocument, setDocType } from './actions'
import { getDocumentList } from './actions/apiActions'
import { setCurrentDocument, setDocType } from './actions/userActions'
import { logger, joyceAPI } from './middleware/'
import { getFirstDocument } from './mixins/firstDocument'
import JoyceReaderPageContainer from './containers/joyceReaderPageContainer'

View File

@ -5,7 +5,8 @@ import { Provider } from 'react-redux'
import 'bootstrap'
import reduceReader from './reducers/reduceReader'
import { getDocumentList, setCurrentDocument, setDocType } from './actions'
import { getDocumentList } from './actions/apiActions'
import { setCurrentDocument, setDocType } from './actions/userActions'
import { logger, joyceAPI } from './middleware/'
import { getFirstDocument } from './mixins/firstDocument'
import JoyceReaderPageContainer from './containers/joyceReaderPageContainer'

View File

@ -2,58 +2,25 @@
#page {
height: 100%;
overflow: scroll;
overflow-y: scroll;
background-color: rgba(256,256,256,.8);
box-shadow: 2px 5px 10px 1px rgba(0, 0, 0, 0.3);
padding: 3% 8%;
border: 1px solid $border_color;
border-radius: 5px;
font-size: 0.8em;
}
#page.show_notes a {
cursor: pointer;
animation-duration: 1s;
animation-name: fadeIn;
animation-fill-mode: forwards;
}
#page.hide_notes a {
color: black;
text-decoration: none;
cursor: default;
pointer-events: none;
}
.annotations a {
cursor: pointer;
animation-duration: 1s;
animation-name: fadeIn;
animation-fill-mode: forwards;
}
.hidden_annotations a {
color: black;
text-decoration: none;
cursor: default;
pointer-events: none;
}
@keyframes fadeIn {
from {
font-size: 0.8em;
&.annotations a {
cursor: pointer;
animation-duration: 1s;
animation-name: fadeIn;
animation-fill-mode: both;
}
&.hidden_annotations a {
color: black;
text-decoration: none;
text-decoration: none;
cursor: default;
pointer-events: none;
}
to {
color: map-get($theme_colors, "primary");
background-color: #f2e9de;
border-radius: 3px;
}
}
#page {
h2 {
text-align: center;
}
@ -64,6 +31,17 @@
h4 {
text-align: center;
}
}
}
@keyframes fadeIn {
from {
color: black;
text-decoration: none;
}
to {
color: map-get($theme_colors, "primary");
background-color: #f2e9de;
border-radius: 3px;
}
}

View File

@ -60,7 +60,7 @@ button {
border-radius: 5px;
background-color: rgba(200, 200, 200, .8);
max-height: 38em;
overflow: scroll;
overflow-y: scroll;
}
#new_document_button > button {

View File

@ -1,34 +1,8 @@
@import "variables";
#chapter_title_input input {
width: 100%;
}
#editor_metadata input {
width: 100%;
margin-bottom: 0.5%;
}
#editor_metadata h4 {
font-size: 1.75rem
}
#editor_topbar button img {
width: 100%;
height: 100%;
}
#editor_topbar .row {
margin-bottom: 0.8%;
}
#editor_topbar .btn-group {
margin: 0 1%;
}
#editor_content {
height: 43em;
overflow: scroll;
overflow-y: scroll;
background-color: rgba(256,256,256,.8);
box-shadow: 2px 5px 10px 1px rgba(0, 0, 0, 0.3);
margin: 1.3% 0;
@ -38,22 +12,31 @@
font-size: 0.8em;
}
#editor_content div {
// overflow: scroll;
#editor_metadata {
h4 {
font-size: 1.75rem
}
input {
width: 100%;
margin-bottom: 0.5%;
}
}
#editor_topbar button img {
width: 60%;
#editor_topbar {
button {
width: 100%;
}
.row {
margin-bottom: 0.8%;
}
.btn-group {
margin: 0 1%;
}
}
#editor_bottombar {
margin: 0.8% 0;
}
#editor_topbar button {
width: 100%;
}
#editor_bottombar button {
width: 100%;
button {
width: 100%;
}
}

View File

@ -36,17 +36,6 @@ html body {
box-shadow: 2px 5px 10px 1px rgba(0, 0, 0, 0.3);
}
#search_content {
height: 44em;
overflow: hidden;
background-color: rgba(250,250,250,.8);
margin: 0 auto;
padding: 2% 2%;
border: 1px solid $border_color;
border-radius: 5px;
box-shadow: 2px 5px 10px 1px rgba(0, 0, 0, 0.3);
}
.fa_inline {
padding-left: 0.5rem;
}

View File

@ -1,13 +1,9 @@
const HtmlWebpackPlugin = require('html-webpack-plugin')
const CleanWebpackPlugin = require('clean-webpack-plugin')
// const HtmlWebpackPlugin = require('html-webpack-plugin')
const ManifestRevisionPlugin = require('manifest-revision-webpack-plugin')
const webpack = require('webpack')
const path = require('path')
const rootAssetPath = './src/'
let pathsToClean = [
'static/js'
]
module.exports = {
entry: {
@ -28,11 +24,6 @@ module.exports = {
rootAssetPath + 'stylesheets/' + 'search.scss'
]
},
// output: {
// publicPath: "/static/js/",
// filename: '[name].[hash].js',
// path: path.resolve(__dirname, 'static/js/')
// },
module : {
rules: [
{
@ -93,6 +84,5 @@ module.exports = {
'window.jQuery': 'jquery',
Popper: ['popper.js', 'default']
}),
new CleanWebpackPlugin(pathsToClean),
],
};

View File

@ -1,6 +1,11 @@
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const path = require('path')
const CleanWebpackPlugin = require('clean-webpack-plugin')
const pathsToClean = [
'static/js'
]
module.exports = merge(common, {
output: {
@ -8,14 +13,12 @@ module.exports = merge(common, {
filename: '[name].[hash].js',
path: path.resolve(__dirname, 'static/js/')
},
// devServer: {
// contentBase: '.',
// hot: true
// },
watch: true,
watchOptions: {
poll: true,
ignored: /node_modules/
},
// new webpack.optimize.UglifyJsPlugin(),
},
plugins: [
new CleanWebpackPlugin(pathsToClean),
]
});

View File

@ -1,21 +1,27 @@
const webpack = require('webpack');
const merge = require('webpack-merge');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin')
const common = require('./webpack.common.js');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const path = require('path')
const pathsToClean = [
'dist/js'
]
module.exports = merge(common, {
output: {
publicPath: "/dist/js/",
filename: '[name].js',
path: path.resolve(__dirname, 'dist/js/')
filename: '[name].js',
path: path.resolve(__dirname, 'dist/js/')
},
optimization: {
minimize: true
},
plugins: [
new UglifyJSPlugin(),
new CleanWebpackPlugin(pathsToClean),
new UglifyJSPlugin(),
new BundleAnalyzerPlugin,
new webpack.LoaderOptionsPlugin({
minimize: true,