mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-28 23:13:45 -05:00
Merge pull request #1440 from overleaf/as-amd-webpack
Bundle all frontend code with webpack GitOrigin-RevId: 1bd93dad516c456fe1649193868e841e20459b0b
This commit is contained in:
parent
e27577bd5b
commit
9cf73f965c
59 changed files with 1466 additions and 1520 deletions
|
@ -3,4 +3,3 @@ modules/**/scripts
|
|||
public/js
|
||||
public/minjs
|
||||
modules/**/public/js
|
||||
test/unit_frontend/js
|
||||
|
|
21
services/web/.gitignore
vendored
21
services/web/.gitignore
vendored
|
@ -42,31 +42,14 @@ TpdsWorker.js
|
|||
BackgroundJobsWorker.js
|
||||
UserAndProjectPopulator.coffee
|
||||
|
||||
public/es/modules
|
||||
|
||||
public/js/*.js
|
||||
public/js/*.map
|
||||
public/js/analytics/
|
||||
public/js/directives/
|
||||
public/js/components/
|
||||
public/js/es/
|
||||
public/js/filters/
|
||||
public/js/ide/
|
||||
public/js/main/
|
||||
public/js/modules/
|
||||
public/js/services/
|
||||
public/js/utils/
|
||||
public/js/manifest.json
|
||||
public/minjs/
|
||||
|
||||
public/stylesheets/style*.css
|
||||
public/stylesheets/sl-style*.css
|
||||
public/stylesheets/light-style*.css
|
||||
public/stylesheets/ieee-style*.css
|
||||
public/stylesheets/*.map
|
||||
public/minjs/
|
||||
|
||||
public/js/libs/require*.js
|
||||
|
||||
test/unit_frontend/js/
|
||||
|
||||
Gemfile.lock
|
||||
|
||||
|
|
|
@ -3,4 +3,3 @@ modules/**/scripts
|
|||
public/js
|
||||
public/minjs
|
||||
modules/**/public/js
|
||||
test/unit_frontend/js
|
||||
|
|
3
services/web/.vscode/settings.json
vendored
3
services/web/.vscode/settings.json
vendored
|
@ -1,8 +1,5 @@
|
|||
{
|
||||
"files.exclude": {
|
||||
"app/js": true,
|
||||
"public/js": true,
|
||||
"test/unit_frontend/js": true,
|
||||
"node_modules": true,
|
||||
"data": true
|
||||
}
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
/* eslint-disable
|
||||
max-len,
|
||||
no-unused-vars,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
// Fix any style issues and re-enable lint.
|
||||
/*
|
||||
* decaffeinate suggestions:
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
const fs = require('fs')
|
||||
const PackageVersions = require('./app/src/infrastructure/PackageVersions')
|
||||
const Settings = require('settings-sharelatex')
|
||||
require('es6-promise').polyfill()
|
||||
|
||||
module.exports = function(grunt) {
|
||||
grunt.loadNpmTasks('grunt-contrib-requirejs')
|
||||
grunt.loadNpmTasks('grunt-file-append')
|
||||
|
||||
const config = {
|
||||
requirejs: {
|
||||
compile: {
|
||||
options: {
|
||||
optimize: 'uglify2',
|
||||
appDir: 'public/js',
|
||||
baseUrl: './',
|
||||
dir: 'public/minjs',
|
||||
inlineText: false,
|
||||
generateSourceMaps: true,
|
||||
preserveLicenseComments: false,
|
||||
paths: {
|
||||
moment: `libs/${PackageVersions.lib('moment')}`,
|
||||
mathjax: '/js/libs/mathjax/MathJax.js?config=TeX-AMS_HTML',
|
||||
'pdfjs-dist/build/pdf': `libs/${PackageVersions.lib('pdfjs')}/pdf`,
|
||||
ace: `${PackageVersions.lib('ace')}`,
|
||||
fineuploader: `libs/${PackageVersions.lib('fineuploader')}`,
|
||||
recurly: 'https://js.recurly.com/v4/recurly'
|
||||
},
|
||||
|
||||
skipDirOptimize: true,
|
||||
modules: [
|
||||
{
|
||||
name: 'main',
|
||||
exclude: ['libraries']
|
||||
},
|
||||
{
|
||||
name: 'ide',
|
||||
exclude: ['pdfjs-dist/build/pdf', 'libraries']
|
||||
},
|
||||
{
|
||||
name: 'libraries'
|
||||
},
|
||||
{
|
||||
name: 'ace/mode-latex'
|
||||
},
|
||||
{
|
||||
name: 'ace/worker-latex'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
file_append: {
|
||||
default_options: {
|
||||
files: [
|
||||
{
|
||||
append: '\n//ide.js is complete - used for automated testing',
|
||||
input: 'public/minjs/ide.js',
|
||||
output: 'public/minjs/ide.js'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
grunt.initConfig(config)
|
||||
return grunt.registerTask(
|
||||
'compile:minify',
|
||||
'Concat and minify the client side js',
|
||||
['requirejs', 'file_append']
|
||||
)
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
DOCKER_COMPOSE_FLAGS ?= -f docker-compose.yml --log-level ERROR
|
||||
|
||||
|
||||
BUILD_NUMBER ?= local
|
||||
BRANCH_NAME ?= $(shell git rev-parse --abbrev-ref HEAD)
|
||||
PROJECT_NAME = web
|
||||
|
@ -16,16 +15,9 @@ MODULE_DIRS := $(shell find modules -mindepth 1 -maxdepth 1 -type d -not -name '
|
|||
MODULE_MAKEFILES := $(MODULE_DIRS:=/Makefile)
|
||||
MODULE_NAME=$(shell basename $(MODULE))
|
||||
|
||||
BABEL := node_modules/.bin/babel
|
||||
GRUNT := node_modules/.bin/grunt
|
||||
LESSC := node_modules/.bin/lessc
|
||||
CLEANCSS := node_modules/.bin/cleancss
|
||||
|
||||
SRC_FILES := $(shell find public/src -name '*.js')
|
||||
DIST_FILES := $(subst src,js,$(SRC_FILES))
|
||||
MAIN_SRC_FILES := $(shell find modules -type f -wholename '*main/index.js')
|
||||
IDE_SRC_FILES := $(shell find modules -type f -wholename '*ide/index.js')
|
||||
|
||||
LESS_FILES := $(shell find public/stylesheets -name '*.less')
|
||||
LESSC_COMMON_FLAGS := --source-map --autoprefix="last 2 versions, ie >= 10"
|
||||
CLEANCSS_FLAGS := --s0 --source-map
|
||||
|
@ -41,45 +33,6 @@ CSS_OL_IEEE_FILE := public/stylesheets/ieee-style.css
|
|||
|
||||
CSS_FILES := $(CSS_SL_FILE) $(CSS_OL_FILE) $(CSS_OL_LIGHT_FILE) $(CSS_OL_IEEE_FILE)
|
||||
|
||||
# The automatic variable $(@D) is the target directory name
|
||||
public/js/%.js: public/src/%.js
|
||||
@mkdir -p $(@D)
|
||||
$(BABEL) $< --out-file $@
|
||||
|
||||
test/unit_frontend/js/%.js: test/unit_frontend/src/%.js
|
||||
@mkdir -p $(@D)
|
||||
$(BABEL) $< --out-file $@
|
||||
|
||||
public/js/ide.js: public/src/ide.js $(IDE_SRC_FILES)
|
||||
@echo Compiling and injecting module includes into public/js/ide.js
|
||||
@INCLUDES=""; \
|
||||
for dir in modules/*; \
|
||||
do \
|
||||
MODULE=`echo $$dir | cut -d/ -f2`; \
|
||||
if [ -e $$dir/public/src/ide/index.js ]; then \
|
||||
INCLUDES="\"ide/$$MODULE/index\",$$INCLUDES"; \
|
||||
fi \
|
||||
done; \
|
||||
INCLUDES=$${INCLUDES%?}; \
|
||||
$(BABEL) $< | \
|
||||
sed -e s=\'__IDE_CLIENTSIDE_INCLUDES__\'=$$INCLUDES= \
|
||||
> $@
|
||||
|
||||
public/js/main.js: public/src/main.js $(MAIN_SRC_FILES)
|
||||
@echo Compiling and injecting module includes into public/js/main.js
|
||||
@INCLUDES=""; \
|
||||
for dir in modules/*; \
|
||||
do \
|
||||
MODULE=`echo $$dir | cut -d/ -f2`; \
|
||||
if [ -e $$dir/public/src/main/index.js ]; then \
|
||||
INCLUDES="\"main/$$MODULE/index\",$$INCLUDES"; \
|
||||
fi \
|
||||
done; \
|
||||
INCLUDES=$${INCLUDES%?}; \
|
||||
$(BABEL) $< | \
|
||||
sed -e s=\'__MAIN_CLIENTSIDE_INCLUDES__\'=$$INCLUDES= \
|
||||
> $@
|
||||
|
||||
public/stylesheets/%.css: $(LESS_FILES)
|
||||
$(LESSC) $(LESSC_COMMON_FLAGS) $(@D)/$*.less $(@D)/$*.css
|
||||
|
||||
|
@ -87,58 +40,15 @@ css_full: $(CSS_FILES)
|
|||
|
||||
css: $(CSS_OL_FILE)
|
||||
|
||||
minify: $(CSS_FILES) $(DIST_FILES)
|
||||
$(GRUNT) compile:minify
|
||||
$(MAKE) minify_css
|
||||
$(MAKE) minify_es
|
||||
|
||||
minify_css: $(CSS_FILES)
|
||||
minify: $(CSS_FILES)
|
||||
$(CLEANCSS) $(CLEANCSS_FLAGS) -o $(CSS_SL_FILE) $(CSS_SL_FILE)
|
||||
$(CLEANCSS) $(CLEANCSS_FLAGS) -o $(CSS_OL_FILE) $(CSS_OL_FILE)
|
||||
$(CLEANCSS) $(CLEANCSS_FLAGS) -o $(CSS_OL_LIGHT_FILE) $(CSS_OL_LIGHT_FILE)
|
||||
$(CLEANCSS) $(CLEANCSS_FLAGS) -o $(CSS_OL_IEEE_FILE) $(CSS_OL_IEEE_FILE)
|
||||
|
||||
minify_es:
|
||||
npm -q run webpack:production
|
||||
compile: css
|
||||
|
||||
compile: $(DIST_FILES) css public/js/main.js public/js/ide.js
|
||||
@$(MAKE) compile_modules
|
||||
|
||||
compile_full:
|
||||
$(BABEL) public/src --out-dir public/js
|
||||
$(BABEL) test/unit_frontend/src --out-dir test/unit_frontend/js
|
||||
rm -f public/js/ide.js public/js/main.js # We need to generate ide.js, main.js, manually later
|
||||
$(MAKE) css_full
|
||||
$(MAKE) compile_modules_full
|
||||
$(MAKE) compile # ide.js, main.js, share.js, and anything missed
|
||||
|
||||
compile_css_full:
|
||||
$(MAKE) css_full
|
||||
|
||||
compile_modules: $(MODULE_MAKEFILES)
|
||||
@set -e; \
|
||||
for dir in $(MODULE_DIRS); \
|
||||
do \
|
||||
if [ -e $$dir/Makefile ]; then \
|
||||
(cd $$dir && $(MAKE) compile); \
|
||||
fi; \
|
||||
if [ ! -e $$dir/Makefile ]; then \
|
||||
echo "No makefile found in $$dir"; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
compile_modules_full: $(MODULE_MAKEFILES)
|
||||
@set -e; \
|
||||
for dir in $(MODULE_DIRS); \
|
||||
do \
|
||||
if [ -e $$dir/Makefile ]; then \
|
||||
echo "Compiling $$dir in full"; \
|
||||
(cd $$dir && $(MAKE) compile_full); \
|
||||
fi; \
|
||||
if [ ! -e $$dir/Makefile ]; then \
|
||||
echo "No makefile found in $$dir"; \
|
||||
fi; \
|
||||
done
|
||||
compile_full: css_full
|
||||
|
||||
$(MODULE_MAKEFILES): Makefile.module
|
||||
@set -e; \
|
||||
|
@ -147,18 +57,9 @@ $(MODULE_MAKEFILES): Makefile.module
|
|||
cp Makefile.module $$makefile; \
|
||||
done
|
||||
|
||||
clean: clean_frontend clean_css clean_tests
|
||||
|
||||
clean_frontend:
|
||||
rm -rf public/js/{analytics,directives,es,filters,ide,main,modules,services,utils}
|
||||
rm -f public/js/*.{js,map}
|
||||
|
||||
clean_css:
|
||||
clean:
|
||||
rm -f public/stylesheets/*.css*
|
||||
|
||||
clean_tests:
|
||||
rm -rf test/unit_frontend/js
|
||||
|
||||
clean_ci:
|
||||
$(DOCKER_COMPOSE) down -v -t 0
|
||||
docker container list | grep 'days ago' | cut -d ' ' -f 1 - | xargs -r docker container stop
|
||||
|
|
|
@ -1,16 +1,6 @@
|
|||
MODULE_NAME := $(notdir $(shell pwd))
|
||||
MODULE_DIR := modules/$(MODULE_NAME)
|
||||
PROJECT_NAME = web
|
||||
BABEL := ../../node_modules/.bin/babel
|
||||
|
||||
IDE_SRC_FILES := $(shell [ -e public/src/ide ] && find public/src/ide -name '*.js')
|
||||
IDE_DIST_FILES := $(subst public/src/ide,../../public/js/ide/$(MODULE_NAME),$(IDE_SRC_FILES))
|
||||
|
||||
IDE_TEST_SRC_FILES := $(shell [ -e test/unit_frontend/src/ide ] && find test/unit_frontend/src/ide -name '*.js')
|
||||
IDE_TEST_DIST_FILES := $(subst test/unit_frontend/src/ide,../../test/unit_frontend/js/ide/$(MODULE_NAME),$(IDE_TEST_SRC_FILES))
|
||||
|
||||
MAIN_SRC_FILES := $(shell [ -e public/src/main ] && find public/src/main -name '*.js')
|
||||
MAIN_DIST_FILES := $(subst public/src/main,../../public/js/main/$(MODULE_NAME),$(MAIN_SRC_FILES))
|
||||
|
||||
DOCKER_COMPOSE_FLAGS ?= -f docker-compose.yml
|
||||
DOCKER_COMPOSE_MODULE_FLAGS := ${DOCKER_COMPOSE_FLAGS} -f $(MODULE_DIR)/docker-compose.yml
|
||||
|
@ -22,26 +12,5 @@ DOCKER_COMPOSE := cd ../../ && \
|
|||
MOCHA_GREP=${MOCHA_GREP} \
|
||||
docker-compose ${DOCKER_COMPOSE_MODULE_FLAGS}
|
||||
|
||||
../../test/unit_frontend/js/ide/$(MODULE_NAME)/%.js: test/unit_frontend/src/ide/%.js
|
||||
@mkdir -p $(dir $@)
|
||||
$(BABEL) $< --out-file $@
|
||||
|
||||
../../public/js/ide/$(MODULE_NAME)/%.js: public/src/ide/%.js
|
||||
@mkdir -p $(dir $@)
|
||||
$(BABEL) $< --out-file $@
|
||||
|
||||
../../public/js/main/$(MODULE_NAME)/%.js: public/src/main/%.js
|
||||
@mkdir -p $(dir $@)
|
||||
$(BABEL) $< --out-file $@
|
||||
|
||||
compile: $(IDE_DIST_FILES) $(MAIN_DIST_FILES) $(IDE_TEST_DIST_FILES)
|
||||
@echo > /dev/null
|
||||
|
||||
compile_full:
|
||||
if [ -e public/src/ide ]; then $(BABEL) public/src/ide --out-dir ../../public/js/ide/$(MODULE_NAME); fi
|
||||
if [ -e public/src/main ]; then $(BABEL) public/src/main --out-dir ../../public/js/main/$(MODULE_NAME); fi
|
||||
if [ -e test/unit_frontend/src/ide ]; then $(BABEL) test/unit_frontend/src/ide --out-dir ../../test/unit_frontend/js/ide/$(MODULE_NAME); fi
|
||||
@$(MAKE) compile # Anything else missed
|
||||
|
||||
test_acceptance:
|
||||
${DOCKER_COMPOSE} run --rm test_acceptance npm -q run test:acceptance:run_dir -- ${MOCHA_ARGS} $(MODULE_DIR)/test/acceptance/src
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
let path
|
||||
const logger = require('logger-sharelatex')
|
||||
const fs = require('fs')
|
||||
const crypto = require('crypto')
|
||||
|
@ -39,12 +38,34 @@ const Features = require('./Features')
|
|||
Modules = require('./Modules')
|
||||
const moment = require('moment')
|
||||
const lodash = require('lodash')
|
||||
const chokidar = require('chokidar')
|
||||
|
||||
const jsPath = Settings.useMinifiedJs ? '/minjs/' : '/js/'
|
||||
|
||||
const ace = PackageVersions.lib('ace')
|
||||
const pdfjs = PackageVersions.lib('pdfjs')
|
||||
const fineuploader = PackageVersions.lib('fineuploader')
|
||||
const webpackManifestPath = Path.join(
|
||||
__dirname,
|
||||
`../../../public${jsPath}manifest.json`
|
||||
)
|
||||
let webpackManifest
|
||||
if (['development', 'test'].includes(process.env.NODE_ENV)) {
|
||||
// In dev the web and webpack containers can race (and therefore the manifest
|
||||
// file may not be created when web is running), so watch the file for changes
|
||||
// and reload
|
||||
webpackManifest = {}
|
||||
const reloadManifest = () => {
|
||||
logger.log('[DEV] Reloading webpack manifest')
|
||||
webpackManifest = require(webpackManifestPath)
|
||||
}
|
||||
|
||||
logger.log('[DEV] Watching webpack manifest')
|
||||
chokidar
|
||||
.watch(webpackManifestPath)
|
||||
.on('add', reloadManifest)
|
||||
.on('change', reloadManifest)
|
||||
} else {
|
||||
logger.log('[PRODUCTION] Loading webpack manifest')
|
||||
webpackManifest = require(webpackManifestPath)
|
||||
}
|
||||
|
||||
const getFileContent = function(filePath) {
|
||||
filePath = Path.join(__dirname, '../../../', `public${filePath}`)
|
||||
|
@ -59,21 +80,17 @@ const getFileContent = function(filePath) {
|
|||
}
|
||||
|
||||
const pathList = [
|
||||
`${jsPath}libs/require.js`,
|
||||
`${jsPath}ide.js`,
|
||||
`${jsPath}main.js`,
|
||||
`${jsPath}libraries.js`,
|
||||
'/stylesheets/style.css',
|
||||
'/stylesheets/light-style.css',
|
||||
'/stylesheets/ieee-style.css',
|
||||
'/stylesheets/sl-style.css'
|
||||
].concat(Modules.moduleAssetFiles(jsPath))
|
||||
]
|
||||
|
||||
if (!Settings.useMinifiedJs) {
|
||||
logger.log('not using minified JS, not hashing static files')
|
||||
} else {
|
||||
logger.log('Generating file hashes...')
|
||||
for (path of Array.from(pathList)) {
|
||||
for (let path of Array.from(pathList)) {
|
||||
const content = getFileContent(path)
|
||||
const hash = crypto
|
||||
.createHash('md5')
|
||||
|
@ -171,56 +188,34 @@ module.exports = function(app, webRouter, privateApiRouter, publicApiRouter) {
|
|||
staticFilesBase = ''
|
||||
}
|
||||
|
||||
res.locals.jsPath = jsPath
|
||||
res.locals.fullJsPath = Url.resolve(staticFilesBase, jsPath)
|
||||
res.locals.lib = PackageVersions.lib
|
||||
|
||||
res.locals.moment = moment
|
||||
|
||||
res.locals.buildJsPath = function(jsFile, opts) {
|
||||
if (opts == null) {
|
||||
opts = {}
|
||||
}
|
||||
path = Path.join(jsPath, jsFile)
|
||||
|
||||
if (opts.hashedPath && hashedFiles[path] != null) {
|
||||
path = hashedFiles[path]
|
||||
}
|
||||
|
||||
if (opts.qs == null) {
|
||||
opts.qs = {}
|
||||
res.locals.buildJsPath = function(jsFile, opts = {}) {
|
||||
// Resolve path from webpack manifest file
|
||||
let path = webpackManifest[jsFile]
|
||||
// If not found in manifest, it is directly linked, so fallback to
|
||||
// relevant public directory
|
||||
if (!path) {
|
||||
path = Path.join(jsPath, jsFile)
|
||||
}
|
||||
|
||||
if (opts.cdn !== false) {
|
||||
path = Url.resolve(staticFilesBase, path)
|
||||
}
|
||||
|
||||
const qs = querystring.stringify(opts.qs)
|
||||
|
||||
if (opts.removeExtension === true) {
|
||||
path = path.slice(0, -3)
|
||||
if (opts.qs) {
|
||||
path = path + '?' + querystring.stringify(opts.qs)
|
||||
}
|
||||
|
||||
if (qs != null && qs.length > 0) {
|
||||
path = path + '?' + qs
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
res.locals.buildWebpackPath = function(jsFile, opts) {
|
||||
if (opts == null) {
|
||||
opts = {}
|
||||
}
|
||||
if (Settings.webpack != null && !Settings.useMinifiedJs) {
|
||||
path = Path.join(jsPath, jsFile)
|
||||
if (opts.removeExtension === true) {
|
||||
path = path.slice(0, -3)
|
||||
}
|
||||
return `${Settings.webpack.url}/public${path}`
|
||||
} else {
|
||||
return res.locals.buildJsPath(jsFile, opts)
|
||||
}
|
||||
}
|
||||
res.locals.mathJaxPath = res.locals.buildJsPath('libs/mathjax/MathJax.js', {
|
||||
cdn: false,
|
||||
qs: { config: 'TeX-AMS_HTML,Safe' }
|
||||
})
|
||||
|
||||
const IEEE_BRAND_ID = 15
|
||||
res.locals.isIEEE = brandVariation =>
|
||||
|
@ -249,7 +244,7 @@ module.exports = function(app, webRouter, privateApiRouter, publicApiRouter) {
|
|||
|
||||
res.locals.buildCssPath = function(themeModifier, buildOpts) {
|
||||
const cssFileName = _buildCssFileName(themeModifier)
|
||||
path = Path.join('/stylesheets/', cssFileName)
|
||||
const path = Path.join('/stylesheets/', cssFileName)
|
||||
if (
|
||||
(buildOpts != null ? buildOpts.hashedPath : undefined) &&
|
||||
hashedFiles[path] != null
|
||||
|
@ -261,15 +256,10 @@ module.exports = function(app, webRouter, privateApiRouter, publicApiRouter) {
|
|||
}
|
||||
|
||||
res.locals.buildImgPath = function(imgFile) {
|
||||
path = Path.join('/img/', imgFile)
|
||||
const path = Path.join('/img/', imgFile)
|
||||
return Url.resolve(staticFilesBase, path)
|
||||
}
|
||||
|
||||
res.locals.mathJaxPath = res.locals.buildJsPath('libs/mathjax/MathJax.js', {
|
||||
cdn: false,
|
||||
qs: { config: 'TeX-AMS_HTML,Safe' }
|
||||
})
|
||||
|
||||
return next()
|
||||
})
|
||||
|
||||
|
@ -421,10 +411,6 @@ module.exports = function(app, webRouter, privateApiRouter, publicApiRouter) {
|
|||
}
|
||||
res.locals.gaToken = Settings.analytics && Settings.analytics.ga.token
|
||||
res.locals.tenderUrl = Settings.tenderUrl
|
||||
res.locals.sentrySrc =
|
||||
Settings.sentry != null ? Settings.sentry.src : undefined
|
||||
res.locals.sentryPublicDSN =
|
||||
Settings.sentry != null ? Settings.sentry.publicDSN : undefined
|
||||
return next()
|
||||
})
|
||||
|
||||
|
|
|
@ -114,16 +114,6 @@ module.exports = Modules = {
|
|||
return (Modules.viewIncludes[view] || []).length > 0
|
||||
},
|
||||
|
||||
moduleAssetFiles(pathPrefix) {
|
||||
const assetFiles = []
|
||||
for (let module of Array.from(this.modules)) {
|
||||
for (let assetFile of Array.from(module.assetFiles || [])) {
|
||||
assetFiles.push(`${pathPrefix}${assetFile}`)
|
||||
}
|
||||
}
|
||||
return assetFiles
|
||||
},
|
||||
|
||||
linkedFileAgentsIncludes() {
|
||||
const agents = {}
|
||||
for (let module of Array.from(this.modules)) {
|
||||
|
|
|
@ -9,7 +9,10 @@ const version = {
|
|||
pdfjs: '2.0.943',
|
||||
moment: '2.9.0',
|
||||
ace: '1.4.5', // Upgrade instructions: https://github.com/overleaf/write_latex/wiki/Upgrading-Ace
|
||||
fineuploader: '5.15.4'
|
||||
fineuploader: '5.15.4',
|
||||
// For frontend. Backend has a different version defined in package.json
|
||||
underscore: '1.9.1',
|
||||
algolia: '2.5.2'
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
|
|
@ -53,7 +53,7 @@ html(
|
|||
window.location.search += '&'+noCdnKey;
|
||||
}
|
||||
|
||||
block scripts
|
||||
block head-scripts
|
||||
|
||||
script(src=buildJsPath("libs/angular-1.6.4.min.js"))
|
||||
|
||||
|
@ -61,7 +61,6 @@ html(
|
|||
window.sharelatex = {
|
||||
siteUrl: '#{settings.siteUrl}',
|
||||
wsUrl: '#{settings.wsUrl}',
|
||||
jsPath: '#{jsPath}',
|
||||
};
|
||||
window.systemMessages = !{StringHelper.stringifyJsonForScript(systemMessages)};
|
||||
window.ab = {};
|
||||
|
@ -116,33 +115,9 @@ html(
|
|||
span(ng-controller="ScribtexPopupController")
|
||||
include scribtex-modal
|
||||
|
||||
block requirejs
|
||||
block requirejs-config
|
||||
script(type='text/javascript').
|
||||
// minimal requirejs configuration (can be extended/overridden)
|
||||
window.requirejs = {
|
||||
"paths" : {
|
||||
"moment": "libs/#{lib('moment')}",
|
||||
"fineuploader": "libs/#{lib('fineuploader')}",
|
||||
"main": "#{buildJsPath('main.js', {hashedPath:settings.useMinifiedJs, removeExtension:true})}",
|
||||
"libraries": "#{buildJsPath('libraries.js', {hashedPath:settings.useMinifiedJs, removeExtension:true})}"
|
||||
},
|
||||
"config":{
|
||||
"moment":{
|
||||
"noGlobal": true
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
block requirejs-init
|
||||
script(
|
||||
data-main=buildJsPath('main.js', {hashedPath:false}),
|
||||
baseurl=fullJsPath,
|
||||
src=buildJsPath('libs/require.js', {hashedPath:true})
|
||||
)
|
||||
|
||||
!= moduleIncludes("contactModal", locals)
|
||||
include v1-tooltip
|
||||
include sentry
|
||||
|
||||
|
||||
block foot-scripts
|
||||
script(src=buildJsPath('libraries.js'))
|
||||
script(src=buildJsPath('main.js'))
|
||||
|
|
|
@ -113,16 +113,6 @@ block content
|
|||
h3 {{ title }}
|
||||
.modal-body(ng-bind-html="message")
|
||||
|
||||
script(src=mathJaxPath)
|
||||
|
||||
block requirejs
|
||||
script(type="text/javascript" src='/socket.io/socket.io.js')
|
||||
|
||||
//- don't use cdn for workers
|
||||
- var aceWorkerPath = buildJsPath(lib('ace'), {cdn:false})
|
||||
- var pdfWorkerPath = buildJsPath('/libs/' + lib('pdfjs') + '/pdf.worker', {cdn:false})
|
||||
- var pdfCMapsPath = buildJsPath('/libs/' + lib('pdfjs') + '/bcmaps/', {cdn:false})
|
||||
|
||||
//- We need to do .replace(/\//g, '\\/') do that '</script>' -> '<\/script>'
|
||||
//- and doesn't prematurely end the script tag.
|
||||
script#data(type="application/json").
|
||||
|
@ -146,44 +136,10 @@ block requirejs
|
|||
window.trackChangesState = data.trackChangesState;
|
||||
window.wikiEnabled = #{!!(settings.apis.wiki && settings.apis.wiki.url)};
|
||||
window.gitBridgePublicBaseUrl = '#{gitBridgePublicBaseUrl}'
|
||||
window.requirejs = {
|
||||
"paths" : {
|
||||
"moment": "libs/#{lib('moment')}",
|
||||
"pdfjs-dist/build/pdf": "libs/#{lib('pdfjs')}/pdf",
|
||||
"pdfjs-dist/build/pdf.worker": "#{pdfWorkerPath}",
|
||||
"ace": "#{lib('ace')}",
|
||||
"fineuploader": "libs/#{lib('fineuploader')}",
|
||||
"ide": "#{buildJsPath('ide.js', {hashedPath:settings.useMinifiedJs, removeExtension:true})}",
|
||||
"libraries": "#{buildJsPath('libraries.js', {hashedPath:settings.useMinifiedJs, removeExtension:true})}",
|
||||
!{moduleIncludes("editor:script", locals)}
|
||||
!{moduleIncludes("publish:script", locals)}
|
||||
},
|
||||
"waitSeconds": 0,
|
||||
"shim": {
|
||||
"ace/ext-searchbox": {
|
||||
"deps": ["ace/ace"]
|
||||
},
|
||||
"ace/ext-modelist": {
|
||||
"deps": ["ace/ace"]
|
||||
},
|
||||
"ace/ext-language_tools": {
|
||||
"deps": ["ace/ace"]
|
||||
},
|
||||
"ace/keybinding-vim": {
|
||||
"deps": ["ace/ace"]
|
||||
},
|
||||
"libs/jquery.ui.touch-punch": {
|
||||
"deps": [ "libs/#{lib('jquery-layout')}" ]
|
||||
}
|
||||
},
|
||||
"config":{
|
||||
"moment":{
|
||||
"noGlobal": true
|
||||
}
|
||||
}
|
||||
};
|
||||
window.aceWorkerPath = "#{aceWorkerPath}";
|
||||
window.pdfCMapsPath = "#{pdfCMapsPath}"
|
||||
//- Set base path for Ace scripts loaded on demand/workers and don't use cdn
|
||||
window.aceBasePath = "#{buildJsPath(lib('ace'), {cdn:false})}"
|
||||
//- Set path for PDFjs CMaps
|
||||
window.pdfCMapsPath = "#{buildJsPath('cmaps/')}"
|
||||
window.uiConfig = JSON.parse('!{StringHelper.stringifyJsonForScript(uiConfig)}');
|
||||
//- enable doc hash checking for all projects
|
||||
//- used in public/js/libs/sharejs.js
|
||||
|
@ -193,9 +149,8 @@ block requirejs
|
|||
script(type='text/javascript').
|
||||
window.overallThemes = JSON.parse('!{StringHelper.stringifyJsonForScript(overallThemes)}');
|
||||
|
||||
script(
|
||||
data-main=buildJsPath("ide.js", {hashedPath:false}),
|
||||
baseurl=fullJsPath,
|
||||
data-ace-base=buildJsPath(lib('ace')),
|
||||
src=buildJsPath('libs/require.js', {hashedPath:true})
|
||||
)
|
||||
block foot-scripts
|
||||
script(type="text/javascript" src='/socket.io/socket.io.js')
|
||||
script(src=mathJaxPath)
|
||||
script(src=buildJsPath('libraries.js'))
|
||||
script(src=buildJsPath('ide.js'))
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
extends ../layout
|
||||
|
||||
block scripts
|
||||
block head-scripts
|
||||
script(type='text/javascript').
|
||||
$(document).ready(function () {
|
||||
$.ajax({dataType: "script", cache: true, url: "//connect.facebook.net/en_US/all.js"}).done(function () {
|
||||
|
|
|
@ -1,88 +0,0 @@
|
|||
- if (typeof(sentryPublicDSN) != "undefined")
|
||||
script(type="text/javascript").
|
||||
require.config({
|
||||
paths: {
|
||||
'raven': 'libs/raven-3.27.0.min'
|
||||
}
|
||||
});
|
||||
|
||||
require(["raven"], function(Raven) {
|
||||
if (typeof(Raven) != "undefined" && Raven.config) {
|
||||
Raven.config("#{sentryPublicDSN}", {
|
||||
tags: { 'commit': '@@COMMIT@@', 'build': '@@RELEASE@@' },
|
||||
release: '@@RELEASE@@',
|
||||
// Ignore list based off: https://gist.github.com/1878283
|
||||
ignoreErrors: [
|
||||
'DealPly',
|
||||
// Random plugins/extensions
|
||||
'top.GLOBALS',
|
||||
// See: http://blog.errorception.com/2012/03/tale-of-unfindable-js-error.html
|
||||
'originalCreateNotification',
|
||||
'canvas.contentDocument',
|
||||
'MyApp_RemoveAllHighlights',
|
||||
'http://tt.epicplay.com',
|
||||
'Can\'t find variable: ZiteReader',
|
||||
'jigsaw is not defined',
|
||||
'ComboSearch is not defined',
|
||||
'http://loading.retry.widdit.com/',
|
||||
'atomicFindClose',
|
||||
// Facebook borked
|
||||
'fb_xd_fragment',
|
||||
// ISP optimizing proxy - `Cache-Control: no-transform` seems to reduce this. (thanks @acdha)
|
||||
// See http://stackoverflow.com/questions/4113268/how-to-stop-javascript-injection-from-vodafone-proxy
|
||||
'bmi_SafeAddOnload',
|
||||
'EBCallBackMessageReceived',
|
||||
// See http://toolbar.conduit.com/Developer/HtmlAndGadget/Methods/JSInjection.aspx
|
||||
'conduitPage',
|
||||
'/NS_ERROR_NOT_CONNECTED/i',
|
||||
"/Cannot read property 'row' of undefined/i",
|
||||
'TypeError: start is undefined'
|
||||
],
|
||||
ignoreUrls: [
|
||||
// Facebook flakiness
|
||||
/graph\.facebook\.com/i,
|
||||
// Facebook blocked
|
||||
/connect\.facebook\.net\/en_US\/all\.js/i,
|
||||
// Woopra flakiness
|
||||
/eatdifferent\.com\.woopra-ns\.com/i,
|
||||
/static\.woopra\.com\/js\/woopra\.js/i,
|
||||
// Chrome extensions
|
||||
/extensions\//i,
|
||||
/^chrome:\/\//i,
|
||||
// Other plugins
|
||||
/127\.0\.0\.1:4001\/isrunning/i, // Cacaoweb
|
||||
/webappstoolbarba\.texthelp\.com\//i,
|
||||
/metrics\.itunes\.apple\.com\.edgesuite\.net\//i,
|
||||
/a\.disquscdn\.com/i,
|
||||
/platform\.twitter\.com/i,
|
||||
/pstatic\.datafastguru\.info/i
|
||||
],
|
||||
shouldSendCallback: function(data) {
|
||||
// only send a fraction of errors
|
||||
var sampleRate = 0.01;
|
||||
return (Math.random() <= sampleRate);
|
||||
},
|
||||
dataCallback: function(data) {
|
||||
// remove circular references from object
|
||||
var cache = [];
|
||||
var s = JSON.stringify(data, function(k, v) { if (typeof v === 'object' && v !== null) { if (cache.indexOf(v) !== -1) return "[circular]"; cache.push(v); }; return v; });
|
||||
return JSON.parse(s);
|
||||
}
|
||||
// we highly recommend restricting exceptions to a domain in order to filter out clutter
|
||||
// whitelistUrls: ['example.com/scripts/']
|
||||
}).install();
|
||||
//- We conditionally depend on Raven (based on whether the sentry
|
||||
//- config is set or not). This does not play well with require.js when
|
||||
//- minifying as it is expecting all dependencies to be defined at
|
||||
//- compile time. Previously Raven added itself as a global, so we just
|
||||
//- mimic that old behaviour
|
||||
window.Raven = Raven
|
||||
}
|
||||
}, function(err) {
|
||||
console.log(">> error loading raven", err);
|
||||
})
|
||||
- if (user && typeof(user) != "undefined" && typeof (user.email) != "undefined")
|
||||
script(type="text/javascript").
|
||||
if (typeof(Raven) != "undefined" && Raven.setUserContext) {
|
||||
Raven.setUserContext({email: '#{user.email}'});
|
||||
}
|
|
@ -2,7 +2,7 @@ extends ../layout
|
|||
|
||||
include ./dashboard/_team_name_mixin
|
||||
|
||||
block scripts
|
||||
block head-scripts
|
||||
script(src="https://js.recurly.com/v4/recurly.js")
|
||||
|
||||
block content
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
extends ../layout
|
||||
|
||||
block scripts
|
||||
block head-scripts
|
||||
script(src="https://js.recurly.com/v4/recurly.js")
|
||||
script(type='text/javascript').
|
||||
window.countryCode = '#{countryCode}'
|
||||
|
|
|
@ -6,7 +6,7 @@ include _plans_page_tables
|
|||
block vars
|
||||
- metadata = { viewport: true }
|
||||
|
||||
block scripts
|
||||
block head-scripts
|
||||
script(type='text/javascript').
|
||||
window.recomendedCurrency = '#{recomendedCurrency}';
|
||||
window.abCurrencyFlag = '#{abCurrencyFlag}';
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
extends ../../layout
|
||||
|
||||
block scripts
|
||||
block head-scripts
|
||||
script(type='text/javascript').
|
||||
window.teamId = '#{teamId}'
|
||||
window.hasIndividualRecurlySubscription = #{hasIndividualRecurlySubscription}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
extends ../layout
|
||||
|
||||
|
||||
block scripts
|
||||
block head-scripts
|
||||
script(type='text/javascript').
|
||||
window.otherSessions = !{StringHelper.stringifyJsonForScript(sessions)}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
block scripts
|
||||
block head-scripts
|
||||
script(type='text/javascript').
|
||||
window.oauthProviders = !{StringHelper.stringifyJsonForScript(oauthProviders)}
|
||||
window.thirdPartyIds = !{StringHelper.stringifyJsonForScript(thirdPartyIds)}
|
||||
|
|
0
services/web/config/.gitignore
vendored
0
services/web/config/.gitignore
vendored
|
@ -506,7 +506,7 @@ module.exports = settings =
|
|||
redirects:
|
||||
"/templates/index": "/templates/"
|
||||
|
||||
reloadModuleViewsOnEachRequest: process.env['NODE_ENV'] != 'production'
|
||||
reloadModuleViewsOnEachRequest: ['development', 'test'].includes(process.env['NODE_ENV'])
|
||||
|
||||
domainLicences: [
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ services:
|
|||
ENABLED_LINKED_FILE_TYPES: 'url,project_file,project_output_file,mendeley,zotero'
|
||||
LINKED_URL_PROXY: 'http://localhost:6543'
|
||||
SHARELATEX_CONFIG: /app/test/acceptance/config/settings.test.coffee
|
||||
NODE_ENV: production
|
||||
NODE_ENV: test
|
||||
user: root
|
||||
depends_on:
|
||||
- redis
|
||||
|
|
|
@ -29,7 +29,7 @@ services:
|
|||
ENABLED_LINKED_FILE_TYPES: 'url,project_file,project_output_file,mendeley,zotero'
|
||||
SHARELATEX_CONFIG: /app/test/acceptance/config/settings.test.coffee
|
||||
MOCHA_GREP: ${MOCHA_GREP}
|
||||
NODE_ENV: production
|
||||
NODE_ENV: test
|
||||
depends_on:
|
||||
- redis
|
||||
- mongo
|
||||
|
@ -42,7 +42,7 @@ services:
|
|||
volumes:
|
||||
- .:/app
|
||||
working_dir: /app
|
||||
command: npm run test:frontend -- --single-run
|
||||
command: npm run test:frontend:single
|
||||
|
||||
redis:
|
||||
image: redis
|
||||
|
|
|
@ -3,14 +3,19 @@
|
|||
make --no-print-directory format & FORMAT=$!
|
||||
make --no-print-directory lint & LINT=$!
|
||||
npm install git+https://github.com/sharelatex/translations-sharelatex.git#master & TRANSLATIONS=$!
|
||||
WEBPACK_ENV=production make minify & MINIFY=$!
|
||||
|
||||
# CSS
|
||||
make minify & MINIFY=$!
|
||||
# JS
|
||||
npm run webpack:production & WEBPACK=$!
|
||||
|
||||
echo "Waiting for lint, format, translations and minify to finish"
|
||||
|
||||
wait $LINT && echo "Lint complete" || exit 1
|
||||
wait $FORMAT && echo "Format complete" || exit 1
|
||||
wait $TRANSLATIONS && echo "Translations install complete" || exit 1
|
||||
wait $MINIFY && echo "Minifiy complete" || exit 1
|
||||
wait $MINIFY && echo "Minify complete" || exit 1
|
||||
wait $WEBPACK && echo "Webpack complete" || exit 1
|
||||
|
||||
chmod -R 0755 /app/public
|
||||
chown -R node:node /app/public
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const path = require('path')
|
||||
const webpackConfig = require('./webpack.config.test')
|
||||
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
|
@ -13,64 +13,29 @@ module.exports = function(config) {
|
|||
},
|
||||
browsers: ['ChromeCustom'],
|
||||
files: [
|
||||
'test/unit_frontend/es/es-bootstrap.js',
|
||||
// Angular must be loaded before requirejs to set up angular global
|
||||
'test/unit_frontend/bootstrap.js',
|
||||
// Include scripts that are injected into the page outside of webpack
|
||||
'public/js/libs/angular-1.6.4.min.js',
|
||||
'public/js/libs/angular-mocks.js',
|
||||
'public/js/libs/jquery-1.11.1.min.js',
|
||||
'public/js/libs/underscore-1.3.3.js',
|
||||
// Set up requirejs
|
||||
'test/unit_frontend/js/test-main.js',
|
||||
// Include source & test files, but don't "include" them as requirejs
|
||||
// handles this for us
|
||||
{ pattern: 'public/js/**/*.js', included: false },
|
||||
{ pattern: 'test/unit_frontend/js/**/*.js', included: false },
|
||||
// Include ES test files
|
||||
'test/unit_frontend/es/**/*.js',
|
||||
'modules/**/test/unit_frontend/es/**/*.js',
|
||||
|
||||
// Allow mocking of angular
|
||||
'public/js/libs/angular-mocks.js',
|
||||
|
||||
// Import all tests (see comment in the file for why this is necessary)
|
||||
'test/unit_frontend/import_tests.js',
|
||||
|
||||
// Include CSS (there is some in js/libs dir)
|
||||
'public/stylesheets/**/*.css',
|
||||
'public/js/libs/**/*.css'
|
||||
],
|
||||
middleware: ['fake-img'],
|
||||
preprocessors: {
|
||||
// Run ES test files through webpack (which will then include source
|
||||
// files in bundle)
|
||||
'test/unit_frontend/es/**/*.js': ['webpack'],
|
||||
'modules/**/test/unit_frontend/es/**/*.js': ['webpack']
|
||||
// Run files through webpack
|
||||
'test/unit_frontend/import_tests.js': ['webpack']
|
||||
},
|
||||
frameworks: ['requirejs', 'mocha', 'chai-sinon'],
|
||||
frameworks: ['mocha', 'chai-sinon'],
|
||||
// Configure webpack in the tests
|
||||
webpack: {
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
// Pass application JS files through babel-loader, compiling to ES5
|
||||
test: /\.js$/,
|
||||
// Only compile application files (dependencies are in ES5 already)
|
||||
exclude: /node_modules/,
|
||||
use: [
|
||||
{
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
// Configure babel-loader to cache compiled output so that
|
||||
// subsequent compile runs are much faster
|
||||
cacheDirectory: true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
resolve: {
|
||||
// Alias common directories in import pathnames to cut down on the
|
||||
// amount of ../../ etc
|
||||
alias: {
|
||||
Src: path.join(__dirname, 'public/es/'),
|
||||
Modules: path.join(__dirname, 'modules')
|
||||
}
|
||||
}
|
||||
},
|
||||
webpack: webpackConfig,
|
||||
// Configure the webpack dev server used to serve test files
|
||||
webpackMiddleware: {
|
||||
// Disable noisy CLI output
|
||||
|
@ -78,7 +43,6 @@ module.exports = function(config) {
|
|||
},
|
||||
plugins: [
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-requirejs'),
|
||||
require('karma-mocha'),
|
||||
require('karma-chai-sinon'),
|
||||
require('karma-webpack'),
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
// TODO: This file was created by bulk-decaffeinate.
|
||||
// Sanity-check the conversion and remove this comment.
|
||||
define(['main/launchpad/controllers/LaunchpadController'], function() {})
|
||||
define(['./controllers/LaunchpadController'], function() {})
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
{
|
||||
"exec": "make compile || exit 1",
|
||||
"watch": [
|
||||
"public/src/",
|
||||
"public/stylesheets/",
|
||||
"modules/**/public/src/"
|
||||
"public/stylesheets/"
|
||||
],
|
||||
"ext": "js less"
|
||||
"ext": "less"
|
||||
}
|
1826
services/web/package-lock.json
generated
1826
services/web/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -17,6 +17,7 @@
|
|||
"test:unit:ci": "bin/unit_test --timeout 10000",
|
||||
"test:unit:app": "bin/unit_test_app $@",
|
||||
"test:frontend": "karma start",
|
||||
"test:frontend:single": "karma start --single-run",
|
||||
"compile": "make compile",
|
||||
"start": "npm -q run compile && node $NODE_APP_OPTIONS app.js",
|
||||
"nodemon": "nodemon --config nodemon.json",
|
||||
|
@ -48,6 +49,7 @@
|
|||
"contentful": "^6.1.1",
|
||||
"cookie": "^0.2.3",
|
||||
"cookie-parser": "1.3.5",
|
||||
"crypto-js": "^3.1.9-1",
|
||||
"csurf": "^1.8.3",
|
||||
"d3": "^3.5.16",
|
||||
"dateformat": "1.0.4-1.2.3",
|
||||
|
@ -98,6 +100,7 @@
|
|||
"passport-orcid": "0.0.3",
|
||||
"passport-saml": "^1.1.0",
|
||||
"passport-twitter": "^1.0.4",
|
||||
"pdfjs-dist": "^2.0.943",
|
||||
"pug": "^2.0.0-beta6",
|
||||
"react": "^15.4.2",
|
||||
"react-dom": "^15.4.2",
|
||||
|
@ -129,7 +132,10 @@
|
|||
"chai-as-promised": "^7.1.1",
|
||||
"chaid": "^1.0.2",
|
||||
"cheerio": "^1.0.0-rc.3",
|
||||
"chokidar": "^3.1.1",
|
||||
"clean-css-cli": "^4.2.1",
|
||||
"copy-webpack-plugin": "^5.0.4",
|
||||
"dom-testing-library": "^3.19.4",
|
||||
"es6-promise": "^4.0.5",
|
||||
"eslint": "^4.18.1",
|
||||
"eslint-config-prettier": "^3.1.0",
|
||||
|
@ -145,11 +151,8 @@
|
|||
"eslint-plugin-promise": "^3.6.0",
|
||||
"eslint-plugin-react": "^7.11.1",
|
||||
"eslint-plugin-standard": "^3.0.1",
|
||||
"expose-loader": "^0.7.5",
|
||||
"glob": "^7.1.3",
|
||||
"grunt": "0.4.5",
|
||||
"grunt-cli": "^1.2.0",
|
||||
"grunt-contrib-requirejs": "0.4.1",
|
||||
"grunt-file-append": "0.0.6",
|
||||
"handlebars-loader": "^1.7.0",
|
||||
"karma": "^2.0.0",
|
||||
"karma-chai-sinon": "^0.1.5",
|
||||
|
@ -172,9 +175,11 @@
|
|||
"sinon-mongoose": "^2.3.0",
|
||||
"timekeeper": "^2.2.0",
|
||||
"translations-sharelatex": "git+https://github.com/sharelatex/translations-sharelatex.git#master",
|
||||
"val-loader": "^1.1.1",
|
||||
"webpack": "^4.39.0",
|
||||
"webpack-cli": "^3.3.6",
|
||||
"webpack-dev-server": "^3.7.2",
|
||||
"webpack-manifest-plugin": "^2.0.4",
|
||||
"webpack-merge": "^4.2.1"
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -329,4 +329,4 @@ b.length<=e}}}}},$c=function(){return{restrict:"A",require:"?ngModel",link:funct
|
|||
"PM"],DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),ERANAMES:["Before Christ","Anno Domini"],ERAS:["BC","AD"],FIRSTDAYOFWEEK:6,MONTH:"January February March April May June July August September October November December".split(" "),SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),STANDALONEMONTH:"January February March April May June July August September October November December".split(" "),WEEKENDRANGE:[5,
|
||||
6],fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",medium:"MMM d, y h:mm:ss a",mediumDate:"MMM d, y",mediumTime:"h:mm:ss a","short":"M/d/yy h:mm a",shortDate:"M/d/yy",shortTime:"h:mm a"},NUMBER_FORMATS:{CURRENCY_SYM:"$",DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{gSize:3,lgSize:3,maxFrac:3,minFrac:0,minInt:1,negPre:"-",negSuf:"",posPre:"",posSuf:""},{gSize:3,lgSize:3,maxFrac:2,minFrac:2,minInt:1,negPre:"-\u00a4",negSuf:"",posPre:"\u00a4",posSuf:""}]},id:"en-us",localeID:"en_US",pluralCat:function(a,
|
||||
c){var e=a|0,f=c;void 0===f&&(f=Math.min(b(a),3));Math.pow(10,f);return 1==e&&0==f?"one":"other"}})}]),B(function(){ue(x.document,Sc)}))})(window);!window.angular.$$csp().noInlineStyle&&window.angular.element(document.head).prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}.ng-animate-shim{visibility:hidden;}.ng-anchor{position:absolute;}</style>');
|
||||
//# sourceMappingURL=angular.min.js.map
|
||||
//# sourceMappingURL=angular-1.6.4.min.js.map
|
||||
|
|
8
services/web/public/js/libs/angular-1.6.4.min.js.map
Normal file
8
services/web/public/js/libs/angular-1.6.4.min.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
services/web/public/js/libs/jquery-1.11.1.min.js.map
Normal file
1
services/web/public/js/libs/jquery-1.11.1.min.js.map
Normal file
File diff suppressed because one or more lines are too long
|
@ -26,7 +26,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
|
|||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
define(['ace/ace','libs/sha1'], function () {
|
||||
define(['ace/ace','crypto-js/sha1'], function (_ignore, CryptoJSSHA1) {
|
||||
var append = void 0,
|
||||
bootstrapTransform = void 0,
|
||||
exports = void 0,
|
||||
|
@ -226,9 +226,6 @@ define(['ace/ace','libs/sha1'], function () {
|
|||
};
|
||||
};
|
||||
|
||||
if (typeof WEB === 'undefined') {
|
||||
exports.bootstrapTransform = bootstrapTransform;
|
||||
}
|
||||
// A simple text implementation
|
||||
//
|
||||
// Operations are lists of components.
|
||||
|
@ -673,21 +670,10 @@ define(['ace/ace','libs/sha1'], function () {
|
|||
|
||||
// [] is used to prevent closure from renaming types.text
|
||||
exports.types.text = text;
|
||||
} else {
|
||||
module.exports = text;
|
||||
|
||||
// The text type really shouldn't need this - it should be possible to define
|
||||
// an efficient transform function by making a sort of transform map and passing each
|
||||
// op component through it.
|
||||
require('./helpers').bootstrapTransform(text, transformComponent, checkValidOp, append);
|
||||
}
|
||||
|
||||
// Text document API for text
|
||||
|
||||
if (typeof WEB === 'undefined') {
|
||||
text = require('./text');
|
||||
}
|
||||
|
||||
text.api = {
|
||||
provides: { text: true },
|
||||
|
||||
|
@ -878,10 +864,6 @@ define(['ace/ace','libs/sha1'], function () {
|
|||
module.exports = MicroEvent;
|
||||
}
|
||||
|
||||
if (WEB == null) {
|
||||
types = require('../types');
|
||||
}
|
||||
|
||||
if (WEB != null) {
|
||||
exports.extendDoc = function (name, fn) {
|
||||
return Doc.prototype[name] = fn;
|
||||
|
@ -1311,7 +1293,7 @@ define(['ace/ace','libs/sha1'], function () {
|
|||
var needToRecomputeHash = !this.__lastSubmitTimestamp || (age > RECOMPUTE_HASH_INTERVAL) || (age < 0)
|
||||
if (needToRecomputeHash || window.sl_debugging) {
|
||||
// send git hash of current snapshot
|
||||
var sha1 = CryptoJS.SHA1("blob " + this.snapshot.length + "\x00" + this.snapshot).toString()
|
||||
var sha1 = CryptoJSSHA1("blob " + this.snapshot.length + "\x00" + this.snapshot).toString()
|
||||
this.__lastSubmitTimestamp = now;
|
||||
}
|
||||
}
|
||||
|
@ -1435,10 +1417,6 @@ define(['ace/ace','libs/sha1'], function () {
|
|||
// Make documents event emitters
|
||||
|
||||
|
||||
if (WEB == null) {
|
||||
MicroEvent = require('./microevent');
|
||||
}
|
||||
|
||||
MicroEvent.mixin(Doc);
|
||||
|
||||
exports.Doc = Doc;
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
define(['base', 'libs/md5'], function(App) {
|
||||
define(['base', 'crypto-js/md5'], function(App, CryptoJS) {
|
||||
const oldKeys = [
|
||||
'sl_abt_multi_currency_editor_eu-eu',
|
||||
'sl_abt_multi_currency_eu-eu',
|
||||
|
@ -73,7 +73,7 @@ define(['base', 'libs/md5'], function(App) {
|
|||
user_uuid = Math.random()
|
||||
ipCookie(sl_user_test_token, user_uuid, { expires: 365, path: '/' })
|
||||
}
|
||||
const hash = CryptoJS.MD5(`${user_uuid}:${testName}`)
|
||||
const hash = CryptoJS(`${user_uuid}:${testName}`)
|
||||
return hash
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,6 @@ define([
|
|||
'ide/directives/layout',
|
||||
'ide/directives/validFile',
|
||||
'ide/services/ide',
|
||||
'__IDE_CLIENTSIDE_INCLUDES__',
|
||||
'analytics/AbTestingManager',
|
||||
'directives/focus',
|
||||
'directives/fineUpload',
|
||||
|
@ -60,7 +59,8 @@ define([
|
|||
'filters/formatDate',
|
||||
'main/event',
|
||||
'main/account-upgrade',
|
||||
'main/exposed-settings'
|
||||
'main/exposed-settings',
|
||||
'../../modules/modules-ide.js'
|
||||
], function(
|
||||
App,
|
||||
FileTreeManager,
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
define(['base', 'libs/md5'], App =>
|
||||
define(['base', 'crypto-js/md5'], (App, CryptoJS) =>
|
||||
App.factory('chatMessages', function($http, ide) {
|
||||
const MESSAGES_URL = `/project/${ide.project_id}/messages`
|
||||
const MESSAGE_LIMIT = 50
|
||||
|
@ -152,7 +152,7 @@ define(['base', 'libs/md5'], App =>
|
|||
}
|
||||
|
||||
var formatUser = function(user) {
|
||||
const hash = CryptoJS.MD5(user.email.toLowerCase())
|
||||
const hash = CryptoJS(user.email.toLowerCase())
|
||||
user.gravatar_url = `//www.gravatar.com/avatar/${hash}`
|
||||
return user
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
define([], function() {
|
||||
define(['crypto-js/md5'], function(CryptoJS) {
|
||||
let ColorManager
|
||||
return (ColorManager = {
|
||||
getColorScheme(hue, element) {
|
||||
|
@ -72,7 +72,7 @@ define([], function() {
|
|||
},
|
||||
|
||||
getHueForId(id) {
|
||||
const hash = CryptoJS.MD5(id)
|
||||
const hash = CryptoJS(id)
|
||||
let hue = parseInt(hash.toString().slice(0, 8), 16) % 320
|
||||
return hue
|
||||
}
|
||||
|
|
|
@ -45,10 +45,10 @@ define([
|
|||
const { Vim } = ace.require('ace/keyboard/vim')
|
||||
const SearchBox = ace.require('ace/ext/searchbox')
|
||||
|
||||
// set the path for ace workers if using a CDN (from editor.pug)
|
||||
if (window.aceWorkerPath !== '') {
|
||||
// Set the base path that ace will fetch modes/snippets/workers from
|
||||
if (window.aceBasePath !== '') {
|
||||
syntaxValidationEnabled = true
|
||||
ace.config.set('workerPath', `${window.aceWorkerPath}`)
|
||||
ace.config.set('basePath', `${window.aceBasePath}`)
|
||||
} else {
|
||||
syntaxValidationEnabled = false
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
*/
|
||||
define([
|
||||
'ide/colors/ColorManager',
|
||||
'libs/md5',
|
||||
'crypto-js/md5',
|
||||
'ide/online-users/controllers/OnlineUsersController'
|
||||
], function(ColorManager) {
|
||||
let OnlineUsersManager
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
define(['base', 'pdfjs-dist/build/pdf'], (App, PDFJS) => {
|
||||
define(['base', 'pdfjs-dist/webpack'], (App, PDFJS) => {
|
||||
const EXTERNAL_LINK_TARGET = '_blank'
|
||||
const REL_NOOPENER = 'noreferrer noopener'
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
define(['base', 'pdfjs-dist/build/pdf'], (App, PDFJS) =>
|
||||
define(['base', 'pdfjs-dist/webpack'], (App, PDFJS) =>
|
||||
// app = angular.module 'pdfHighlights', []
|
||||
|
||||
App.factory('pdfHighlights', function() {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* DS207: Consider shorter variations of null checks
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
define(['base', 'pdfjs-dist/build/pdf'], (App, PDFJS) =>
|
||||
define(['base', 'pdfjs-dist/webpack'], (App, PDFJS) =>
|
||||
// App = angular.module 'PDFRenderer', ['pdfAnnotations', 'pdfTextLayer']
|
||||
|
||||
App.factory('PDFRenderer', function(
|
||||
|
|
|
@ -50,64 +50,70 @@ define([
|
|||
this.load = function() {
|
||||
// $scope.pages = []
|
||||
|
||||
if ($scope.document != null) {
|
||||
$scope.document.destroy()
|
||||
}
|
||||
$scope.loadCount = $scope.loadCount != null ? $scope.loadCount + 1 : 1
|
||||
// TODO need a proper url manipulation library to add to query string
|
||||
let url = $scope.pdfSrc
|
||||
// add 'pdfng=true' to show that we are using the angular pdfjs viewer
|
||||
const queryStringExists = /\?/.test(url)
|
||||
url = url + (!queryStringExists ? '?' : '&') + 'pdfng=true'
|
||||
// for isolated compiles, load the pdf on-demand because nobody will overwrite it
|
||||
const onDemandLoading = true
|
||||
$scope.document = new PDFRenderer(url, {
|
||||
scale: 1,
|
||||
disableAutoFetch: onDemandLoading ? true : undefined,
|
||||
navigateFn(ref) {
|
||||
// this function captures clicks on the annotation links
|
||||
$scope.navigateTo = ref
|
||||
return $scope.$apply()
|
||||
},
|
||||
progressCallback(progress) {
|
||||
return $scope.$emit('progress', progress)
|
||||
},
|
||||
loadedCallback() {
|
||||
return $scope.$emit('loaded')
|
||||
},
|
||||
errorCallback(error) {
|
||||
__guardMethod__(window.Raven, 'captureMessage', o =>
|
||||
o.captureMessage(`pdfng error ${error}`)
|
||||
)
|
||||
return $scope.$emit('pdf:error', error)
|
||||
},
|
||||
pageSizeChangeCallback(pageNum, deltaH) {
|
||||
return $scope.$broadcast('pdf:page:size-change', pageNum, deltaH)
|
||||
}
|
||||
})
|
||||
// Ensure previous document is torn down before loading the next one (to
|
||||
// prevent race conditions)
|
||||
const documentTearDown =
|
||||
$scope.document != null ? $scope.document.destroy() : Promise.resolve()
|
||||
|
||||
// we will have all the main information needed to start display
|
||||
// after the following promise is resolved
|
||||
return ($scope.loaded = $q
|
||||
.all({
|
||||
numPages: $scope.document.getNumPages(),
|
||||
// get size of first page as default @ scale 1
|
||||
pdfViewport: $scope.document.getPdfViewport(1, 1)
|
||||
return documentTearDown.then(() => {
|
||||
$scope.loadCount = $scope.loadCount != null ? $scope.loadCount + 1 : 1
|
||||
// TODO need a proper url manipulation library to add to query string
|
||||
let url = $scope.pdfSrc
|
||||
// add 'pdfng=true' to show that we are using the angular pdfjs viewer
|
||||
const queryStringExists = /\?/.test(url)
|
||||
url = url + (!queryStringExists ? '?' : '&') + 'pdfng=true'
|
||||
// for isolated compiles, load the pdf on-demand because nobody will overwrite it
|
||||
const onDemandLoading = true
|
||||
$scope.document = new PDFRenderer(url, {
|
||||
scale: 1,
|
||||
disableAutoFetch: onDemandLoading ? true : undefined,
|
||||
navigateFn(ref) {
|
||||
// this function captures clicks on the annotation links
|
||||
$scope.navigateTo = ref
|
||||
return $scope.$apply()
|
||||
},
|
||||
progressCallback(progress) {
|
||||
return $scope.$emit('progress', progress)
|
||||
},
|
||||
loadedCallback() {
|
||||
return $scope.$emit('loaded')
|
||||
},
|
||||
errorCallback(error) {
|
||||
__guardMethod__(window.Raven, 'captureMessage', o =>
|
||||
o.captureMessage(`pdfng error ${error}`)
|
||||
)
|
||||
return $scope.$emit('pdf:error', error)
|
||||
},
|
||||
pageSizeChangeCallback(pageNum, deltaH) {
|
||||
return $scope.$broadcast('pdf:page:size-change', pageNum, deltaH)
|
||||
}
|
||||
})
|
||||
.then(function(result) {
|
||||
$scope.pdfViewport = result.pdfViewport
|
||||
$scope.pdfPageSize = [
|
||||
result.pdfViewport.height,
|
||||
result.pdfViewport.width
|
||||
]
|
||||
// console.log 'resolved q.all, page size is', result
|
||||
$scope.$emit('loaded')
|
||||
return ($scope.numPages = result.numPages)
|
||||
})
|
||||
.catch(function(error) {
|
||||
$scope.$emit('pdf:error', error)
|
||||
return $q.reject(error)
|
||||
}))
|
||||
|
||||
// we will have all the main information needed to start display
|
||||
// after the following promise is resolved
|
||||
$scope.loaded = $q
|
||||
.all({
|
||||
numPages: $scope.document.getNumPages(),
|
||||
// get size of first page as default @ scale 1
|
||||
pdfViewport: $scope.document.getPdfViewport(1, 1)
|
||||
})
|
||||
.then(function(result) {
|
||||
$scope.pdfViewport = result.pdfViewport
|
||||
$scope.pdfPageSize = [
|
||||
result.pdfViewport.height,
|
||||
result.pdfViewport.width
|
||||
]
|
||||
// console.log 'resolved q.all, page size is', result
|
||||
$scope.$emit('loaded')
|
||||
return ($scope.numPages = result.numPages)
|
||||
})
|
||||
.catch(function(error) {
|
||||
$scope.$emit('pdf:error', error)
|
||||
return $q.reject(error)
|
||||
})
|
||||
|
||||
return $scope.loaded
|
||||
})
|
||||
}
|
||||
|
||||
this.setScale = (scale, containerHeight, containerWidth) =>
|
||||
|
|
|
@ -9,4 +9,4 @@
|
|||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
define(['base'], App =>
|
||||
app.filter('notEmpty', () => object => !angular.equals({}, object)))
|
||||
App.filter('notEmpty', () => object => !angular.equals({}, object)))
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
define(['base'], App =>
|
||||
app.filter(
|
||||
App.filter(
|
||||
'numKeys',
|
||||
() =>
|
||||
function(object) {
|
||||
|
|
|
@ -56,7 +56,7 @@ define([
|
|||
'services/validateCaptchaV3',
|
||||
'filters/formatDate',
|
||||
'components/inputSuggestions',
|
||||
'__MAIN_CLIENTSIDE_INCLUDES__'
|
||||
'../../modules/modules-main.js'
|
||||
], function() {
|
||||
angular.module('SharelatexApp').config(function($locationProvider) {
|
||||
try {
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
*/
|
||||
|
||||
const { User } = require('../../app/src/models/User')
|
||||
require('colors')
|
||||
// const somePackage = require('some-package')
|
||||
|
||||
const runScript = async () => {
|
||||
const user = await User.findOne({}, { first_name: 1 }).exec()
|
||||
const name = user ? user.first_name : 'World'
|
||||
console.log(`Hello ${name}!`.rainbow.underline.bold)
|
||||
console.log(`Hello ${name}!`)
|
||||
}
|
||||
|
||||
if (!module.parent) {
|
||||
|
|
|
@ -17,3 +17,19 @@ chai.Assertion.addMethod('equalPos', function(expectedPos) {
|
|||
`Pos({ line: ${actualLine}, ch: ${actualCh} })`
|
||||
)
|
||||
})
|
||||
|
||||
// Mock ExposedSettings
|
||||
window.ExposedSettings = {}
|
||||
|
||||
// Mock the file operation I18n names that are stored in the DOM
|
||||
function mockFileOperationI18nNames(id, text) {
|
||||
const el = document.createElement('div')
|
||||
el.id = id
|
||||
el.innerText = text
|
||||
el.setAttribute('hidden', true)
|
||||
document.body.appendChild(el)
|
||||
}
|
||||
mockFileOperationI18nNames('file_action_edited_str', 'edited')
|
||||
mockFileOperationI18nNames('file_action_renamed_str', 'renamed')
|
||||
mockFileOperationI18nNames('file_action_created_str', 'created')
|
||||
mockFileOperationI18nNames('file_action_deleted_str', 'deleted')
|
22
services/web/test/unit_frontend/import_tests.js
Normal file
22
services/web/test/unit_frontend/import_tests.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Bundle all test files together into a single bundle, and run tests against
|
||||
* this single bundle.
|
||||
* We are using karma-webpack to bundle our tests and the 'default' strategy is
|
||||
* to create a bundle for each test file. This isolates the tests better, but
|
||||
* causes a problem with Angular. The issue with Angular tests is because we
|
||||
* load a single global copy of Angular (see karma.conf.js) but
|
||||
* public/src/base.js is included in each bundle, meaning the Angular app is
|
||||
* initialised for each bundle when it is loaded onto the page when Karma
|
||||
* starts. This means that only the last bundle will have controllers/directives
|
||||
* registered against it, ultimately meaning that all other bundles will fail
|
||||
* because Angular cannot find the controller/directive under test.
|
||||
*/
|
||||
|
||||
// Import from the top-level any JS files within a test/unit_frontend/src
|
||||
// directory
|
||||
const context = require.context(
|
||||
'../../',
|
||||
true,
|
||||
/test\/unit_frontend\/src\/.*\.js$/
|
||||
)
|
||||
context.keys().forEach(context)
|
|
@ -1,8 +0,0 @@
|
|||
define([], () => {
|
||||
return {
|
||||
edited: 'edited',
|
||||
renamed: 'renamed',
|
||||
created: 'created',
|
||||
deleted: 'deleted'
|
||||
}
|
||||
})
|
|
@ -1,34 +0,0 @@
|
|||
/* eslint-disable
|
||||
no-undef,
|
||||
max-len,
|
||||
*/
|
||||
// Set up requirejs to load the tests and mocked dependencies
|
||||
// For tests, uses heuristic that test filenames end with Tests.js (existing
|
||||
// frontend code) or _tests.js (newer frontend code)
|
||||
// For mocks, uses heuristic that loads any .js file within the mocks subfolder
|
||||
const testDeps = []
|
||||
for (let file in window.__karma__.files) {
|
||||
if (window.__karma__.files.hasOwnProperty(file)) {
|
||||
if (
|
||||
/test\/unit_frontend\/js.+(_t|T)ests\.js$/.test(file) ||
|
||||
/test\/unit_frontend\/js\/mocks\/.+\.js$/.test(file)
|
||||
) {
|
||||
testDeps.push(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
requirejs.config({
|
||||
baseUrl: '/base/public/js',
|
||||
paths: {
|
||||
moment: 'libs/moment-2.9.0'
|
||||
},
|
||||
map: {
|
||||
'*': {
|
||||
'ide/file-tree/util/fileOperationI18nNames':
|
||||
'../../test/unit_frontend/js/mocks/ide/file-tree/util/fileOperationI18nNames'
|
||||
}
|
||||
},
|
||||
deps: testDeps,
|
||||
callback: window.__karma__.start
|
||||
})
|
|
@ -1,3 +1,4 @@
|
|||
const path = require('path')
|
||||
const merge = require('webpack-merge')
|
||||
|
||||
const base = require('./webpack.config')
|
||||
|
@ -9,7 +10,7 @@ module.exports = merge(base, {
|
|||
devtool: 'cheap-module-eval-source-map',
|
||||
|
||||
output: {
|
||||
publicPath: '/public/js/es/'
|
||||
publicPath: '/js/'
|
||||
},
|
||||
|
||||
devServer: {
|
||||
|
@ -27,21 +28,21 @@ module.exports = merge(base, {
|
|||
'Access-Control-Allow-Origin': '*'
|
||||
},
|
||||
|
||||
// Serve all content from public via webpack. This allows for serving assets
|
||||
// not (currently) bundled with webpack to be served as normal scripts
|
||||
contentBase: path.join(__dirname, 'public'),
|
||||
|
||||
// Customise output to the (node) console
|
||||
stats: {
|
||||
colors: true, // Enable some coloured highlighting
|
||||
timings: true, // Show build timing info
|
||||
assets: true, // Show output bundles
|
||||
warnings: true, // Show build warnings
|
||||
// Hide some overly verbose output
|
||||
performance: false, // Disable as code is uncompressed in dev mode
|
||||
hash: false,
|
||||
version: false,
|
||||
chunks: false
|
||||
chunks: false,
|
||||
modules: false,
|
||||
// Hide cmaps from asset output
|
||||
excludeAssets: [/cmap/]
|
||||
}
|
||||
},
|
||||
|
||||
// Disable performance budget warnings as code is uncompressed in dev mode
|
||||
performance: {
|
||||
hints: false
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,13 +1,22 @@
|
|||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const webpack = require('webpack')
|
||||
const CopyPlugin = require('copy-webpack-plugin')
|
||||
const ManifestPlugin = require('webpack-manifest-plugin')
|
||||
|
||||
const PackageVersions = require('./app/src/infrastructure/PackageVersions')
|
||||
|
||||
const MODULES_PATH = path.join(__dirname, '/modules')
|
||||
|
||||
// Generate a hash of entry points, including modules
|
||||
const entryPoints = {}
|
||||
const entryPoints = {
|
||||
main: './public/src/main.js',
|
||||
ide: './public/src/ide.js'
|
||||
}
|
||||
|
||||
if (fs.existsSync(MODULES_PATH)) {
|
||||
fs.readdirSync(MODULES_PATH).reduce((acc, module) => {
|
||||
const entryPath = path.join(MODULES_PATH, module, '/public/es/index.js')
|
||||
const entryPath = path.join(MODULES_PATH, module, '/public/src/index.js')
|
||||
if (fs.existsSync(entryPath)) {
|
||||
acc[module] = entryPath
|
||||
}
|
||||
|
@ -15,12 +24,6 @@ if (fs.existsSync(MODULES_PATH)) {
|
|||
}, entryPoints)
|
||||
}
|
||||
|
||||
// If no entry points are found, silently exit
|
||||
if (!Object.keys(entryPoints).length) {
|
||||
console.warn('No entry points found, exiting')
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
// Defines the "entry point(s)" for the application - i.e. the file which
|
||||
// bootstraps the application
|
||||
|
@ -30,7 +33,7 @@ module.exports = {
|
|||
// Note: webpack-dev-server does not write the bundle to disk, instead it is
|
||||
// kept in memory for speed
|
||||
output: {
|
||||
path: path.join(__dirname, '/public/js/es'),
|
||||
path: path.join(__dirname, '/public/js'),
|
||||
|
||||
filename: '[name].js',
|
||||
|
||||
|
@ -61,7 +64,7 @@ module.exports = {
|
|||
]
|
||||
},
|
||||
{
|
||||
// These options are neccesary for handlebars to have access to helper
|
||||
// These options are necessary for handlebars to have access to helper
|
||||
// methods
|
||||
test: /\.handlebars$/,
|
||||
loader: 'handlebars-loader',
|
||||
|
@ -70,14 +73,122 @@ module.exports = {
|
|||
knownHelpersOnly: false,
|
||||
runtimePath: 'handlebars/runtime'
|
||||
}
|
||||
},
|
||||
// Allow for injection of modules dependencies by reading contents of
|
||||
// modules directory and adding necessary dependencies
|
||||
{
|
||||
test: path.join(__dirname, 'modules/modules-main.js'),
|
||||
use: [
|
||||
{
|
||||
loader: 'val-loader'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
test: path.join(__dirname, 'modules/modules-ide.js'),
|
||||
use: [
|
||||
{
|
||||
loader: 'val-loader'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
// Expose underscore global variable
|
||||
test: path.join(
|
||||
__dirname,
|
||||
`public/js/libs/${PackageVersions.lib('underscore')}.js`
|
||||
),
|
||||
use: [
|
||||
{
|
||||
loader: 'expose-loader',
|
||||
options: '_'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
// Expose Algolia global variable
|
||||
test: path.join(
|
||||
__dirname,
|
||||
`public/js/libs/${PackageVersions.lib('algolia')}.js`
|
||||
),
|
||||
use: [
|
||||
{
|
||||
loader: 'expose-loader',
|
||||
options: 'AlgoliaSearch'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
// makes handlebars globally accessible to backbone
|
||||
handlebars: 'handlebars/dist/handlebars.min.js',
|
||||
jquery: path.join(__dirname, 'node_modules/jquery/dist/jquery')
|
||||
// Aliases for AMD modules
|
||||
|
||||
// Vendored dependencies in public/js/libs (e.g. angular)
|
||||
libs: path.join(__dirname, 'public/js/libs'),
|
||||
// Use vendored moment (with correct version)
|
||||
moment: path.join(
|
||||
__dirname,
|
||||
`public/js/libs/${PackageVersions.lib('moment')}`
|
||||
),
|
||||
// Enables ace/ace shortcut
|
||||
ace: path.join(__dirname, `public/js/${PackageVersions.lib('ace')}`),
|
||||
// fineupload vendored dependency (which we're aliasing to fineuploadER
|
||||
// for some reason)
|
||||
fineuploader: path.join(
|
||||
__dirname,
|
||||
`public/js/libs/${PackageVersions.lib('fineuploader')}`
|
||||
)
|
||||
},
|
||||
// Define what can be imported with out an absolute or relative path. This
|
||||
// is because we need to override the default (which is just node_modules)
|
||||
// to get AMD modules in public/src to work as they do not use relative/
|
||||
// absolute paths for dependencies
|
||||
modules: [path.join(__dirname, 'public/src'), 'node_modules']
|
||||
},
|
||||
|
||||
// Split out vendored dependencies that are shared between 2 or more "real
|
||||
// bundles" (e.g. ide.js/main.js) as a separate "libraries" bundle and ensure
|
||||
// that they are de-duplicated from the other bundles. This allows the
|
||||
// libraries bundle to be independently cached (as it likely will change less
|
||||
// than the other bundles)
|
||||
optimization: {
|
||||
splitChunks: {
|
||||
cacheGroups: {
|
||||
libraries: {
|
||||
test: /[\\/]node_modules[\\/]|[\\/]public[\\/]js[\\/]libs[\\/]/,
|
||||
name: 'libraries',
|
||||
chunks: 'initial',
|
||||
minChunks: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
plugins: [
|
||||
// Generate a manifest.json file which is used by the backend to map the
|
||||
// base filenames to the generated output filenames
|
||||
new ManifestPlugin({
|
||||
// Always write the manifest file to disk (even if in dev mode, where
|
||||
// files are held in memory). This is needed because the server will read
|
||||
// this file (from disk) when building the script's url
|
||||
writeToFileEmit: true
|
||||
}),
|
||||
|
||||
// Silence warning when loading moment from vendored dependencies as it
|
||||
// attempts to load locales.js file which does not exist (but this is fine
|
||||
// as we don't want to load the large amount of locale data from moment)
|
||||
new webpack.IgnorePlugin(/^\.\/locale$/, /public\/js\/libs/),
|
||||
|
||||
// Copy CMap files from pdfjs-dist package to build output. These are used
|
||||
// to provide support for non-Latin characters
|
||||
new CopyPlugin([{ from: 'node_modules/pdfjs-dist/cmaps', to: 'cmaps' }])
|
||||
],
|
||||
|
||||
// If jquery or underscore is required by another dependency *don't* include
|
||||
// in the bundle and use the relevant global variable instead
|
||||
externals: {
|
||||
jquery: '$',
|
||||
underscore: '_'
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,58 @@
|
|||
const path = require('path')
|
||||
const merge = require('webpack-merge')
|
||||
const CopyPlugin = require('copy-webpack-plugin')
|
||||
|
||||
const base = require('./webpack.config')
|
||||
const PackageVersions = require('./app/src/infrastructure/PackageVersions')
|
||||
|
||||
module.exports = merge(base, {
|
||||
mode: 'production',
|
||||
|
||||
devtool: false,
|
||||
// Enable a full source map. Generates a comment linking to the source map
|
||||
devtool: 'source-map',
|
||||
|
||||
output: {
|
||||
// Override output path to minjs dir
|
||||
path: path.join(__dirname, '/public/minjs/es')
|
||||
}
|
||||
path: path.join(__dirname, '/public/minjs'),
|
||||
|
||||
// Override filename to include hash for immutable caching
|
||||
filename: '[name]-[chunkhash].js',
|
||||
|
||||
publicPath: '/minjs/'
|
||||
},
|
||||
|
||||
plugins: [
|
||||
// Copy vendored dependencies to minjs directory as these are directly
|
||||
// loaded in a script tag by instead of being part of the webpack build
|
||||
new CopyPlugin([
|
||||
{
|
||||
from: 'public/js/libs/angular-1.6.4.min.js',
|
||||
to: 'libs/angular-1.6.4.min.js'
|
||||
},
|
||||
{
|
||||
from: 'public/js/libs/angular-1.6.4.min.js.map',
|
||||
to: 'libs/angular-1.6.4.min.js.map'
|
||||
},
|
||||
{
|
||||
from: 'public/js/libs/jquery-1.11.1.min.js',
|
||||
to: 'libs/jquery-1.11.1.min.js'
|
||||
},
|
||||
{
|
||||
from: 'public/js/libs/jquery-1.11.1.min.js.map',
|
||||
to: 'libs/jquery-1.11.1.min.js.map'
|
||||
},
|
||||
{
|
||||
from: 'public/js/libs/mathjax',
|
||||
to: 'libs/mathjax'
|
||||
},
|
||||
{
|
||||
from: 'public/js/libs/sigma-master',
|
||||
to: 'libs/sigma-master'
|
||||
},
|
||||
{
|
||||
from: `public/js/ace-${PackageVersions.version.ace}/`,
|
||||
to: `ace-${PackageVersions.version.ace}/`
|
||||
}
|
||||
])
|
||||
]
|
||||
})
|
||||
|
|
11
services/web/webpack.config.test.js
Normal file
11
services/web/webpack.config.test.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
const merge = require('webpack-merge')
|
||||
|
||||
const base = require('./webpack.config')
|
||||
|
||||
module.exports = merge(base, {
|
||||
mode: 'development',
|
||||
|
||||
// Karma configures entry & output for us, so disable these
|
||||
entry: null,
|
||||
output: null
|
||||
})
|
Loading…
Reference in a new issue