├── .czrc.json
├── nodemon.json
├── .prettierrc
├── changelog.config.js
├── src
├── img
│ └── favicon-32x32.png
├── html
│ └── index.html
└── js
│ └── app.js
├── docs
└── images
│ ├── cwrcwriter-high-level-diagram.png
│ ├── oauth.svg
│ └── cwrc-gitwriter-overview.svg
├── .env-cmdrc.json
├── .dockerignore
├── Dockerfile.dev
├── server
├── index.mjs
├── server.mjs
└── dev
│ └── dev.mjs
├── ecosystem.config.js
├── Dockerfile
├── .eslintrc
├── babel.config.json
├── .gitignore
├── issue_template.md
├── webpack.dev.js
├── webpack.prod.js
├── .github
└── workflows
│ ├── main.yml
│ ├── next.yml
│ └── development.yml
├── package.json
├── webpack.common.js
├── config
└── config.json
└── README.md
/.czrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "path": "git-cz"
3 | }
--------------------------------------------------------------------------------
/nodemon.json:
--------------------------------------------------------------------------------
1 | {
2 | "watch": ["server"]
3 | }
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 100,
3 | "singleQuote": true
4 | }
--------------------------------------------------------------------------------
/changelog.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | maxMessageLength: 110,
3 | };
4 |
--------------------------------------------------------------------------------
/src/img/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cwrc/CWRC-GitWriter/HEAD/src/img/favicon-32x32.png
--------------------------------------------------------------------------------
/docs/images/cwrcwriter-high-level-diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cwrc/CWRC-GitWriter/HEAD/docs/images/cwrcwriter-high-level-diagram.png
--------------------------------------------------------------------------------
/.env-cmdrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "development": {
3 | "NODE_ENV": "development"
4 | },
5 | "production": {
6 | "NODE_ENV": "production"
7 | }
8 | }
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | .git
2 |
3 | # Coverage directory used by tools like istanbul
4 | coverage
5 |
6 | # Dependency directories
7 | node_modules
8 |
9 | # build
10 |
--------------------------------------------------------------------------------
/Dockerfile.dev:
--------------------------------------------------------------------------------
1 | # CWRC-GitWriter
2 |
3 | FROM node:14.15.1
4 |
5 | WORKDIR /apps/CWRC-GitWriter
6 |
7 | COPY . .
8 |
9 | CMD ["npm", "run", "middleware-server-dev"]
10 |
11 | EXPOSE 3000
--------------------------------------------------------------------------------
/server/index.mjs:
--------------------------------------------------------------------------------
1 | import { app } from './server.mjs';
2 | const port = process.env.PORT || 3000;
3 |
4 | // isDev();
5 |
6 | app.listen(port, () => {
7 | console.log(`Server started on port ${port}`);
8 | });
9 |
--------------------------------------------------------------------------------
/ecosystem.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | apps: [{
3 | name: 'cwrc-gitwriter',
4 | script: './server/index.mjs',
5 | args: '--no-daemon',
6 | env: { NODE_ENV: 'production' },
7 | env_production: { NODE_ENV: 'production' },
8 | }],
9 | };
10 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | # CWRC-GitWriter
2 |
3 | FROM node:14.15.1
4 |
5 | WORKDIR /apps/CWRC-GitWriter
6 |
7 | RUN npm install pm2 -g
8 |
9 | COPY . .
10 |
11 | RUN npm install && \
12 | npm run build
13 |
14 | # CMD ["pm2", "start", "./server/server.js", "--no-daemon"]
15 | CMD ["pm2-runtime", "ecosystem.config.js"]
16 |
17 | EXPOSE 3000
18 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "es6": true,
5 | "jquery": true,
6 | "node": true
7 | },
8 | "extends": ["eslint:recommended", "prettier"],
9 | "globals": {
10 | "Atomics": "readonly",
11 | "SharedArrayBuffer": "readonly"
12 | },
13 | "parser": "@babel/eslint-parser",
14 | "parserOptions": {
15 | "allowImportExportEverywhere": true,
16 | "ecmaVersion": 2020,
17 | "sourceType": "module"
18 | },
19 | "rules": {
20 | "no-unused-vars": 2
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/server/server.mjs:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import { fileURLToPath } from 'url';
3 | import express from 'express';
4 |
5 | const __filename = fileURLToPath(import.meta.url);
6 | const __dirname = path.dirname(__filename);
7 | const publicPath = path.join(__dirname, '..', 'build');
8 |
9 | export const app = express();
10 |
11 | // export const isDev = async () => {
12 | // if (process.env.NODE_ENV === 'development') {
13 | // const { devTools } = await import('./dev/dev.mjs');
14 | // devTools(app);
15 | // }
16 | // };
17 |
18 | //make content available
19 | app.use(express.static(publicPath));
20 |
--------------------------------------------------------------------------------
/babel.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "@babel/preset-env",
4 | "@babel/preset-react"
5 | ],
6 | "plugins": [
7 | "@babel/plugin-proposal-class-properties"
8 | ],
9 | "overrides": [{
10 | "include": [
11 | "./node_modules/cwrc-writer-base/node_modules/tinymce/tinymce.js",
12 | "./node_modules/cwrc-writer-base/node_modules/react-dom/cjs/react-dom.development.js",
13 | "./node_modules/cwrc-writer-base/node_modules/openseadragon/build/openseadragon/openseadragon.js",
14 | "./node_modules/cwrc-git-dialogs/node_modules/react-dom/cjs/react-dom.development.js"
15 | ],
16 | "compact": true
17 | }]
18 | }
--------------------------------------------------------------------------------
/src/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | CWRC-Writer
7 |
8 |
9 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/server/dev/dev.mjs:
--------------------------------------------------------------------------------
1 | import webpack from 'webpack';
2 | import webpackDevMiddleware from 'webpack-dev-middleware';
3 | import webpackHotMiddleware from 'webpack-hot-middleware';
4 |
5 | import config from '../../webpack.dev.js';
6 |
7 | export const devTools = (app) => {
8 | //webpack middleware and hot reload
9 | config.entry.app.unshift('webpack-hot-middleware/client?reload=true&timeout=1000'); //Auto-reloading when webpack detects any changes
10 | config.plugins.push(new webpack.HotModuleReplacementPlugin()); //Add HMR plugin
11 | const compiler = webpack(config);
12 | app.use(
13 | webpackDevMiddleware(compiler, {
14 | publicPath: config.output.publicPath,
15 | writeToDisk: true,
16 | })
17 | );
18 |
19 | // Enable "webpack-hot-middleware"
20 | app.use(webpackHotMiddleware(compiler));
21 |
22 | console.log('Dev Server is online!');
23 | };
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 |
6 | # Runtime data
7 | pids
8 | *.pid
9 | *.seed
10 |
11 | /dist
12 |
13 | # Directory for instrumented libs generated by jscoverage/JSCover
14 | lib-cov
15 |
16 | .idea
17 |
18 | # Coverage directory used by tools like istanbul
19 | coverage
20 |
21 | # nyc test coverage
22 | .nyc_output
23 |
24 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
25 | .grunt
26 |
27 | # node-waf configuration
28 | .lock-wscript
29 |
30 | # Compiled binary addons (http://nodejs.org/api/addons.html)
31 | build/Release
32 |
33 | # Dependency directories
34 | node_modules
35 | jspm_packages
36 |
37 | # Optional npm cache directory
38 | .npm
39 |
40 | # Optional REPL history
41 | .node_repl_history
42 |
43 | build
44 | /bin/
45 | /classes/
46 | .classpath
47 | .settings
48 |
49 | .DS_Store
50 |
51 | /config/config.json
--------------------------------------------------------------------------------
/issue_template.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Expected Behaviour
4 |
5 |
6 |
7 | # Current Behaviour
8 |
9 |
10 |
11 | # Possible Solution
12 |
13 |
14 |
15 | # Steps to Reproduce (for bugs)
16 |
17 |
18 |
19 |
20 | 1.
21 | 2.
22 | 3.
23 | 4.
24 |
25 | ## Your Environment
26 |
27 | * URL:
28 |
29 | * Browser Name:
30 |
31 | * Operating System:
32 |
33 | * Attachements:
34 |
35 |
36 | * CWRC user name if submitting an issue for the CWRC research space, or the Github username if using GitWriter.
37 |
--------------------------------------------------------------------------------
/webpack.dev.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const webpack = require('webpack');
3 | const { merge } = require('webpack-merge');
4 |
5 | const common = require('./webpack.common.js');
6 |
7 | module.exports = merge(common, {
8 | // devtool: 'inline-cheap-module-source-map',
9 | devtool: false,
10 | cache: true,
11 | performance: { hints: false },
12 | output: { pathinfo: true },
13 | optimization: {
14 | namedModules: true,
15 | namedChunks: true,
16 | nodeEnv: 'development',
17 | flagIncludedChunks: false,
18 | occurrenceOrder: false,
19 | sideEffects: false,
20 | usedExports: false,
21 | concatenateModules: false,
22 | noEmitOnErrors: false,
23 | checkWasmTypes: false,
24 | minimize: false,
25 | removeAvailableModules: false,
26 | },
27 | plugins: [
28 | new webpack.NamedModulesPlugin(),
29 | new webpack.NamedChunksPlugin(),
30 | new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('development') }),
31 | new webpack.EvalSourceMapDevToolPlugin({
32 | module: true,
33 | columns: true,
34 | exclude: [
35 | // /jquery/,
36 | // /tinymce.js/,
37 | // /bootstrap/,
38 | /react/,
39 | /openseadragon/,
40 | /moment/,
41 | ],
42 | }),
43 | ],
44 | devServer: {
45 | contentBase: path.join(__dirname, 'build'),
46 | port: 3000,
47 | host: 'localhost',
48 | },
49 | });
50 |
--------------------------------------------------------------------------------
/webpack.prod.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack');
2 | const { merge } = require('webpack-merge');
3 | const TerserPlugin = require('terser-webpack-plugin');
4 | const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
5 |
6 | const common = require('./webpack.common.js');
7 |
8 | module.exports = merge(common, {
9 | devtool: false,
10 | performance: { hints: 'warning' },
11 | output: { pathinfo: false },
12 | optimization: {
13 | namedModules: false,
14 | namedChunks: false,
15 | nodeEnv: 'production',
16 | flagIncludedChunks: true,
17 | occurrenceOrder: true,
18 | sideEffects: true,
19 | usedExports: true,
20 | concatenateModules: true,
21 | noEmitOnErrors: true,
22 | checkWasmTypes: true,
23 | minimize: true,
24 | minimizer: [
25 | new TerserPlugin({
26 | cache: true, //default
27 | parallel: true, // default
28 | sourceMap: true, //use sourceMapDevToolPlugin
29 | }),
30 | new OptimizeCSSAssetsPlugin({}),
31 | ],
32 | },
33 | plugins: [
34 | new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('production') }),
35 | new webpack.optimize.ModuleConcatenationPlugin(),
36 | new webpack.NoEmitOnErrorsPlugin(),
37 | new webpack.SourceMapDevToolPlugin({
38 | filename: 'js/app.js.map',
39 | module: true,
40 | columns: true,
41 | noSources: false,
42 | namespace: '',
43 | exclude: [/jquery/, /tinymce.js/, /bootstrap/, /react/, /openseadragon/, /moment/],
44 | }),
45 | ],
46 | });
47 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: CI (main)
2 |
3 | # Controls when the workflow will run
4 | on:
5 | # Triggers the workflow on push or pull request events but only for the master branch
6 | push:
7 | branches: [ master, main ]
8 | tags:
9 | - 'v*.*.*'
10 |
11 | # Allows you to run this workflow manually from the Actions tab
12 | workflow_dispatch:
13 |
14 | jobs:
15 | docker:
16 | runs-on: ubuntu-latest
17 | steps:
18 | -
19 | name: Checkout
20 | uses: actions/checkout@v2
21 | -
22 | name: Docker meta
23 | id: meta
24 | uses: docker/metadata-action@v3
25 | with:
26 | # list of Docker images to use as base name for tags
27 | # assumes image named after owner/repository
28 | images: |
29 | ${{ github.repository }}
30 | # generate Docker tags based on the following events/attributes
31 | tags: |
32 | type=raw,value=latest
33 | type=schedule
34 | type=ref,event=branch
35 | type=ref,event=pr
36 | type=semver,pattern={{version}}
37 | type=semver,pattern={{major}}.{{minor}}
38 | type=semver,pattern={{major}}
39 | type=sha
40 | -
41 | name: Set up QEMU
42 | uses: docker/setup-qemu-action@v1
43 | -
44 | name: Set up Docker Buildx
45 | uses: docker/setup-buildx-action@v1
46 | -
47 | name: Login to DockerHub
48 | if: github.event_name != 'pull_request'
49 | uses: docker/login-action@v1
50 | with:
51 | username: ${{ secrets.DOCKERHUB_USERNAME }}
52 | password: ${{ secrets.DOCKERHUB_TOKEN }}
53 | -
54 | name: Build and push
55 | uses: docker/build-push-action@v2
56 | with:
57 | context: .
58 | push: ${{ github.event_name != 'pull_request' }}
59 | tags: ${{ steps.meta.outputs.tags }}
60 | labels: ${{ steps.meta.outputs.labels }}
61 |
62 |
--------------------------------------------------------------------------------
/.github/workflows/next.yml:
--------------------------------------------------------------------------------
1 | # Workflow to align with special naming of `next` branch to DockerHub `dev-next` convention
2 | # ToDo: stopgap - find better way to map Git branch to custom tag name (in ways not supported by docker/metadata-action)
3 |
4 | name: CI (next branch)
5 |
6 | # Controls when the workflow will run
7 | on:
8 | # Triggers the workflow on push or pull request events but only for the master branch
9 | push:
10 | branches: [ next ]
11 | tags:
12 | - 'v*.*.*'
13 |
14 | # Allows you to run this workflow manually from the Actions tab
15 | workflow_dispatch:
16 |
17 | jobs:
18 | docker:
19 | runs-on: ubuntu-latest
20 | steps:
21 | -
22 | name: Checkout
23 | uses: actions/checkout@v2
24 | -
25 | name: Docker meta
26 | id: meta
27 | uses: docker/metadata-action@v3
28 | with:
29 | # list of Docker images to use as base name for tags
30 | # assumes image named after owner/repository
31 | images: |
32 | ${{ github.repository }}
33 | # generate Docker tags based on the following events/attributes
34 | tags: |
35 | type=raw,value=dev-next
36 | type=ref,event=branch
37 | type=sha
38 | -
39 | name: Set up QEMU
40 | uses: docker/setup-qemu-action@v1
41 | -
42 | name: Set up Docker Buildx
43 | uses: docker/setup-buildx-action@v1
44 | -
45 | name: Login to DockerHub
46 | if: github.event_name != 'pull_request'
47 | uses: docker/login-action@v1
48 | with:
49 | username: ${{ secrets.DOCKERHUB_USERNAME }}
50 | password: ${{ secrets.DOCKERHUB_TOKEN }}
51 | -
52 | name: Build and push
53 | uses: docker/build-push-action@v2
54 | with:
55 | context: .
56 | push: ${{ github.event_name != 'pull_request' }}
57 | tags: ${{ steps.meta.outputs.tags }}
58 | labels: ${{ steps.meta.outputs.labels }}
59 |
60 |
--------------------------------------------------------------------------------
/.github/workflows/development.yml:
--------------------------------------------------------------------------------
1 | # Workflow to align with special naming of `development` branch to DockerHub `dev-latest` convention
2 | # ToDo: stopgap - find better way to map Git branch to custom tag name (in ways not supported by docker/metadata-action)
3 |
4 | name: CI (development branch)
5 |
6 | # Controls when the workflow will run
7 | on:
8 | # Triggers the workflow on push or pull request events but only for the master branch
9 | push:
10 | branches: [ development ]
11 | tags:
12 | - 'v*.*.*'
13 |
14 | # Allows you to run this workflow manually from the Actions tab
15 | workflow_dispatch:
16 |
17 | jobs:
18 | docker:
19 | runs-on: ubuntu-latest
20 | steps:
21 | -
22 | name: Checkout
23 | uses: actions/checkout@v2
24 | -
25 | name: Docker meta
26 | id: meta
27 | uses: docker/metadata-action@v3
28 | with:
29 | # list of Docker images to use as base name for tags
30 | # assumes image named after owner/repository
31 | images: |
32 | ${{ github.repository }}
33 | # generate Docker tags based on the following events/attributes
34 | tags: |
35 | type=raw,value=dev-latest
36 | type=ref,event=branch
37 | type=sha
38 | -
39 | name: Set up QEMU
40 | uses: docker/setup-qemu-action@v1
41 | -
42 | name: Set up Docker Buildx
43 | uses: docker/setup-buildx-action@v1
44 | -
45 | name: Login to DockerHub
46 | if: github.event_name != 'pull_request'
47 | uses: docker/login-action@v1
48 | with:
49 | username: ${{ secrets.DOCKERHUB_USERNAME }}
50 | password: ${{ secrets.DOCKERHUB_TOKEN }}
51 | -
52 | name: Build and push
53 | uses: docker/build-push-action@v2
54 | with:
55 | context: .
56 | push: ${{ github.event_name != 'pull_request' }}
57 | tags: ${{ steps.meta.outputs.tags }}
58 | labels: ${{ steps.meta.outputs.labels }}
59 |
60 |
--------------------------------------------------------------------------------
/src/js/app.js:
--------------------------------------------------------------------------------
1 | import dbpedia from 'dbpedia-entity-lookup';
2 | import geonames from 'geonames-entity-lookup';
3 | import getty from 'getty-entity-lookup';
4 | import lgpn from 'lgpn-entity-lookup';
5 | import viaf from 'viaf-entity-lookup';
6 | import wikidata from 'wikidata-entity-lookup';
7 |
8 | import GitStorageDialogs from 'cwrc-git-dialogs';
9 | import EntityLookupDialogs from 'cwrc-public-entity-dialogs';
10 |
11 | import CWRCWriter from 'cwrc-writer-base';
12 |
13 | EntityLookupDialogs.showNoLinkButton(true);
14 | EntityLookupDialogs.showCreateNewButton(false);
15 | EntityLookupDialogs.showEditButton(false);
16 | EntityLookupDialogs.registerEntitySources({
17 | rs: new Map().set('viaf', viaf).set('wikidata', wikidata).set('dbpedia', dbpedia),
18 | person: new Map()
19 | .set('viaf', viaf)
20 | .set('wikidata', wikidata)
21 | .set('getty', getty)
22 | .set('dbpedia', dbpedia)
23 | .set('lgpn', lgpn),
24 | place: new Map()
25 | .set('geonames', geonames)
26 | .set('viaf', viaf)
27 | .set('dbpedia', dbpedia)
28 | .set('wikidata', wikidata),
29 | organization: new Map().set('viaf', viaf).set('wikidata', wikidata).set('dbpedia', dbpedia),
30 | title: new Map().set('viaf', viaf).set('wikidata', wikidata).set('dbpedia', dbpedia),
31 | });
32 |
33 | // if (process.env.NODE_ENV === 'development') {
34 | // GitStorageDialogs.setServerURL('http://localhost:3000/github');
35 | // } else {
36 | GitStorageDialogs.setServerURL('./github');
37 | // }
38 |
39 | const init = async () => {
40 | const configRequest = await fetch('./config/config.json').catch((err) => {
41 | console.log(err);
42 | });
43 | const config = await configRequest.json();
44 |
45 | // if (process.env.NODE_ENV === 'development') {
46 | // config.schema.schemaProxyUrl = 'http://localhost:3000';
47 | // }
48 |
49 | config.container = 'cwrcWriterContainer';
50 | config.modules = {
51 | west: [
52 | { id: 'structure', title: 'Markup' },
53 | { id: 'entities', title: 'Entities' },
54 | {
55 | id: 'nerve',
56 | title: 'NERVE',
57 | config: { nerveUrl: config.nerveUrl },
58 | },
59 | ],
60 | south: [
61 | { id: 'selection', title: 'Selection' },
62 | {
63 | id: 'validation',
64 | title: 'Validation',
65 | config: { validationUrl: config.validationUrl },
66 | },
67 | ],
68 | east: [{ id: 'imageViewer', title: 'Image Viewer' }],
69 | };
70 | config.entityLookupDialogs = EntityLookupDialogs;
71 | config.storageDialogs = GitStorageDialogs;
72 |
73 | //setup geonames
74 | if (config.lookups.geonames.username && config.lookups.geonames.username !== '') {
75 | geonames.credentials.username = config.lookups.geonames.username;
76 | }
77 |
78 | const writer = new CWRCWriter(config);
79 |
80 | window.writer = writer;
81 |
82 | writer.event('writerInitialized').subscribe(() => {
83 | writer.showLoadDialog();
84 | });
85 | };
86 |
87 | init();
88 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cwrc-git-writer",
3 | "version": "0.0.0",
4 | "description": "xml editing and rdf annotation using github as document store",
5 | "keywords": [
6 | "xml",
7 | "rdf",
8 | "editor",
9 | "annotation"
10 | ],
11 | "homepage": "https://github.com/cwrc/CWRC-GitWriter",
12 | "bugs": {
13 | "url": "https://github.com/cwrc/CWRC-GitWriter/issues"
14 | },
15 | "license": "GPL-2.0",
16 | "contributors": [
17 | "Andrew MacDonald ",
18 | "James Chartrand ",
19 | "Luciano Frizzera "
20 | ],
21 | "repository": {
22 | "type": "git",
23 | "url": "https://github.com/cwrc/CWRC-GitWriter.git"
24 | },
25 | "scripts": {
26 | "start": "env-cmd -e production node ./server/server.js",
27 | "middleware-server-dev": "env-cmd -e development nodemon -L ./server/index.mjs",
28 | "dev-server": "npm run cwrc-writer-editor-css-dev & webpack-dev-server --config webpack.dev.js",
29 | "webpack-dev": "npm run build-cwrc-writer-base && webpack --config webpack.dev.js --debug=true --display-error-details=true",
30 | "webpack-dev-watch": "env-cmd -e development npm run cwrc-writer-editor-css-dev & webpack --config webpack.dev.js --debug=true --display-error-details=true --watch",
31 | "cwrc-writer-editor-css-dev": "cd \"node_modules/cwrc-writer-base\" && npm run build-editor-css-dev",
32 | "build": "npm run build-cwrc-writer-base && npm run webpack-prod && npm run mockup-ui:copy-files",
33 | "build-cwrc-writer-base": "cd \"node_modules/cwrc-writer-base\" && npm run build",
34 | "webpack-prod": "webpack --config webpack.prod.js",
35 | "stats": "webpack --profile --json > stats.json",
36 | "analyzer": "webpack-bundle-analyzer stats.json",
37 | "mockup-ui:copy-files": "copyfiles -u 1 mockup-ui/* mockup-ui/**/* build/mockup-ui",
38 | "cm": "git-cz"
39 | },
40 | "dependencies": {
41 | "cwrc-git-dialogs": "^4.0.0",
42 | "cwrc-public-entity-dialogs": "^4.0.0",
43 | "cwrc-writer-base": "^8.2.0",
44 | "dbpedia-entity-lookup": "^2.0.0",
45 | "env-cmd": "^10.1.0",
46 | "express": "^4.18.1",
47 | "geonames-entity-lookup": "^2.1.0",
48 | "getty-entity-lookup": "^2.3.2",
49 | "lgpn-entity-lookup": "^2.2.0",
50 | "viaf-entity-lookup": "^2.1.0",
51 | "wikidata-entity-lookup": "^2.1.0"
52 | },
53 | "devDependencies": {
54 | "@babel/core": "^7.19.3",
55 | "@babel/eslint-parser": "^7.19.1",
56 | "@babel/plugin-proposal-class-properties": "^7.18.6",
57 | "@babel/plugin-syntax-dynamic-import": "^7.8.3",
58 | "@babel/plugin-transform-react-jsx": "^7.19.0",
59 | "@babel/plugin-transform-runtime": "^7.19.1",
60 | "@babel/preset-env": "^7.19.3",
61 | "@babel/preset-react": "^7.18.6",
62 | "@babel/runtime-corejs2": "^7.19.2",
63 | "babel-loader": "^8.2.5",
64 | "clean-webpack-plugin": "^3.0.0",
65 | "commitizen": "^4.2.5",
66 | "copy-webpack-plugin": "^6.4.1",
67 | "copyfiles": "^2.4.1",
68 | "css-loader": "^4.3.0",
69 | "eslint": "^7.32.0",
70 | "eslint-config-prettier": "^8.5.0",
71 | "eslint-plugin-prettier": "^3.4.1",
72 | "file-loader": "^6.2.0",
73 | "git-cz": "^4.9.0",
74 | "html-webpack-externals-plugin": "^3.8.0",
75 | "html-webpack-plugin": "^4.5.2",
76 | "image-webpack-loader": "^7.0.1",
77 | "less": "^4.1.3",
78 | "less-loader": "^7.3.0",
79 | "less-watch-compiler": "^1.16.3",
80 | "mini-css-extract-plugin": "^0.11.3",
81 | "nodemon": "^2.0.20",
82 | "optimize-css-assets-webpack-plugin": "^5.0.8",
83 | "prettier": "^2.7.1",
84 | "style-loader": "^1.3.0",
85 | "svg-inline-loader": "^0.8.2",
86 | "terser-webpack-plugin": "^4.2.3",
87 | "url-loader": "^4.1.1",
88 | "webpack": "^4.46.0",
89 | "webpack-bundle-analyzer": "^3.9.0",
90 | "webpack-cli": "^3.3.12",
91 | "webpack-dev-middleware": "^3.7.3",
92 | "webpack-dev-server": "^3.11.3",
93 | "webpack-hot-middleware": "^2.25.2",
94 | "webpack-merge": "^5.4.0",
95 | "webpackbar": "^4.0.0"
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/webpack.common.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const { CleanWebpackPlugin } = require('clean-webpack-plugin');
3 | const CopyWebpackPlugin = require('copy-webpack-plugin');
4 | const HtmlWebpackPlugin = require('html-webpack-plugin');
5 | const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin');
6 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
7 | const WebpackBar = require('webpackbar');
8 |
9 | module.exports = {
10 | entry: {
11 | app: ['./src/js/app.js'],
12 | },
13 | mode: 'none', // all mode defaults for dev and prod and set in the respective configs
14 | output: {
15 | filename: 'js/[name].js',
16 | path: path.resolve(__dirname, 'build'),
17 | publicPath: './',
18 | },
19 | plugins: [
20 | new CleanWebpackPlugin({ cleanStaleWebpackAssets: false }),
21 | new CopyWebpackPlugin({
22 | patterns: [{
23 | //copy config.json
24 | context: 'config/',
25 | from: '*',
26 | to: 'config',
27 | },
28 | {
29 | //copy images for GitWriter (favicon)
30 | context: 'src/img',
31 | from: '*',
32 | to: 'img',
33 | },
34 | {
35 | //copy images from Writer-Base
36 | context: 'node_modules/cwrc-writer-base/src/img',
37 | from: '*',
38 | to: 'img',
39 | },
40 | {
41 | //Copy pre-compiled CSS required by tinyMCE
42 | context: 'node_modules/cwrc-writer-base/src/css/tinymce/',
43 | from: '*.css',
44 | to: 'css/tinymce',
45 | },
46 | {
47 | //Copy pre-compiled CSS to stylize the editor (must be recompiled after each change)
48 | context: 'node_modules/cwrc-writer-base/src/css/build/',
49 | from: 'editor.css',
50 | to: 'css/editor.css',
51 | toType: 'file',
52 | }],
53 | }),
54 | new HtmlWebpackPlugin({
55 | template: 'src/html/index.html',
56 | inject: 'body',
57 | }),
58 | new MiniCssExtractPlugin({
59 | filename: '/css/[name].css',
60 | chunkFilename: '/css/[id].css',
61 | }),
62 | new HtmlWebpackExternalsPlugin({
63 | externals: [{
64 | module: 'rdflib',
65 | global: '$rdf',
66 | entry: {
67 | path: 'rdflib.min.js',
68 | cwpPatternConfig: {
69 | context: path.resolve(
70 | __dirname,
71 | 'node_modules/cwrc-writer-base/src/lib'
72 | ),
73 | },
74 | },
75 | }],
76 | outputPath: 'js',
77 | }),
78 | new WebpackBar({ color: '#0099ff' }),
79 | ],
80 | module: {
81 | rules: [
82 | {
83 | test: /\.(js|jsx)$/,
84 | use: [{
85 | loader: 'babel-loader',
86 | options: {
87 | sourceType: 'unambiguous',
88 | presets: ['@babel/preset-env', '@babel/preset-react'],
89 | plugins: [
90 | '@babel/plugin-proposal-class-properties', [
91 | '@babel/plugin-transform-runtime', {
92 | absoluteRuntime: false,
93 | corejs: false,
94 | helpers: false,
95 | regenerator: true,
96 | useESModules: false,
97 | },
98 | ],
99 | ],
100 | },
101 | }],
102 | },
103 | {
104 | test: /\.(le|c)ss$/,
105 | use: [{
106 | loader: MiniCssExtractPlugin.loader,
107 | options: {
108 | // you can specify a publicPath here
109 | // by default it uses publicPath in webpackOptions.output
110 | publicPath: '../',
111 | esModule: true,
112 | hmr: process.env.NODE_ENV === 'development', //allows to use this plugin in DEV
113 | },
114 | },
115 | { loader: 'css-loader' /* translates CSS into CommonJS*/ },
116 | {
117 | loader: 'less-loader', // compiles Less to CSS //more: https://itnext.io/webpack-and-less-a75e04aaf528
118 | options: {
119 | lessOptions: {
120 | relativeUrls: 'local', //https://github.com/webpack-contrib/less-loader/issues/109,
121 | globalVars: { parentId: '#cwrcWriterContainer' },
122 | },
123 | },
124 | }],
125 | },
126 | {
127 | test: /\.(woff(2)?|ttf|eot)(\?v=\d+\.\d+\.\d+)?$/,
128 | enforce: 'pre', // preload the jshint loader
129 | use: [{
130 | loader: 'url-loader',
131 | options: {
132 | query: { limit: 25000 },
133 | },
134 | }],
135 | },
136 | {
137 | test: /\.(png|jpg|jpeg|gif)$/i,
138 | enforce: 'pre', // preload the jshint loader
139 | // exclude: /node_modules/, // exclude any and all files in the node_modules folder
140 | use: [{
141 | loader: 'file-loader',
142 | options: {
143 | name: '[name].[ext]',
144 | outputPath: 'img',
145 | },
146 | },
147 | {
148 | loader: 'image-webpack-loader',
149 | options: { disable: true /* webpack@2.x and newer */ },
150 | }],
151 | },
152 | {
153 | test: /\.svg$/,
154 | loader: 'svg-inline-loader',
155 | options: {
156 | removeSVGTagAttrs: false
157 | }
158 | },
159 | ],
160 | },
161 | optimization: {
162 | splitChunks: {
163 | cacheGroups: {
164 | commons: {
165 | // don't include cwrc or entity lookup modules in vendor bundle
166 | test: /[\\/]node_modules[\\/](?!.*(cwrc|entity-lookup))/,
167 | name: 'vendor',
168 | chunks: 'all',
169 | },
170 | styles: {
171 | name: 'styles',
172 | test: /\.css$/,
173 | chunks: 'all',
174 | enforce: true,
175 | },
176 | },
177 | },
178 | },
179 | resolve: {
180 | extensions: ['*', '.js', '.jsx'],
181 | symlinks: false,
182 | },
183 | node: { fs: 'empty' },
184 | };
185 |
--------------------------------------------------------------------------------
/config/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "cwrcRootUrl": "",
3 | "nerveUrl": "https://localhost/nerve/",
4 | "validationUrl": "https://localhost/validator/validate.html",
5 | "helpUrl": "https://cwrc.ca/CWRC-Writer_Documentation/",
6 | "lookups": {
7 | "geonames": {
8 | "username": ""
9 | }
10 | },
11 | "schema": {
12 | "proxyXmlEndpoint": "./schema/xml/",
13 | "proxyCssEndpoint": "./schema/css/",
14 | "schemas": [{
15 | "id": "cwrcTeiLite",
16 | "name": "CWRC TEI Lite",
17 | "schemaMappingsId": "tei",
18 | "xmlUrl": [
19 | "https://cwrc.ca/schemas/cwrc_tei_lite.rng",
20 | "https://raw.githubusercontent.com/cwrc/CWRC-Schema/master/schemas/cwrc_tei_lite.rng"
21 | ],
22 | "cssUrl": [
23 | "https://cwrc.ca/templates/css/tei.css",
24 | "https://raw.githubusercontent.com/cwrc/CWRC-Schema/master/templates/css/tei.css"
25 | ]
26 | },
27 | {
28 | "id": "orlando",
29 | "name": "Orlando Schema",
30 | "schemaMappingsId": "orlando",
31 | "xmlUrl": [
32 | "https://cwrc.ca/schemas/orlando_entry.rng",
33 | "https://raw.githubusercontent.com/cwrc/CWRC-Schema/master/schemas/orlando_entry.rng"
34 | ],
35 | "cssUrl": [
36 | "https://cwrc.ca/templates/css/orlando_v2_cwrc-writer.css",
37 | "https://raw.githubusercontent.com/cwrc/CWRC-Schema/master/templates/css/orlando_v2_cwrc-writer.css"
38 | ]
39 | },
40 | {
41 | "id": "event",
42 | "name": "Events Schema",
43 | "schemaMappingsId": "orlando",
44 | "xmlUrl": [
45 | "https://cwrc.ca/schemas/orlando_event.rng",
46 | "https://raw.githubusercontent.com/cwrc/CWRC-Schema/master/schemas/orlando_event.rng"
47 | ],
48 | "cssUrl": [
49 | "https://cwrc.ca/templates/css/orlando_v2_cwrc-writer.css",
50 | "https://raw.githubusercontent.com/cwrc/CWRC-Schema/master/templates/css/orlando_v2_cwrc-writer.css"
51 | ]
52 | },
53 | {
54 | "id": "cwrcEntry",
55 | "name": "CWRC Entry Schema",
56 | "schemaMappingsId": "cwrcEntry",
57 | "xmlUrl": [
58 | "https://cwrc.ca/schemas/cwrc_entry.rng",
59 | "https://raw.githubusercontent.com/cwrc/CWRC-Schema/master/schemas/cwrc_entry.rng"
60 | ],
61 | "cssUrl": [
62 | "https://cwrc.ca/templates/css/cwrc.css",
63 | "https://raw.githubusercontent.com/cwrc/CWRC-Schema/master/templates/css/cwrc.css"
64 | ]
65 | },
66 | {
67 | "id": "epidoc",
68 | "name": "EpiDoc Schema",
69 | "schemaMappingsId": "tei",
70 | "xmlUrl": [
71 | "http://www.stoa.org/epidoc/schema/latest/tei-epidoc.rng",
72 | "https://cwrc.ca/epidoc/schema/latest/tei-epidoc.rng"
73 | ],
74 | "cssUrl": [
75 | "https://cwrc.ca/templates/css/tei.css"
76 | ]
77 | },
78 | {
79 | "id": "teiAll",
80 | "name": "TEI All Schema",
81 | "schemaMappingsId": "tei",
82 | "xmlUrl": [
83 | "https://www.tei-c.org/release/xml/tei/custom/schema/relaxng/tei_all.rng",
84 | "https://jenkins.tei-c.org/job/TEIP5/lastSuccessfulBuild/artifact/P5/release/xml/tei/custom/schema/relaxng/tei_all.rng"
85 | ],
86 | "cssUrl": [
87 | "https://cwrc.ca/templates/css/tei.css"
88 | ]
89 | },
90 | {
91 | "id": "teiDrama",
92 | "name": "TEI Drama Schema",
93 | "schemaMappingsId": "tei",
94 | "xmlUrl": [
95 | "https://tei-c.org/release/xml/tei/custom/schema/relaxng/tei_drama.rng",
96 | "https://jenkins.tei-c.org/job/TEIP5/lastSuccessfulBuild/artifact/P5/release/xml/tei/custom/schema/relaxng/tei_drama.rng"
97 | ],
98 | "cssUrl": [
99 | "https://cwrc.ca/templates/css/tei.css"
100 | ]
101 | },
102 | {
103 | "id": "teiCorpus",
104 | "name": "TEI Corpus Schema",
105 | "schemaMappingsId": "tei",
106 | "xmlUrl": [
107 | "https://www.tei-c.org/release/xml/tei/custom/schema/relaxng/tei_corpus.rng",
108 | "https://jenkins.tei-c.org/job/TEIP5/lastSuccessfulBuild/artifact/P5/release/xml/tei/custom/schema/relaxng/tei_corpus.rng"
109 | ],
110 | "cssUrl": [
111 | "https://cwrc.ca/templates/css/tei.css"
112 | ]
113 | },
114 | {
115 | "id": "teiMs",
116 | "name": "TEI Manuscript Schema",
117 | "schemaMappingsId": "tei",
118 | "xmlUrl": [
119 | "https://www.tei-c.org/release/xml/tei/custom/schema/relaxng/tei_ms.rng",
120 | "https://jenkins.tei-c.org/job/TEIP5/lastSuccessfulBuild/artifact/P5/release/xml/tei/custom/schema/relaxng/tei_ms.rng"
121 | ],
122 | "cssUrl": [
123 | "https://cwrc.ca/templates/css/tei.css"
124 | ]
125 | },
126 | {
127 | "id": "teiSpeech",
128 | "name": "TEI Speech Schema",
129 | "schemaMappingsId": "tei",
130 | "xmlUrl": [
131 | "https://www.tei-c.org/release/xml/tei/custom/schema/relaxng/tei_speech.rng",
132 | "https://jenkins.tei-c.org/job/TEIP5/lastSuccessfulBuild/artifact/P5/release/xml/tei/custom/schema/relaxng/tei_speech.rng"
133 | ],
134 | "cssUrl": [
135 | "https://cwrc.ca/templates/css/tei.css"
136 | ]
137 | },
138 | {
139 | "id": "teiLite",
140 | "name": "TEI Lite Schema",
141 | "schemaMappingsId": "teiLite",
142 | "xmlUrl": [
143 | "https://www.tei-c.org/release/xml/tei/custom/schema/relaxng/tei_lite.rng",
144 | "https://jenkins.tei-c.org/job/TEIP5/lastSuccessfulBuild/artifact/P5/release/xml/tei/custom/schema/relaxng/tei_lite.rng"
145 | ],
146 | "cssUrl": [
147 | "https://cwrc.ca/templates/css/tei.css"
148 | ]
149 | },
150 | {
151 | "id": "moravian",
152 | "name": "Moravian Lives (TEI)",
153 | "schemaMappingsId": "tei",
154 | "xmlUrl": [
155 | "https://raw.githubusercontent.com/moravianlives/ML/master/Projects/TEI_Memoirs/out/MoravianMemoirs.rng"
156 | ],
157 | "cssUrl": [
158 | "https://cwrc.ca/templates/css/tei.css"
159 | ]
160 | },
161 | {
162 | "id": "reed",
163 | "name": "Reed",
164 | "schemaMappingsId": "tei",
165 | "xmlUrl": [
166 | "https://cwrc.ca/islandora/object/cwrc%3A5d5159ce-8710-4717-b977-cc528dedc25e/datastream/SCHEMA/view"
167 | ],
168 | "cssUrl": [
169 | "https://cwrc.ca/templates/css/tei.css"
170 | ]
171 | }
172 | ]
173 | }
174 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CWRC-GitWriter
2 |
3 | 
4 |
5 | [](http://github.com/badges/stability-badges)
6 |
7 | The code in this repository serves two purposes:
8 |
9 | 1. To back the sandbox deployment: [https://cwrc-writer.cwrc.ca/](https://cwrc-writer.cwrc.ca/)
10 |
11 | 2. To provide an example configuration of the CWRC-Writer for those who might like to substitute a different storage or lookup system.
12 |
13 | ## Table of Contents
14 |
15 | 1. [Overview](#overview)
16 | 2. [Use](#use)
17 | 3. [Installation](#installation)
18 | 4. [Development](#development)
19 | 5. [Authentication](#authentication)
20 | 6. [Contributing](#contributing)
21 | 7. [License](#license)
22 |
23 | ### Overview
24 |
25 | 
26 |
27 | As you can see from the overview diagram, CWRC-GitWriter is the parent package which collects and configures the various child packages. While [CWRC-WriterBase](https://github.com/cwrc/CWRC-WriterBase) provides the primary editing functionality, it requires both storage and entity lookup packages, which in this case are [cwrc-git-dialogs](https://github.com/cwrc/cwrc-git-dialogs) and [CWRC-PublicEntityDialogs](https://github.com/cwrc/CWRC-PublicEntityDialogs).
28 |
29 | Although the sandbox version provides a freely usable instance, you may of course install an instance of the CWRC-GitWriter on your own server. CWRC-GitWriter also requires a running instance of [CWRC-GitServer](https://github.com/cwrc/CWRC-GitServer), which in turn interacts with GitHub through the [GitHub API](https://developer.github.com/v3/).
30 |
31 | Note that if you want to create a new version of the CWRC-Writer that is configured to work with your own document repository (e.g., a database), this repository still provides you with the best example to follow. You'll also want to look at the [cwrc-git-dialogs](https://www.npmjs.com/package/cwrc-git-dialogs) repository, which holds
32 |
33 | The javascript class that handles calls to the backend storage, in this case to Github via the CWRC-GitServer. This is the class you'd want to replace with your own. To replace the entity lookups you'd replace [cwrc-public-entity-dialogs](https://www.npmjs.com/package/cwrc-public-entity-dialogs)
34 |
35 | ## Use
36 |
37 | A running deployment of the code in this repository is available for anyone's use at: [https://cwrc-writer.cwrc.ca](https://cwrc-writer.cwrc.ca)
38 |
39 | ## Building
40 |
41 | There are two approached to install the [sandbox version of the CWRC-GitWriter](https://cwrc-writer.cwrc.ca).
42 |
43 | 1. Install the dockerized verion of Git-Server/Git-Writer (**recommended**). The instruction for this approach is descibed in the [CWRC-GitWriter-Docker repo](https://github.com/cwrc/CWRC-GitWriter-Docker).
44 | 2. Manually install each component. Instruction is down below:
45 |
46 | This repository contains a JS file — the [app file](src/js/app.js), and a JSON file — the [config file](config/config.json). The app file does not contain much code itself; it's main purpose to load/require other code bases, and then configure and instantiate the CWRC-Writer. It must first be built in order to be useable. To build:
47 |
48 | - Download the code for this repository, or clone the repository
49 | - Install all the NPM package dependencies: `npm install`
50 | - Check the `config.json file`. Provide the necessary information/customization. See below.
51 | - Use Webpack to package it up for deployment: `npm run build`
52 |
53 | The built code resides in the newly created build directory. It contains the app, along with all the necessary CSS, XML, and image files. To deploy the CWRC-GitWriter simply copy the build directory to your server, probably the same server from which you'd serve the [CWRC-GitServer](https://github.com/cwrc/CWRC-GitServer). You might choose to use ftp, scp, rsync, etc. An example rsync command might be:
54 |
55 | Alternately, if your server has Git and npm support you can clone and build this repository directly on your server.
56 |
57 | ### Config file
58 |
59 | #### cwrcRootUrl
60 |
61 | The path where CWRC-GitWriter is located on the server. Default `""`
62 |
63 | #### nerveUrl
64 |
65 | Nerve url. Default `"https://localhost/nerve/"`
66 |
67 | #### validationUrl
68 |
69 | Validator url. Default `"https://localhost/validator/validate.html"`
70 |
71 | #### helpUrl
72 |
73 | Help url. Default `"https://cwrc.ca/Documentation/CWRC-Writer"`
74 |
75 | #### lookups
76 |
77 | ##### geonames
78 |
79 | Provide a GeoNames username. Default `""`
80 | Note that if a username is not provided, CWRC-Git-Writer will throw an error when trying to access GeoNames.
81 |
82 | You can create a free user account here account: [https://www.geonames.org/login](https://www.geonames.org/login)
83 |
84 | #### schema
85 |
86 | #### proxyXmlEndpoint
87 |
88 | The endpoint path to make call request for schemas xml files. Default: `"./schema/xml/"`
89 | The schema is requested as the 'xml' parameter. eg. `"./schema/xml/:url"`
90 |
91 | #### proxyCssEndpoint
92 |
93 | The endpoint path to make call request for schemas css files. Default: `"./schema/css/"`
94 | The schema is requested as the 'css' parameter. eg. `"./schema/css/:url"`
95 |
96 | ##### schemas
97 |
98 | A list of schemas made available on CWRC-Writer. **Default list of schemas**: CWRC Basic TEI, Events, Biography, Writing, CWRC Entry, EpiDoc, TEI All, TEI Corpus, TEI Manuscript, TEI Speech, TEI Lite, Moravian Lives (TEI).
99 |
100 | Each schema is am object with the following information:
101 |
102 | ```js
103 | {
104 | id: `${uniqueID}`,
105 | name: `${name}`,
106 | schemaMappingsId: `${one_of_the_following['tei', 'orlando', 'cwrcEntry', 'teiLite']}`,
107 | xmlUrl: [`${list_of_URI}`],
108 | cssUrl: [`${list_of_URI}`]
109 | }
110 | ```
111 |
112 | ## Development
113 |
114 | ### Using this code as an example to build a CWRC-Writer with a different backend
115 |
116 | The code in this repository brings together and configures code from other repositories and wouldn't in itself typically be usefully modified. You could, however, clone this repository as a base from which to create a new configuration of the CWRC-Writer, or simply use the code here as a guide in creating your own configuration. Your configuration might, for example, use Fedora to store documents, rather than GitHub.
117 |
118 | ### npm and webapack
119 |
120 | The code in this repository simply brings together and configures code from other repositories and wouldn't in itself typically be usefully modified. You could, however, clone this repository as a base from which to create a new configuration of the CWRC-Writer, or simply use the code here as a guide in creating your own configuration. Your configuration might, for example, use Fedora to store documents, rather than GitHub.
121 |
122 | CWRC-GitWriter uses [NPM](https://www.npmjs.com) both for dependency management and for running it's main build script. The build script in turn uses [Webpack](https://webpack.js.org/) to bundle all code into the single [build/js/app.js](build/js/app.js) file. The [package.json](package.json) file contains the script for invoking Webpack as well as the full list of NPM packages required.
123 |
124 | The entry point into the CWRC-GitWriter code, on which Webpack is invoked, is [src/js/app.js](src/js/app.js) which uses [node.js module loading](https://nodejs.org/api/modules.html) to 'require' - either from the [NPM public registry](https://www.npmjs.com) or from local files - the bits and pieces that make up the CWRC-GitWriter, and plug them together. [Webpack](https://webpack.js.org/) resolves all the 'require' statements, and bundles all the code, including NPM packages and local files, into a single javascript file that is loaded into the web browser.
125 |
126 | To develop a new configuration of the CWRC-Writer, you'll therefore need to understand NPM and Webpack. Then you can get into the CWRC-GitWriter NPM [package.json](package.json) file and [src/js/app.js](src/js/app.js) and adapt it to your own project.
127 |
128 | The [src/js/app.js](src/js/app.js) file imports the following npm CWRC packages:
129 |
130 | - [CWRC-WriterBase](https://www.npmjs.com/package/cwrc-writer-base)
131 | The CWRC-Writer editor
132 |
133 | - [cwrc-git-dialogs](https://www.npmjs.com/package/cwrc-git-dialogs)
134 | The javascript class that handles calls to the backend storage, in this case to Github via the CWRC-GitServer. This is the class you'd want to replace with your own.
135 |
136 | - [cwrc-public-entity-dialogs](https://www.npmjs.com/package/cwrc-public-entity-dialogs)
137 | The javascript class that handles lookups of named entities. You may want to replace this with your own entity lookup
138 |
139 | The app.js file also imports a config file:
140 |
141 | - [src/js/config/config.json](src/js/config/config.json)
142 |
143 | A JSON file that provides the basic configurations to CWRC-GitWriter. It also describes the XML schemas supported.
144 |
145 | - The [src/js/app.js](src/js/app.js) file ties all these together as you would for your own configuration of the CWRC-Writer.
146 |
147 | Note that the authentication for Github is invoked in app.js since it redirects to the GitHub site if the user isn't loaded. Better to redirect here at the outset before loading up all the other CWRC related code. Read more about authentication below in the [Authentication Section](#authentication)
148 |
149 | #### npm link
150 |
151 | If you are making changes to the npm packages that contribute to the CWRC-GitWriter (or more likely to some custom instance of the CWRC-GitWriter that you've built) and you find yourself repeatedly packaging and publishing the npm packages and re-importing the newly published packages (e.g.`npm i cwrc-writer-base@latest`) then you can instead use [npm link](https://docs.npmjs.com/cli/link) to point the package.json dependencies at the local instances.
152 |
153 | For example, when developing cwrc-git-dialogs you would use:
154 |
155 | ```bash
156 | cd ~/projects/cwrc-git-dialogs
157 | npm link
158 | cd ~/projects/CWRC-GitWriter
159 | npm link cwrc-git-dialogs
160 | ```
161 |
162 | This creates a symbolic link between the two packages on your computer. Then, when you run `npm run watch` from CWRC-GitWriter, changes made to cwrc-git-dialogs will cause the CWRC-GitWriter build to update.
163 |
164 | Once finished making and testing local changes, publish the new NPM packages, including the local packages, and remove the dependencies from package.json:
165 |
166 | ```bash
167 | cd ~/projects/CWRC-GitWriter
168 | npm unlink cwrc-git-dialogs
169 | npm i cwrc-git-dialogs@latest
170 | ```
171 |
172 | ## Authentication
173 |
174 | Authentication is with Github using OAuth, as described in the Github API docs: [Github - building oauth apps](https://developer.github.com/apps/building-oauth-apps/)
175 |
176 | The two relevant steps there are:
177 |
178 | 1. [Creating an OAuth App](https://developer.github.com/apps/building-oauth-apps/creating-an-oauth-app/)
179 |
180 | 2. The section called Web Application Flow in [Authorizing OAuth Apps](https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/#web-application-flow)
181 |
182 | After authenticating with GitHub, GitHub returns an OAuth token, which is then submitted on every request to the GitHub API.
183 |
184 | We could store this token in a server side session, but instead we store it in a browser cookie that the CWRC-GitWriter submits in the request header (to help guard against [CSRF](https://en.wikipedia.org/wiki/Cross-site_request_forgery)) for each request to the CWRC-GitServer.
185 |
186 | As explained in the development section you wouldn't typically usefully modify anything here for use by others. Nevertheless, if there is something we've missed, please submit an Issue. If you are interested, however, please take a look at our [Development Docs](https://github.com/cwrc/CWRC-Writer-Dev-Docs)
187 |
188 | 
189 |
190 | ## License
191 |
192 | [GNU GPL V2](LICENSE)
193 |
--------------------------------------------------------------------------------
/docs/images/oauth.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/images/cwrc-gitwriter-overview.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------