Skip to content

Commit afaeeef

Browse files
committed
create codemirror extension. Needs to bundle it properly to work on another project.
0 parents  commit afaeeef

9 files changed

+1518
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
dist
2+
node_modules

CONTRIBUTING.md

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# Contributing
2+
3+
If you want to start contributing for `CodeMirror ReadOnly Ranges Extension`, read the documentation below to understand more about the project structure and its directives.
4+
5+
## Scripts
6+
Install the project using `yarn`
7+
8+
### Build the project locally
9+
```bash
10+
yarn build:lib #Generate a /dist folder.
11+
```
12+
13+
## Test Library built:
14+
15+
To test your built package we need to go through 2 steps.
16+
17+
- Step 1: Install the built package on a target project
18+
- You can choose between 2 methods:
19+
- Method A: Linking the built package to a target project
20+
- \[**BEST**\] Method B: Publishing to a private registry using Docker + Verdaccio
21+
- Step 2: Using the library on the target project
22+
23+
### Step1
24+
#### Method A) Linking the built package to a target project
25+
26+
A.1) After running `yarn build:lib`, on terminal, run:
27+
28+
`yarn link`
29+
30+
It will create a local link of the library named as "codemirror-readonly-ranges" (so you can use it on your target project)
31+
32+
A.2) Inside your target project:
33+
34+
- On terminal, run:
35+
36+
```bash
37+
yarn link "codemirror-readonly-ranges"
38+
39+
```
40+
It will allows you to use the generated link on step 1 inside the target project.
41+
42+
#### Method B) Publishing to a private registry using Docker + Verdaccio
43+
44+
B.1) Publish the Package
45+
```bash
46+
yarn verdaccio:publish
47+
```
48+
PS: You can enter on `http://localhost:4873/` to check the package published.
49+
50+
Troubleshoot:
51+
52+
- If you are having some permission issue:
53+
On the project root folder, run:
54+
```bash
55+
sudo chown -R 10001:65533 /verdaccio
56+
```
57+
58+
Some command tips:
59+
60+
- Stop the container:
61+
```bash
62+
yarn verdaccio:down
63+
```
64+
65+
- Check container files
66+
```bash
67+
docker exec -it verdaccio /bin/sh
68+
#then you can execute bash commands such as 'ls -a'
69+
```
70+
71+
- Check container logs
72+
```bash
73+
docker logs verdaccio
74+
```
75+
76+
B.2) On the `target project`:
77+
78+
First, you need to install the published package. There is two ways to do it, let me show you:
79+
(Choose the one that fits best for you)
80+
81+
Way 01: Configure `.npmrc` and install the library and its dependencies.
82+
83+
- Create `.npmrc` file with the following content:
84+
```bash
85+
registry=https://registry.npmjs.org/
86+
codemirror-readonly-ranges:registry=http://localhost:4873
87+
```
88+
89+
> PS: `Way 01` is the best option because automatic identifies when to download from verdaccio's registry, so if you publish many times you just need to run `yarn` or `npm install` to update the `codemirror-readonly-ranges` package (instead of manually ask to download it from verdaccio's registry).
90+
91+
92+
Way 02: Install the package pointing directly to verdaccio's registry, then install the related dependencies.
93+
94+
- Install the package pointing directly to verdaccio's registry
95+
```bash
96+
yarn add codemirror-readonly-ranges --registry http://localhost:4873
97+
```

README.md

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# CodeMirror ReadOnly Ranges Extension
2+
3+
This library aims to help you dealing with readonly ranges on Codemirror
4+
5+
## Installation
6+
https://www.npmjs.com/package/codemirror-readonly-ranges
7+
8+
```bash
9+
10+
//Using npm
11+
npm install codemirror-readonly-ranges range-analyzer
12+
13+
//Using yarn
14+
yarn add codemirror-readonly-ranges range-analyzer
15+
16+
```
17+
## Using the extension
18+
19+
First, you need to define a function that returns an array of readonly ranges.
20+
21+
In the example above we are defining the following readonly ranges:
22+
23+
- from 0 until the last position of the 3ed line
24+
- from the last line beggining until the last position of the last line
25+
```typescript
26+
27+
import { EditorState } from '@codemirror/state';
28+
29+
const getReadOnlyRanges = (targetState:EditorState):Array<{from:number|undefined, to:number|undefined}> => {
30+
return [
31+
{
32+
from: undefined, //same as targetState.doc.line(0).from or 0
33+
to: targetState.doc.line(3).to
34+
},
35+
{
36+
from: targetState.doc.line(targetState.doc.lines).from,
37+
to: undefined // same as targetState.doc.line(targetState.doc.lines).to
38+
}
39+
]
40+
}
41+
42+
```
43+
44+
```typescript
45+
import readOnlyRangesExtension from 'codemirror-readonly-ranges'
46+
47+
...
48+
extensions=[readOnlyRangesExtension(getReadOnlyRanges)]
49+
...
50+
51+
```
52+
53+
# CONTRIBUITING
54+
55+
Check out [CONTRIBUTING.md](CONTRIBUTING.md) to understand more about the project internals and how to contribute to it.

