@modusoperandi/licit 0.14.3 → 0.14.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = void 0;
7
7
  var _prosemirrorState = require("prosemirror-state");
8
8
  var _prosemirrorView = require("prosemirror-view");
9
+ var _prosemirrorModel = require("prosemirror-model");
9
10
  var React = _interopRequireWildcard(require("react"));
10
11
  var _CommandMenuButton = _interopRequireDefault(require("./CommandMenuButton"));
11
12
  var _EditorToolbarConfig = require("./EditorToolbarConfig");
@@ -26,11 +27,20 @@ class TableCellMenu extends React.PureComponent {
26
27
  render() {
27
28
  const {
28
29
  editorState,
29
- editorView
30
+ editorView,
31
+ pluginView,
32
+ actionNode
30
33
  } = this.props;
34
+ let cmdGrps = null;
35
+ if (pluginView.getMenu) {
36
+ cmdGrps = pluginView.getMenu(editorState, actionNode, _EditorToolbarConfig.TABLE_COMMANDS_GROUP);
37
+ }
38
+ if (!cmdGrps) {
39
+ cmdGrps = _EditorToolbarConfig.TABLE_COMMANDS_GROUP;
40
+ }
31
41
  return /*#__PURE__*/React.createElement(_CommandMenuButton.default, {
32
42
  className: "czi-table-cell-menu",
33
- commandGroups: _EditorToolbarConfig.TABLE_COMMANDS_GROUP,
43
+ commandGroups: cmdGrps,
34
44
  dispatch: editorView.dispatch,
35
45
  editorState: editorState,
36
46
  editorView: editorView,
@@ -1,6 +1,7 @@
1
1
  // @flow
2
- import { EditorState } from 'prosemirror-state';
2
+ import { EditorState, PluginView } from 'prosemirror-state';
3
3
  import { EditorView } from 'prosemirror-view';
4
+ import { Node } from 'prosemirror-model';
4
5
  import * as React from 'react';
5
6
 
6
7
  import CommandMenuButton from './CommandMenuButton';
@@ -12,6 +13,8 @@ import './czi-table-cell-menu.css';
12
13
  type Props = {
13
14
  editorState: EditorState,
14
15
  editorView: EditorView,
16
+ pluginView: PluginView,
17
+ actionNode: Node,
15
18
  };
16
19
 
17
20
  class TableCellMenu extends React.PureComponent<any, any> {
@@ -20,11 +23,21 @@ class TableCellMenu extends React.PureComponent<any, any> {
20
23
  props: Props;
21
24
 
22
25
  render(): React.Element<any> {
23
- const { editorState, editorView } = this.props;
26
+ const { editorState, editorView, pluginView, actionNode } = this.props;
27
+ let cmdGrps = null;
28
+
29
+ if (pluginView.getMenu) {
30
+ cmdGrps = pluginView.getMenu(editorState, actionNode, TABLE_COMMANDS_GROUP);
31
+ }
32
+
33
+ if (!cmdGrps) {
34
+ cmdGrps = TABLE_COMMANDS_GROUP;
35
+ }
36
+
24
37
  return (
25
38
  <CommandMenuButton
26
39
  className="czi-table-cell-menu"
27
- commandGroups={TABLE_COMMANDS_GROUP}
40
+ commandGroups={cmdGrps}
28
41
  dispatch={editorView.dispatch}
29
42
  editorState={editorState}
30
43
  editorView={editorView}
@@ -12,8 +12,10 @@ function isElementFullyVisible(el) {
12
12
  w,
13
13
  h
14
14
  } = (0, _licitUiCommands.fromHTMlElement)(el);
15
+ // to handle the rounded border scenario.
16
+ const factor = '10px' === el.style.borderRadius ? 3 : 1;
15
17
  // Only checks the top-left point.
16
- const nwEl = w && h ? el.ownerDocument.elementFromPoint(x + 1, y + 1) : null;
18
+ const nwEl = w && h ? el.ownerDocument.elementFromPoint(x + factor, y + factor) : null;
17
19
  if (!nwEl) {
18
20
  return false;
19
21
  }
@@ -4,8 +4,11 @@ import { fromHTMlElement } from '@modusoperandi/licit-ui-commands';
4
4
 
5
5
  export default function isElementFullyVisible(el: HTMLElement): boolean {
6
6
  const { x, y, w, h } = fromHTMlElement(el);
7
+ // to handle the rounded border scenario.
8
+ const factor = '10px' === el.style.borderRadius ? 3 : 1;
7
9
  // Only checks the top-left point.
8
- const nwEl = w && h ? el.ownerDocument.elementFromPoint(x + 1, y + 1) : null;
10
+ const nwEl =
11
+ w && h ? el.ownerDocument.elementFromPoint(x + factor, y + factor) : null;
9
12
 
10
13
  if (!nwEl) {
11
14
  return false;
@@ -3,7 +3,7 @@
3
3
  // This implements the interface of `EditorRuntime`.
4
4
  // To run editor directly:
5
5
  import type { ImageLike } from '../../src/Types';
6
- import { POST, req } from '../../src/client/http';
6
+ import { POST } from '../../src/client/http';
7
7
 
8
8
  // When use it in a componet:
9
9
 
@@ -12,42 +12,201 @@ import { POST, req } from '../../src/client/http';
12
12
  import {POST } from '@modusoperandi/licit';
13
13
  */
14
14
 
15
+ // const GLOSSARY_URI = 'http://greathints.com:3003';
16
+
17
+ type Glossary = {
18
+ id: string,
19
+ term: string,
20
+ description: string,
21
+ };
22
+
15
23
  class CustomLicitRuntime {
24
+ getAcronyms(abbreviation: string): Promise<Glossary[]> {
25
+ return new Promise((resolve, _reject) => {
26
+ resolve([
27
+ {
28
+ id: '1',
29
+ term: 'ASAP',
30
+ description:
31
+ 'ASAP is an acronym for as soon as possible. This common phrase means you will do something when you have the chance.',
32
+ },
33
+ {
34
+ id: '2',
35
+ term: 'IMAX',
36
+ description:
37
+ 'The IMAX in IMAX Theater actually stands for Image Maximum. This is a large-format movie theater.',
38
+ },
39
+ {
40
+ id: '3',
41
+ term: 'PIN',
42
+ description:
43
+ 'When in all-caps, the word PIN stands for �personal identification number.� This is a secret number you create to access private documents, files and account information.',
44
+ },
45
+ {
46
+ id: '4',
47
+ term: 'RADAR',
48
+ description:
49
+ 'RADAR stands for �radio detection and ranging.� This technology is rarely called anything other than its acronym.',
50
+ },
51
+ {
52
+ id: '5',
53
+ term: 'TASER',
54
+ description:
55
+ 'The electrical weapon actually is an acronym for �Thomas A. Swift�s Electric Rifle.�',
56
+ },
57
+ {
58
+ id: '6',
59
+ term: 'SCUBA',
60
+ description:
61
+ 'This piece of diving equipment is an acronym for �self-contained underwater breathing apparatus.�',
62
+ },
63
+ {
64
+ id: '7',
65
+ term: 'NASA',
66
+ description:
67
+ 'NASA stands for �National Aeronautics and Space Administration,� and this organization once took a man to the moon.',
68
+ },
69
+ {
70
+ id: '8',
71
+ term: 'NAFTA',
72
+ description:
73
+ 'NAFTA is the acronym or the �North American Free Trade Agreement.� This organization governs trade among North American countries.',
74
+ },
75
+ {
76
+ id: '9',
77
+ term: 'HIPAA',
78
+ description:
79
+ 'The �Health Insurance Portability Accountability Act� is responsible for keeping medical information private.',
80
+ },
81
+ {
82
+ id: '10',
83
+ term: 'DARE',
84
+ description:
85
+ 'Most people no longer remember that DARE stands for �Drug Abuse Resistance Education�',
86
+ },
87
+ { id: 11, term: 'AEF', description: 'air expeditionary force' },
88
+ { id: 12, term: 'AFDP', description: 'Air Force Doctrine Publication' },
89
+ {
90
+ id: 13,
91
+ term: 'AvFID',
92
+ description: 'aviation foreign internal defense',
93
+ },
94
+ { id: 14, term: 'BSZ', description: 'base security zone' },
95
+ { id: 15, term: 'CS', description: 'combat support' },
96
+ {
97
+ id: 16,
98
+ term: 'COMAFFOR',
99
+ description: 'commander, Air Force forces',
100
+ },
101
+ {
102
+ id: 17,
103
+ term: 'COMAFSOF',
104
+ description: 'commander, Air Force special operations forces',
105
+ },
106
+ { id: 18, term: 'CoL', description: 'continuum of learning' },
107
+ {
108
+ id: 19,
109
+ term: 'CTO',
110
+ description: 'counterthreat operations; cyber tasking order',
111
+ },
112
+ { id: 20, term: 'DFC', description: 'defense force commander' },
113
+ { id: 21, term: 'DCS', description: 'defensive counterspace' },
114
+ {
115
+ id: 22,
116
+ term: 'DIRSPACEFOR',
117
+ description: 'director of space forces',
118
+ },
119
+ {
120
+ id: 23,
121
+ term: 'EBAO',
122
+ description: 'effects-based approach to operations',
123
+ },
124
+ {
125
+ id: 24,
126
+ term: 'EWIR',
127
+ description: 'electronic warfare integrated reprogramming',
128
+ },
129
+ { id: 25, term: 'FPI', description: 'force protection intelligence' },
130
+ {
131
+ id: 26,
132
+ term: 'GAMSS',
133
+ description: 'Global Air Mobility Support System',
134
+ },
135
+ { id: 27, term: 'JPPA', description: 'joint planning process for air' },
136
+ { id: 28, term: 'OA', description: 'operational-level assessment' },
137
+ { id: 29, term: 'OCS', description: 'offensive counterspace' },
138
+ { id: 30, term: 'OWS', description: 'operational weather squadron' },
139
+ ]);
140
+ });
141
+ }
142
+
143
+ getGlossary(term: string): Promise<Glossary[]> {
144
+ return new Promise((resolve, _reject) => {
145
+ resolve([
146
+ { id: '1', term: 'IAS', description: 'Indian Administrative Service' },
147
+ { id: '2', term: 'IIT', description: 'Indian Institute of Technology' },
148
+ { id: '3', term: 'CAS', description: 'Close Air Support' },
149
+ { id: '4', term: 'CAS', description: 'Continuous Aerial Surveillance' },
150
+ {
151
+ id: '5',
152
+ term: 'Analysis of Variance (ANOVA)',
153
+ description:
154
+ 'A statistical tool used to analyze the differences among means.',
155
+ },
156
+ {
157
+ id: '6',
158
+ term: 'Confidence Interval (CI)',
159
+ description:
160
+ 'The mean of an estimate 4/- the variation in the estimate.',
161
+ },
162
+ {
163
+ id: '7',
164
+ term: 'Comma Separated Value (CSV)',
165
+ description:
166
+ 'A text file that uses a comma (,) to separate each value inputted.',
167
+ },
168
+ {
169
+ id: '8',
170
+ term: 'Mean Squared Error (MSE)',
171
+ description:
172
+ 'A measurement of how close a fitted line is to plotted data points.',
173
+ },
174
+ {
175
+ id: '9',
176
+ term: 'Odds Ratio (OR)',
177
+ description:
178
+ 'A quantification of the strength of association between two events.',
179
+ },
180
+ {
181
+ id: '10',
182
+ term: 'Process Behavior Analysis (PBA)',
183
+ description: 'Written analysis of a Process Behavior Chart (PBC.)',
184
+ },
185
+ {
186
+ id: '11',
187
+ term: 'Quality Assurance (QA)',
188
+ description:
189
+ 'Systematic monitoring and evaluation to ensure standards are met.',
190
+ },
191
+ {
192
+ id: '12',
193
+ term: 'Root Mean Square (RMC)',
194
+ description:
195
+ 'The square root of the mean square, or the quadratic mean.',
196
+ },
197
+ ]);
198
+ });
199
+ }
200
+
16
201
  // Image Proxy
17
202
  canProxyImageSrc(): boolean {
18
203
  return false;
19
204
  }
20
205
 
21
- getProxyImageSrc(id: string): Promise<string> {
22
- return new Promise((resolve, reject) => {
23
- const token =
24
- 'Bearer <access_token>';
25
- const endPoint = 'https://moviacloud.modusoperandi.com/movia/content';
26
-
27
- (async () => {
28
- // image that will be fetched and appended
29
- const imageURL = endPoint + id;
30
-
31
- // Fetch remote URL, getting contents as binary blob
32
- const vidBlob = await (
33
- await fetch(imageURL, { headers: { Authorization: token } })
34
- ).blob();
35
-
36
- const reader = new window.FileReader();
37
- reader.addEventListener('error', () =>
38
- reject(new Error('Failed to load image'))
39
- );
40
- reader.addEventListener('load', () =>
41
- // Convert to ImageLike. Width and Height are unknown, and would
42
- // require rendering into a hidden canvas to determine
43
- resolve({
44
- alt: vidBlob.name,
45
- src: reader.result
46
- })
47
- );
48
- reader.readAsDataURL(vidBlob);
49
- })();
50
- });
206
+ getProxyImageSrc(src: string): string {
207
+ // This simulate a fake proxy.
208
+ const suffix = 'proxied=1';
209
+ return src.indexOf('?') === -1 ? `${src}?${suffix}` : `${src}&${suffix}`;
51
210
  }
52
211
 
53
212
  // Image Upload
@@ -94,33 +253,8 @@ class CustomLicitRuntime {
94
253
  }
95
254
 
96
255
  getProxyVideoSrc(src: string): string {
97
- // This simulate a fake proxy.
98
- const suffix = 'proxied=1';
99
- return src.indexOf('?') === -1 ? `${src}?${suffix}` : `${src}&${suffix}`;
100
- }
101
-
102
- getVideoSrc(id: string): Promise<string> {
103
- return new Promise((resolve, reject) => {
104
- const token =
105
- 'Bearer <access_token>';
106
- const endPoint = 'https://moviacloud.modusoperandi.com/movia/content';
107
-
108
- (async () => {
109
- // Video that will be fetched and appended
110
- const remoteVidUrl = endPoint + '/id/' + id;
111
-
112
- // Fetch remote URL, getting contents as binary blob
113
- const vidBlob = await (
114
- await fetch(remoteVidUrl, { headers: { Authorization: token } })
115
- ).blob();
116
-
117
- const videoEle = document.createElement('video');
118
- videoEle.src = URL.createObjectURL(vidBlob);
119
- videoEle.addEventListener('loadedmetadata', function () {
120
- resolve(videoEle.src);
121
- });
122
- })();
123
- });
256
+ // eslint-disable-next-line
257
+ return getProxyImageSrc(src);
124
258
  }
125
259
 
126
260
  // Video Upload
@@ -128,51 +262,36 @@ class CustomLicitRuntime {
128
262
  return true;
129
263
  }
130
264
 
131
- uploadVideo(blob: Object, id: string): Promise<ImageLike> {
265
+ uploadVideo(blob: Object): Promise<ImageLike> {
132
266
  let img: ImageLike;
267
+ // Note: While looking at the uploadImage() function, it is found that a promise is resolved blindly after 3 seconds. Is it a
268
+ // requirement? If not, then I think it causes two issues, 1. Even if an image upload finishes in 700ms, it will take 3s for
269
+ // resolving the promise. 2. If the image upload takes more than 3s, then the promise will be incorrectly resolved before
270
+ // completing the upload.
271
+ // The following structure may be good to solve the issue.
133
272
  return new Promise((resolve, reject) => {
134
273
  // Use uploaded image URL.
135
- const formData = new FormData();
136
- formData.append('label', blob.name);
137
- formData.append('file', blob);
138
- const token =
139
- 'Bearer <access_token>';
140
- const endPoint = 'https://moviacloud.modusoperandi.com/movia/content';
141
- req({
142
- url: endPoint,
143
- method: 'POST',
144
- body: formData,
145
- headers: {
146
- Authorization: token,
147
- },
148
- }).then((data) => {
149
- const resp = JSON.parse(data);
150
- const id = resp.entity.id.substring(
151
- resp.entity.id.lastIndexOf('/') + 1
152
- );
153
-
154
- (async () => {
155
- // Video that will be fetched and appended
156
- const remoteVidUrl = endPoint + '/id/' + id;
157
-
158
- // Fetch remote URL, getting contents as binary blob
159
- const vidBlob = await (
160
- await fetch(remoteVidUrl, { headers: { Authorization: token } })
161
- ).blob();
162
-
163
- const videoEle = document.createElement('video');
164
- videoEle.src = URL.createObjectURL(vidBlob);
165
- videoEle.addEventListener('loadedmetadata', function () {
166
- img = {
167
- id: id,
168
- width: this.videoWidth,
169
- height: this.videoHeight,
170
- src: videoEle.src,
171
- };
172
- resolve(img);
173
- });
174
- })();
175
- });
274
+ const url =
275
+ window.location.protocol +
276
+ '//' +
277
+ window.location.hostname +
278
+ ':3004/saveimage?fn=' +
279
+ blob.name;
280
+ POST(url, blob, 'application/octet-stream').then(
281
+ (data) => {
282
+ img = JSON.parse(data);
283
+ resolve(img);
284
+ },
285
+ (err) => {
286
+ img = {
287
+ id: '',
288
+ width: 0,
289
+ height: 0,
290
+ src: '',
291
+ };
292
+ reject(img);
293
+ }
294
+ );
176
295
  });
177
296
  }
178
297
  }
@@ -335,7 +335,7 @@ function main(): void {
335
335
  // To pass prosemirror plugins to editor pass it to plugins property which accept array of plugin object.
336
336
  // null means no custom plugins to pass
337
337
  // the plugin object must contain a method getEffectiveSchema() which accept schema and returns schema.
338
- const plugins = null;
338
+ const plugins = [];
339
339
  const runtime = new CustomLicitRuntime();
340
340
  ReactDOM.render(
341
341
  <Licit
@@ -343,7 +343,7 @@ function main(): void {
343
343
  data={docJSON}
344
344
  dataType={DataType.JSON}
345
345
  debug={true}
346
- docID={'0000-0000-0000-0000'}
346
+ docID={''}
347
347
  embedded={false}
348
348
  height={'100vh'}
349
349
  onChange={onChangeCB}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@modusoperandi/licit",
3
- "version": "0.14.3",
3
+ "version": "0.14.14",
4
4
  "subversion": "1",
5
5
  "description": "Rich text editor built with React and ProseMirror",
6
6
  "main": "dist/index.js",
@@ -56,7 +56,7 @@
56
56
  "babel-plugin-transform-react-remove-prop-types": "0.4.24",
57
57
  "clean-webpack-plugin": "4.0.0",
58
58
  "copy-webpack-plugin": "^11.0.0",
59
- "css-loader": "3.6.0",
59
+ "css-loader": "6.7.3",
60
60
  "enzyme": "^3.11.0",
61
61
  "eslint": "^8.25.0",
62
62
  "eslint-config-prettier": "^8.5.0",
@@ -70,12 +70,12 @@
70
70
  "flow-webpack-plugin": "1.2.0",
71
71
  "html-loader": "1.1.0",
72
72
  "html-webpack-inline-source-plugin": "1.0.0-beta.2",
73
- "html-webpack-plugin": "^4.5.0",
73
+ "html-webpack-plugin": "^5.5.0",
74
74
  "husky": "^8.0.1",
75
75
  "identity-obj-proxy": "^3.0.0",
76
76
  "jest": "^29.2.0",
77
77
  "jest-environment-jsdom": "^29.3.1",
78
- "jest-prosemirror": "^2.0.6",
78
+ "jest-prosemirror": "^1.0.3",
79
79
  "jest-sonar-reporter": "^2.0.0",
80
80
  "lint-staged": "^13.0.3",
81
81
  "mkdirp": "^1.0.4",
@@ -105,9 +105,7 @@
105
105
  "node-mathquill": "0.10.2",
106
106
  "prosemirror-collab": "1.2.2",
107
107
  "prosemirror-dev-tools": "3.0.2",
108
- "prosemirror-model": "~1.16.0",
109
108
  "prosemirror-tables": "1.2.5",
110
- "prosemirror-view": "1.27.0",
111
109
  "query-string": "6.13.1",
112
110
  "resize-observer-polyfill": "1.5.1",
113
111
  "smooth-scroll-into-view-if-needed": "1.1.28",
@@ -13,6 +13,7 @@ import { createPopUp } from '@modusoperandi/licit-ui-commands';
13
13
  import isElementFullyVisible from './ui/isElementFullyVisible';
14
14
 
15
15
  import '@modusoperandi/licit-ui-commands/dist/ui/czi-pop-up.css';
16
+ import { CellSelection } from 'prosemirror-tables';
16
17
 
17
18
  class TableCellTooltipView {
18
19
  _cellElement: null;
@@ -41,9 +42,15 @@ class TableCellTooltipView {
41
42
 
42
43
  let cellEl = domFound.node;
43
44
  const popUp = this._popUp;
45
+ let actionNode = null;
46
+ if (result && state.selection instanceof CellSelection) {
47
+ actionNode = state.selection.$anchorCell.node(-1);
48
+ }
44
49
  const viewPops = {
45
50
  editorState: state,
46
51
  editorView: view,
52
+ pluginView: this,
53
+ actionNode,
47
54
  };
48
55
 
49
56
  if (cellEl && !isElementFullyVisible(cellEl)) {
@@ -595,9 +595,10 @@ export default class TableResizePlugin extends Plugin {
595
595
  key: PLUGIN_KEY,
596
596
  state: {
597
597
  init(_: any, state: EditorState): ResizeState {
598
- this.spec.props.nodeViews[
599
- tableNodeTypes(state.schema).table.name
600
- ] = createTableView;
598
+ if (!this.spec.props.nodeViews['table']) {
599
+ this.spec.props.nodeViews[tableNodeTypes(state.schema).table.name] =
600
+ createTableView;
601
+ }
601
602
  return new ResizeState(-1, null);
602
603
  },
603
604
  apply(tr: Transform, prev: EditorState): EditorState {
@@ -1,6 +1,7 @@
1
1
  // @flow
2
- import { EditorState } from 'prosemirror-state';
2
+ import { EditorState, PluginView } from 'prosemirror-state';
3
3
  import { EditorView } from 'prosemirror-view';
4
+ import { Node } from 'prosemirror-model';
4
5
  import * as React from 'react';
5
6
 
6
7
  import CommandMenuButton from './CommandMenuButton';
@@ -12,6 +13,8 @@ import './czi-table-cell-menu.css';
12
13
  type Props = {
13
14
  editorState: EditorState,
14
15
  editorView: EditorView,
16
+ pluginView: PluginView,
17
+ actionNode: Node,
15
18
  };
16
19
 
17
20
  class TableCellMenu extends React.PureComponent<any, any> {
@@ -20,11 +23,21 @@ class TableCellMenu extends React.PureComponent<any, any> {
20
23
  props: Props;
21
24
 
22
25
  render(): React.Element<any> {
23
- const { editorState, editorView } = this.props;
26
+ const { editorState, editorView, pluginView, actionNode } = this.props;
27
+ let cmdGrps = null;
28
+
29
+ if (pluginView.getMenu) {
30
+ cmdGrps = pluginView.getMenu(editorState, actionNode, TABLE_COMMANDS_GROUP);
31
+ }
32
+
33
+ if (!cmdGrps) {
34
+ cmdGrps = TABLE_COMMANDS_GROUP;
35
+ }
36
+
24
37
  return (
25
38
  <CommandMenuButton
26
39
  className="czi-table-cell-menu"
27
- commandGroups={TABLE_COMMANDS_GROUP}
40
+ commandGroups={cmdGrps}
28
41
  dispatch={editorView.dispatch}
29
42
  editorState={editorState}
30
43
  editorView={editorView}
@@ -4,8 +4,11 @@ import { fromHTMlElement } from '@modusoperandi/licit-ui-commands';
4
4
 
5
5
  export default function isElementFullyVisible(el: HTMLElement): boolean {
6
6
  const { x, y, w, h } = fromHTMlElement(el);
7
+ // to handle the rounded border scenario.
8
+ const factor = '10px' === el.style.borderRadius ? 3 : 1;
7
9
  // Only checks the top-left point.
8
- const nwEl = w && h ? el.ownerDocument.elementFromPoint(x + 1, y + 1) : null;
10
+ const nwEl =
11
+ w && h ? el.ownerDocument.elementFromPoint(x + factor, y + factor) : null;
9
12
 
10
13
  if (!nwEl) {
11
14
  return false;
package/webpack.config.js CHANGED
@@ -60,15 +60,7 @@ var options = {
60
60
  },
61
61
  {
62
62
  test: /\.(woff(2)?|ttf|otf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
63
- use: [
64
- {
65
- loader: 'file-loader',
66
- options: {
67
- name: '[name].[ext]',
68
- outputPath: 'fonts/',
69
- },
70
- },
71
- ],
63
+ type: 'asset/resource',
72
64
  },
73
65
  {
74
66
  test: /\.css$/,
@@ -93,10 +85,8 @@ var options = {
93
85
  // jQuery (for Mathquill)
94
86
  'window.jQuery': 'jquery',
95
87
  }),
96
- // type checker
97
- // ...(isDev
98
- // ? [new FlowWebpackPlugin({ flowArgs: ['--show-all-errors'] })]
99
- // : []),
88
+ // type checker
89
+ ... (isDev ? [new FlowWebpackPlugin({flowArgs: ['--show-all-errors']})] : []),
100
90
  // clean the web folder
101
91
  new CleanWebpackPlugin(),
102
92
  // expose and write the allowed env vars on the compiled bundle