package.json

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
"name": "codemirror-readonly-ranges",
3+
"version": "0.1.0-alpha.0",
4+
"description": "Codemirror extension for readonly ranges",
5+
"main": "dist/index.js",
6+
"types": "dist/index.d.ts",
7+
"files": [
8+
"/dist"
9+
],
10+
"scripts": {
11+
"prebuild:lib": "rimraf dist/",
12+
"build:lib": "tsc",
13+
"verdaccio:up": "docker-compose -f verdaccio-docker-compose.yaml up -d",
14+
"verdaccio:down": "docker-compose -f verdaccio-docker-compose.yaml down -v",
15+
"preverdaccio:publish": "cross-var $npm_execpath run verdaccio:down && cross-var $npm_execpath run verdaccio:up",
16+
"verdaccio:publish": "npm publish --registry http://localhost:4873/"
17+
},
18+
"keywords": [
19+
"Codemirror",
20+
"Typescript",
21+
"Library"
22+
],
23+
"author": "Andre Borba Netto Assis",
24+
"license": "MIT",
25+
"repository": {
26+
"type": "git",
27+
"url": "git+https://github.com/andrebnassis/codemirror-readonly-ranges.git"
28+
},
29+
"homepage": "https://github.com/andrebnassis/codemirror-readonly-ranges#readme",
30+
"bugs": {
31+
"url": "https://github.com/andrebnassis/codemirror-readonly-ranges/issues"
32+
},
33+
"dependencies": {},
34+
"devDependencies": {
35+
"@codemirror/state": "^0.19.9",
36+
"@codemirror/view": "^0.19.48",
37+
"cross-var": "^1.1.0",
38+
"range-analyzer": "^0.1.1-alpha.0",
39+
"rimraf": "^3.0.2",
40+
"typescript": "^4.6.3"
41+
},
42+
"peerDependencies": {
43+
"@codemirror/state": "^0.19.9",
44+
"@codemirror/view": "^0.19.48",
45+
"range-analyzer": "^0.1.1-alpha.0"
46+
}
47+
}

src/index.ts

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { EditorState, Extension, Transaction } from "@codemirror/state";
2+
import { EditorView } from "@codemirror/view";
3+
import { getAvailableRanges } from "range-analyzer";
4+
5+
6+
export const smartDelete = (getReadOnlyRanges:(targetState:EditorState)=>Array<{from:number|undefined, to:number|undefined}>) => EditorState.transactionFilter.of((tr:Transaction) => {
7+
8+
9+
if(tr.isUserEvent('delete.selection')){
10+
11+
const initialSelections = tr.startState.selection.ranges.map(range => ({
12+
from: range.from,
13+
to: range.to
14+
}))
15+
16+
if(initialSelections.length > 0)
17+
{
18+
const readOnlyRanges = getReadOnlyRanges(tr.startState);
19+
const result = getAvailableRanges(readOnlyRanges, initialSelections[0], {from: 0, to: tr.startState.doc.line(tr.startState.doc.lines).to }) as Array<{from:number, to:number}>;
20+
return result.map(range => tr.startState.update({changes:{from:range.from, to: range.to}}));
21+
}
22+
}
23+
24+
25+
return tr;
26+
27+
})
28+
29+
export const preventModifyTargetRanges = (getReadOnlyRanges:(targetState:EditorState)=>Array<{from:number|undefined, to:number|undefined}>) => EditorState.changeFilter.of((tr:Transaction) => {
30+
31+
try{
32+
const readOnlyRangesBeforeTransaction = getReadOnlyRanges(tr.startState);
33+
const readOnlyRangesAfterTransaction = getReadOnlyRanges(tr.state);
34+
35+
for(let i = 0; i < readOnlyRangesBeforeTransaction.length; i++){
36+
const targetFromBeforeTransaction = readOnlyRangesBeforeTransaction[i].from ?? 0;
37+
const targetToBeforeTransaction = readOnlyRangesBeforeTransaction[i].to ?? tr.startState.doc.line(tr.startState.doc.lines).to;
38+
39+
const targetFromAfterTransaction = readOnlyRangesAfterTransaction[i].from ?? 0;
40+
const targetToAfterTransaction = readOnlyRangesAfterTransaction[i].to ?? tr.state.doc.line(tr.state.doc.lines).to;
41+
42+
if(tr.startState.sliceDoc(targetFromBeforeTransaction,targetToBeforeTransaction) !== tr.state.sliceDoc(targetFromAfterTransaction, targetToAfterTransaction)){
43+
return false;
44+
}
45+
}
46+
}
47+
catch(e){
48+
return false;
49+
}
50+
return true;
51+
});
52+
53+
export const smartPaste = (getReadOnlyRanges:(targetState:EditorState)=>Array<{from:number|undefined, to:number|undefined}>) => EditorView.domEventHandlers({
54+
55+
paste(event, view)
56+
{
57+
58+
const clipboardData = event.clipboardData || (window as any).clipboardData;
59+
const pastedData = clipboardData.getData('Text');
60+
const initialSelections = view.state.selection.ranges.map(range => ({
61+
from: range.from,
62+
to: range.to
63+
}));
64+
65+
if(initialSelections.length > 0)
66+
{
67+
const readOnlyRanges = getReadOnlyRanges(view.state);
68+
const result = getAvailableRanges(readOnlyRanges, initialSelections[0], {from: 0, to: view.state.doc.line(view.state.doc.lines).to}) as Array<{from:number, to:number}>;
69+
if(result.length > 0)
70+
{
71+
view.dispatch({changes:{from: result[0].from, to: result[0].to, insert: pastedData }})
72+
}
73+
}
74+
}
75+
76+
})
77+
78+
79+
const readOnlyRangesExtension = (getReadOnlyRanges:(targetState:EditorState)=>Array<{from:number|undefined, to:number|undefined}>):Extension => [smartPaste(getReadOnlyRanges), smartDelete(getReadOnlyRanges), preventModifyTargetRanges(getReadOnlyRanges)];
80+
export default readOnlyRangesExtension;

tsconfig.json

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
{
2+
"compilerOptions": {
3+
/* Visit https://aka.ms/tsconfig.json to read more about this file */
4+
5+
/* Basic Options */
6+
// "incremental": true, /* Enable incremental compilation */
7+
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */
8+
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
9+
// "lib": [], /* Specify library files to be included in the compilation. */
10+
// "allowJs": true, /* Allow javascript files to be compiled. */
11+
// "checkJs": true, /* Report errors in .js files. */
12+
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */
13+
"declaration": true, /* Generates corresponding '.d.ts' file. */
14+
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
15+
"sourceMap": true, /* Generates corresponding '.map' file. */
16+
// "outFile": "./", /* Concatenate and emit output to single file. */
17+
"outDir": "./dist", /* Redirect output structure to the directory. */
18+
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
19+
// "composite": true, /* Enable project compilation */
20+
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
21+
// "removeComments": true, /* Do not emit comments to output. */
22+
// "noEmit": true, /* Do not emit outputs. */
23+
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
24+
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
25+
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
26+
27+
/* Strict Type-Checking Options */
28+
"strict": true, /* Enable all strict type-checking options. */
29+
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
30+
// "strictNullChecks": true, /* Enable strict null checks. */
31+
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
32+
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
33+
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
34+
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
35+
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
36+
37+
/* Additional Checks */
38+
// "noUnusedLocals": true, /* Report errors on unused locals. */
39+
// "noUnusedParameters": true, /* Report errors on unused parameters. */
40+
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
41+
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
42+
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
43+
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an 'override' modifier. */
44+
// "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */
45+
46+
/* Module Resolution Options */
47+
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
48+
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
49+
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
50+
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
51+
// "typeRoots": [], /* List of folders to include type definitions from. */
52+
// "types": [], /* Type declaration files to be included in compilation. */
53+
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
54+
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
55+
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
56+
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
57+
58+
/* Source Map Options */
59+
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
60+
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
61+
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
62+
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
63+
64+
/* Experimental Options */
65+
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
66+
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
67+
68+
/* Advanced Options */
69+
"skipLibCheck": true, /* Skip type checking of declaration files. */
70+
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
71+
},
72+
"include":["src/**/*"],
73+
"exclude":["node_modules"]
74+
}

verdaccio-docker-compose.yaml

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# old package.json script command before using docker-compose file:
2+
# "verdaccio:up":"docker start verdaccio 2>/dev/null || docker run -it -d --rm --name verdaccio -p 4873:4873 -v $(pwd)/verdaccio/conf:/verdaccio/conf verdaccio/verdaccio",
3+
4+
version: '3.3'
5+
services:
6+
verdaccio:
7+
container_name: verdaccio
8+
ports:
9+
- '4873:4873'
10+
volumes:
11+
- "./verdaccio/conf:/verdaccio/conf"
12+
image: verdaccio/verdaccio
13+
14+

0 commit comments

Comments
 (0)