diff --git a/.gitignore b/.gitignore index 01019cf150..56ce0b4d49 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ .idea *.iml /lib/codemirror.js +/.vscode \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000..cd4ae76d7b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,940 @@ +{ + "name": "codemirror", + "version": "5.38.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "acorn": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.6.1.tgz", + "integrity": "sha512-XH4o5BK5jmw9PzSGK7mNf+/xV+mPxQxGZoeC36OVsJZYV77JAG9NnI7T90hoUpI/C1TOfXWTvugRdZ9ZR3iE2Q==", + "dev": true + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "3.3.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "acorn-object-spread": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/acorn-object-spread/-/acorn-object-spread-1.0.0.tgz", + "integrity": "sha1-SOrQ9KjrFplaF6Dbn/xqyq2kumg=", + "dev": true, + "requires": { + "acorn": "3.3.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", + "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=", + "dev": true + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", + "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "blint": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/blint/-/blint-1.0.3.tgz", + "integrity": "sha512-6RwH3oJYMujQNd38WWU+jUSRqWfECrmpfL8o3fn3Q3fE9nn5iAktLZJHGEHqeecownbZZwZneTLbaNbIWwU9/A==", + "dev": true, + "requires": { + "acorn": "5.6.1", + "nomnom": "1.8.1" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "buble": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/buble/-/buble-0.15.2.tgz", + "integrity": "sha1-VH/EdIP45egXbYKqXrzLGDsC1hM=", + "dev": true, + "requires": { + "acorn": "3.3.0", + "acorn-jsx": "3.0.1", + "acorn-object-spread": "1.0.0", + "chalk": "1.1.3", + "magic-string": "0.14.0", + "minimist": "1.2.0", + "os-homedir": "1.0.2" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + } + } + }, + "buffer-from": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", + "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "chalk": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", + "dev": true, + "requires": { + "ansi-styles": "1.0.0", + "has-color": "0.1.7", + "strip-ansi": "0.1.1" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "1.1.0", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "typedarray": "0.0.6" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "es6-promise": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", + "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "estree-walker": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.2.1.tgz", + "integrity": "sha1-va/oCVOD2EFNXcLs9MkXO225QS4=", + "dev": true + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extract-zip": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz", + "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=", + "dev": true, + "requires": { + "concat-stream": "1.6.2", + "debug": "2.6.9", + "mkdirp": "0.5.1", + "yauzl": "2.4.1" + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fd-slicer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", + "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "dev": true, + "requires": { + "pend": "1.2.0" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "dev": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "fs-extra": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", + "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "2.4.0", + "klaw": "1.3.1" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "dev": true, + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-color": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", + "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=", + "dev": true + }, + "hasha": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz", + "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=", + "dev": true, + "requires": { + "is-stream": "1.1.0", + "pinkie-promise": "2.0.1" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.14.1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kew": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz", + "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=", + "dev": true + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + }, + "magic-string": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.14.0.tgz", + "integrity": "sha1-VyJK7xcByu7Sc7F6OalW5ysXJGI=", + "dev": true, + "requires": { + "vlq": "0.2.3" + } + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true, + "requires": { + "mime-db": "1.33.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node-static": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/node-static/-/node-static-0.6.0.tgz", + "integrity": "sha1-6FQ6iX88ggSCILOVaShNRHluseI=", + "dev": true + }, + "nomnom": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", + "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=", + "dev": true, + "requires": { + "chalk": "0.4.0", + "underscore": "1.6.0" + } + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "phantomjs-prebuilt": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.16.tgz", + "integrity": "sha1-79ISpKOWbTZHaE6ouniFSb4q7+8=", + "dev": true, + "requires": { + "es6-promise": "4.2.4", + "extract-zip": "1.6.7", + "fs-extra": "1.0.0", + "hasha": "2.2.0", + "kew": "0.7.0", + "progress": "1.1.8", + "request": "2.87.0", + "request-progress": "2.0.1", + "which": "1.3.1" + } + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.87.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", + "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", + "dev": true, + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.7.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.0.3", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.2", + "safe-buffer": "5.1.2", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.6.0", + "uuid": "3.2.1" + } + }, + "request-progress": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz", + "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=", + "dev": true, + "requires": { + "throttleit": "1.0.0" + } + }, + "require-relative": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz", + "integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=", + "dev": true + }, + "rollup": { + "version": "0.41.6", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.41.6.tgz", + "integrity": "sha1-4NBUl4d6OYwQTYFtJzOnGKepTio=", + "dev": true, + "requires": { + "source-map-support": "0.4.18" + } + }, + "rollup-plugin-buble": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-buble/-/rollup-plugin-buble-0.15.0.tgz", + "integrity": "sha1-g8PonH/SJmx5GPQbo5gDE1Gcf9A=", + "dev": true, + "requires": { + "buble": "0.15.2", + "rollup-pluginutils": "1.5.2" + } + }, + "rollup-pluginutils": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz", + "integrity": "sha1-HhVud4+UtyVb+hs9AXi+j1xVJAg=", + "dev": true, + "requires": { + "estree-walker": "0.2.1", + "minimatch": "3.0.4" + } + }, + "rollup-watch": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/rollup-watch/-/rollup-watch-3.2.2.tgz", + "integrity": "sha1-XldCMunvNtqRd/RpRtgIDLJnNUs=", + "dev": true, + "requires": { + "require-relative": "0.8.7" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "0.5.7" + } + }, + "sshpk": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", + "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", + "dev": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "strip-ansi": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", + "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "throttleit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", + "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", + "dev": true + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "dev": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true, + "optional": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "vlq": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", + "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "yauzl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", + "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", + "dev": true, + "requires": { + "fd-slicer": "1.0.1" + } + } + } +} diff --git a/src/display/selection.js b/src/display/selection.js index c658c0a272..fcaa40b47b 100644 --- a/src/display/selection.js +++ b/src/display/selection.js @@ -69,8 +69,8 @@ function drawSelectionRange(cm, range, output) { let lineObj = getLine(doc, line) let lineLen = lineObj.text.length let start, end - function coords(ch, bias) { - return charCoords(cm, Pos(line, ch), "div", lineObj, bias) + function coords(ch, bias, atomic) { + return charCoords(cm, Pos(line, ch), "div", lineObj, bias, atomic) } function wrapX(pos, dir, side) { @@ -79,12 +79,12 @@ function drawSelectionRange(cm, range, output) { let ch = side == "after" ? extent.begin : extent.end - (/\s/.test(lineObj.text.charAt(extent.end - 1)) ? 2 : 1) return coords(ch, prop)[prop] } - + if (cm.state.newIsolate) { lineObj.order = cm.state.newIsolate = null; } // remove previous order in case an isolate marker was added let order = getOrder(lineObj, doc.direction) - iterateBidiSections(order, fromArg || 0, toArg == null ? lineLen : toArg, (from, to, dir, i) => { + iterateBidiSections(order, fromArg || 0, toArg == null ? lineLen : toArg, (from, to, dir, i, atomic) => { let ltr = dir == "ltr" - let fromPos = coords(from, ltr ? "left" : "right") - let toPos = coords(to - 1, ltr ? "right" : "left") + let fromPos = coords(from, ltr ? "left" : "right", atomic) + let toPos = coords(to - 1, ltr ? "right" : "left", atomic) let openStart = fromArg == null && from == 0, openEnd = toArg == null && to == lineLen let first = i == 0, last = !order || i == order.length - 1 diff --git a/src/line/line_data.js b/src/line/line_data.js index 74acdaffc0..e5e2962fed 100644 --- a/src/line/line_data.js +++ b/src/line/line_data.js @@ -127,7 +127,7 @@ export function defaultSpecialCharPlaceholder(ch) { // Build up the DOM representation for a single token, and add it to // the line map. Takes care to render special characters separately. -function buildToken(builder, text, style, startStyle, endStyle, title, css) { +function buildToken(builder, text, style, startStyle, endStyle, title, css, isolate) { if (!text) return let displayText = builder.splitSpaces ? splitSpaces(text, builder.trailingSpace) : text let special = builder.cm.state.specialChars, mustWrap = false @@ -178,12 +178,18 @@ function buildToken(builder, text, style, startStyle, endStyle, title, css) { } } builder.trailingSpace = displayText.charCodeAt(text.length - 1) == 32 - if (style || startStyle || endStyle || mustWrap || css) { + if (style || startStyle || endStyle || mustWrap || css || isolate) { let fullStyle = style || "" if (startStyle) fullStyle += startStyle if (endStyle) fullStyle += endStyle let token = elt("span", [content], fullStyle, css) if (title) token.title = title + if (isolate) { + token.setAttribute("dir", isolate) + var bdiWrapper = document.createElement("bdi") + bdiWrapper.appendChild(token) + token = bdiWrapper + } return builder.content.appendChild(token) } builder.content.appendChild(content) @@ -251,11 +257,11 @@ function insertLineContent(line, builder, styles) { } let len = allText.length, pos = 0, i = 1, text = "", style, css - let nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed + let nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed, isolate for (;;) { if (nextChange == pos) { // Update current marker set spanStyle = spanEndStyle = spanStartStyle = title = css = "" - collapsed = null; nextChange = Infinity + collapsed = isolate = null; nextChange = Infinity let foundBookmarks = [], endStyles for (let j = 0; j < spans.length; ++j) { let sp = spans[j], m = sp.marker @@ -271,6 +277,7 @@ function insertLineContent(line, builder, styles) { if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle if (m.endStyle && sp.to == nextChange) (endStyles || (endStyles = [])).push(m.endStyle, sp.to) if (m.title && !title) title = m.title + if (m.isolate) { isolate = m.isolate } if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0)) collapsed = sp } else if (sp.from > pos && nextChange > sp.from) { @@ -298,7 +305,7 @@ function insertLineContent(line, builder, styles) { if (!collapsed) { let tokenText = end > upto ? text.slice(0, upto - pos) : text builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle, - spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title, css) + spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title, css, isolate) } if (end >= upto) {text = text.slice(upto - pos); pos = upto; break} pos = end diff --git a/src/line/saw_special_spans.js b/src/line/saw_special_spans.js index d315e7ba99..55a2ba582f 100644 --- a/src/line/saw_special_spans.js +++ b/src/line/saw_special_spans.js @@ -1,5 +1,5 @@ // Optimize some code when these features are not used. -export let sawReadOnlySpans = false, sawCollapsedSpans = false +export let sawReadOnlySpans = false, sawCollapsedSpans = false, sawIsolateSpans = false export function seeReadOnlySpans() { sawReadOnlySpans = true @@ -8,3 +8,7 @@ export function seeReadOnlySpans() { export function seeCollapsedSpans() { sawCollapsedSpans = true } + +export function seeIsolateSpans() { + sawIsolateSpans = true +} diff --git a/src/line/spans.js b/src/line/spans.js index d81dec4b83..2344fec774 100644 --- a/src/line/spans.js +++ b/src/line/spans.js @@ -1,7 +1,7 @@ import { indexOf, lst } from "../util/misc.js" import { cmp } from "./pos.js" -import { sawCollapsedSpans } from "./saw_special_spans.js" +import { sawCollapsedSpans, sawIsolateSpans } from "./saw_special_spans.js" import { getLine, isLine, lineNo } from "./utils_line.js" // TEXTMARKER SPANS @@ -247,6 +247,21 @@ export function conflictingCollapsedRange(doc, lineNo, from, to, marker) { } } +// Test whether two isolate ranges overlap, which is not allowed +export function conflictingIsolateRange(doc, lineNo$$2, from, to, marker) { + let line = getLine(doc, lineNo$$2) + let sis = sawIsolateSpans && line.markedSpans + if (sis) { for (let i = 0; i < sis.length; ++i) { + let si = sis[i] + if (!si.marker.isolate) { continue } + let found = si.marker.find(0) + let fromCmp = cmp(found.from, from) || extraLeft(si.marker) - extraLeft(marker) + if (fromCmp <= 0 && (si.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.to, from) >= 0 : cmp(found.to, from) > 0) || + fromCmp >= 0 && (si.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.from, to) <= 0 : cmp(found.from, to) < 0)) + { return true } + } } +} + // A visual line is a line as drawn on the screen. Folding, for // example, can cause multiple logical lines to appear on the same // visual line. This finds the start of the visual line that the diff --git a/src/measurement/position_measurement.js b/src/measurement/position_measurement.js index eb9d18a4cb..8bcee03002 100644 --- a/src/measurement/position_measurement.js +++ b/src/measurement/position_measurement.js @@ -84,8 +84,8 @@ function updateExternalMeasurement(cm, line) { // Get a {top, bottom, left, right} box (in line-local coordinates) // for a given character. -export function measureChar(cm, line, ch, bias) { - return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias) +export function measureChar(cm, line, ch, bias, atomic) { + return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias, null, atomic) } // Find a line view that corresponds to the given line number. @@ -124,7 +124,7 @@ export function prepareMeasureForLine(cm, line) { // Given a prepared measurement object, measures the position of an // actual character (or fetches it from the cache). -export function measureCharPrepared(cm, prepared, ch, bias, varHeight) { +export function measureCharPrepared(cm, prepared, ch, bias, varHeight, atomic) { if (prepared.before) ch = -1 let key = ch + (bias || ""), found if (prepared.cache.hasOwnProperty(key)) { @@ -136,7 +136,7 @@ export function measureCharPrepared(cm, prepared, ch, bias, varHeight) { ensureLineHeights(cm, prepared.view, prepared.rect) prepared.hasHeights = true } - found = measureCharInner(cm, prepared, ch, bias) + found = measureCharInner(cm, prepared, ch, bias, atomic) if (!found.bogus) prepared.cache[key] = found } return {left: found.left, right: found.right, @@ -194,7 +194,7 @@ function getUsefulRect(rects, bias) { return rect } -function measureCharInner(cm, prepared, ch, bias) { +function measureCharInner(cm, prepared, ch, bias, atomic) { let place = nodeAndOffsetInLineMap(prepared.map, ch, bias) let node = place.node, start = place.start, end = place.end, collapse = place.collapse @@ -205,8 +205,10 @@ function measureCharInner(cm, prepared, ch, bias) { while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) ++end if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart) rect = node.parentNode.getBoundingClientRect() - else - rect = getUsefulRect(range(node, start, end).getClientRects(), bias) + else { + if (atomic) {start = 0, end = place.coverEnd - place.coverStart} // cover the entire isolate segment + rect = getUsefulRect(range(node, start, end).getClientRects(), bias) + } if (rect.left || rect.right || start == 0) break end = start start = start - 1 @@ -342,9 +344,9 @@ export function fromCoordSystem(cm, coords, context) { return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top} } -export function charCoords(cm, pos, context, lineObj, bias) { +export function charCoords(cm, pos, context, lineObj, bias, atomic) { if (!lineObj) lineObj = getLine(cm.doc, pos.line) - return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context) + return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias, atomic), context) } // Returns a box for a given cursor position, which may have an @@ -366,11 +368,14 @@ export function charCoords(cm, pos, context, lineObj, bias) { export function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) { lineObj = lineObj || getLine(cm.doc, pos.line) if (!preparedMeasure) preparedMeasure = prepareMeasureForLine(cm, lineObj) - function get(ch, right) { - let m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight) - if (right) m.left = m.right; else m.right = m.left + function get(ch, right, atomic) { + var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight, atomic) + if (atomic && right) { m.right = m.left; } + else if (atomic || right) { m.left = m.right; } + else { m.right = m.left; } return intoCoordSystem(cm, lineObj, m, context) } + if (cm.state.newIsolate) { lineObj.order = cm.state.newIsolate = null; } // remove previous order in case an isolate marker was added let order = getOrder(lineObj, cm.doc.direction), ch = pos.ch, sticky = pos.sticky if (ch >= lineObj.text.length) { ch = lineObj.text.length @@ -383,7 +388,7 @@ export function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeig function getBidi(ch, partPos, invert) { let part = order[partPos], right = part.level == 1 - return get(invert ? ch - 1 : ch, right != invert) + return get(invert ? ch - 1 : ch, right != invert, part.atomic) } let partPos = getBidiPartAt(order, ch, sticky) let other = bidiOther diff --git a/src/model/mark_text.js b/src/model/mark_text.js index 955c72c4a7..f51ed7d679 100644 --- a/src/model/mark_text.js +++ b/src/model/mark_text.js @@ -4,8 +4,8 @@ import { endOperation, operation, runInOp, startOperation } from "../display/ope import { clipPos, cmp, Pos } from "../line/pos.js" import { lineNo, updateLineHeight } from "../line/utils_line.js" import { clearLineMeasurementCacheFor, findViewForLine, textHeight } from "../measurement/position_measurement.js" -import { seeReadOnlySpans, seeCollapsedSpans } from "../line/saw_special_spans.js" -import { addMarkedSpan, conflictingCollapsedRange, getMarkedSpanFor, lineIsHidden, lineLength, MarkedSpan, removeMarkedSpan, visualLine } from "../line/spans.js" +import { seeReadOnlySpans, seeCollapsedSpans, seeIsolateSpans } from "../line/saw_special_spans.js" +import { addMarkedSpan, conflictingCollapsedRange, conflictingIsolateRange, getMarkedSpanFor, lineIsHidden, lineLength, MarkedSpan, removeMarkedSpan, visualLine } from "../line/spans.js" import { copyObj, indexOf, lst } from "../util/misc.js" import { signalLater } from "../util/operation_group.js" import { widgetHeight } from "../measurement/widgets.js" @@ -58,6 +58,7 @@ export class TextMarker { if (span.to != null) max = lineNo(line) if (span.from != null) min = lineNo(line) } + if (cm) { cm.state.newIsolate = true; } line.markedSpans = removeMarkedSpan(line.markedSpans, span) if (span.from == null && this.collapsed && !lineIsHidden(this.doc, line) && cm) updateLineHeight(line, textHeight(cm.display)) @@ -176,6 +177,12 @@ export function markText(doc, from, to, options, type) { throw new Error("Inserting collapsed marker partially overlapping an existing one") seeCollapsedSpans() } + if (marker.isolate) { + if (conflictingIsolateRange(doc, from.line, from, to, marker) || + from.line != to.line && conflictingIsolateRange(doc, to.line, from, to, marker)) + { throw new Error("Inserting isolate marker partially overlapping an existing one") } + seeIsolateSpans() + } if (marker.addToHistory) addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN) @@ -206,6 +213,7 @@ export function markText(doc, from, to, options, type) { marker.id = ++nextMarkerId marker.atomic = true } + if (marker.isolate) { doc.cm.state.newIsolate = true; } if (cm) { // Sync editor state if (updateMaxLine) cm.curOp.updateMaxLine = true diff --git a/src/util/bidi.js b/src/util/bidi.js index 33ab854d88..bc82e4f02e 100644 --- a/src/util/bidi.js +++ b/src/util/bidi.js @@ -8,7 +8,7 @@ export function iterateBidiSections(order, from, to, f) { for (let i = 0; i < order.length; ++i) { let part = order[i] if (part.from < to && part.to > from || from == to && part.to == from) { - f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr", i) + f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr", i, part.atomic) found = true } } @@ -34,6 +34,30 @@ export function getBidiPartAt(order, ch, sticky) { return found != null ? found : bidiOther } +// Returns an array with the positions of isolate and normal segments for the entire string +function getTextAndIsolatePositions(str, marks) { + let flag = 0, len = str.length, textAndIsolates = [], start, nextIsolate, nextNextIsolate, nextIsolateEnd + if (!marks) return [{from: 0, to: len}] + let markers = marks.sort((a, b) => { return a.from - b.from == 0 ? a.to - b.to : a.from - b.from }).filter(x => x.marker.isolate) + for (let i = 0; i < len;) { + start = i, nextIsolate = markers[flag], nextNextIsolate = markers[flag + 1] + if (nextIsolate) { nextIsolateEnd = nextIsolate.to } + else { nextIsolate = {from: len } } + // If the second next isolate overlaps the previous one, truncate the first one + if (nextNextIsolate && nextNextIsolate.from < nextIsolate.to) { nextIsolateEnd = nextNextIsolate.from } + if (i < nextIsolate.from) { + for (; i < len && i < nextIsolate.from; i++ ) {} + textAndIsolates.push({from: start, to: i}) + } else { + for (; i < len && i < nextIsolateEnd; i++) {} + flag += 1 + if (start === i) continue + textAndIsolates.push({from: start, to: i, isolate: nextIsolate.marker.isolate, atomic: nextIsolate.marker.atomic}) + } + } + return textAndIsolates +} + // Bidirectional ordering algorithm // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm // that this (partially) implements. @@ -75,14 +99,17 @@ let bidiOrdering = (function() { let bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/ let isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/ - function BidiSpan(level, from, to) { + function BidiSpan(level, from, to, isolate, atomic) { this.level = level this.from = from; this.to = to + this.isolate = isolate; this.atomic = atomic } - return function(str, direction) { + return function(str, direction, marks) { let outerType = direction == "ltr" ? "L" : "R" + let textAndIsolates = getTextAndIsolatePositions(str, marks) + if (str.length == 0 || direction == "ltr" && !bidiRE.test(str)) return false let len = str.length, types = [] for (let i = 0; i < len; ++i) @@ -151,15 +178,19 @@ let bidiOrdering = (function() { // terms of their influence on neutrals. Start-of-level-run (sor) // and end-of-level-run (eor) are used at level run boundaries. // N2. Any remaining neutrals take the embedding direction. - for (let i = 0; i < len; ++i) { - if (isNeutral.test(types[i])) { - let end - for (end = i + 1; end < len && isNeutral.test(types[end]); ++end) {} - let before = (i ? types[i-1] : outerType) == "L" - let after = (end < len ? types[end] : outerType) == "L" - let replace = before == after ? (before ? "L" : "R") : outerType - for (let j = i; j < end; ++j) types[j] = replace - i = end - 1 + for (var i$6b = 0; i$6b < textAndIsolates.length; i$6b++) { + var isolatePart = textAndIsolates[i$6b], isolateDir = isolatePart.isolate + var isolateLen = textAndIsolates[i$6b].to + for (var i$6 = 0; i$6 < isolateLen; ++i$6) { + if (isNeutral.test(types[i$6])) { + var end$1 = (void 0), replace$1 + for (end$1 = i$6 + 1; end$1 < isolateLen && isNeutral.test(types[end$1]); ++end$1) {} + var before = (i$6 - textAndIsolates[i$6b].from ? types[i$6-1] : outerType) == "L" + var after = (end$1 < isolateLen ? types[end$1] : outerType) == "L" + replace$1 = before == after ? (before ? "L" : "R") : isolateDir ? isolateDir == "rtl" ? "R" : "L" : outerType + for (var j$1 = i$6; j$1 < end$1; ++j$1) { types[j$1] = replace$1 } + i$6 = end$1 - 1 + } } } @@ -169,24 +200,28 @@ let bidiOrdering = (function() { // explicit embedding into account, we can build up the order on // the fly, without following the level-based algorithm. let order = [], m - for (let i = 0; i < len;) { - if (countsAsLeft.test(types[i])) { - let start = i - for (++i; i < len && countsAsLeft.test(types[i]); ++i) {} - order.push(new BidiSpan(0, start, i)) - } else { - let pos = i, at = order.length - for (++i; i < len && types[i] != "L"; ++i) {} - for (let j = pos; j < i;) { - if (countsAsNum.test(types[j])) { - if (pos < j) order.splice(at, 0, new BidiSpan(1, pos, j)) - let nstart = j - for (++j; j < i && countsAsNum.test(types[j]); ++j) {} - order.splice(at, 0, new BidiSpan(2, nstart, j)) - pos = j - } else ++j + for (var i$0 = 0; i$0 < textAndIsolates.length; i$0++) { + len = textAndIsolates[i$0].to + let isolate = textAndIsolates[i$0].isolate, atomic = textAndIsolates[i$0].atomic + for (var i$7 = textAndIsolates[i$0].from; i$7 < len;) { + if (countsAsLeft.test(types[i$7])) { + var start = i$7 + for (++i$7; i$7 < len && countsAsLeft.test(types[i$7]); ++i$7) {} + order.push(new BidiSpan(0, start, i$7, isolate, atomic)) + } else { + var pos = i$7, at = order.length + for (++i$7; i$7 < len && types[i$7] != "L"; ++i$7) {} + for (var j$2 = pos; j$2 < i$7;) { + if (countsAsNum.test(types[j$2])) { + if (pos < j$2) { order.splice(at, 0, new BidiSpan(1, pos, j$2, isolate, atomic)); } + var nstart = j$2 + for (++j$2; j$2 < i$7 && countsAsNum.test(types[j$2]); ++j$2) {} + order.splice(at, 0, new BidiSpan(2, nstart, j$2, isolate, atomic)) + pos = j$2 + } else { ++j$2; } + } + if (pos < i$7) { order.splice(at, 0, new BidiSpan(1, pos, i$7, isolate, atomic)); } } - if (pos < i) order.splice(at, 0, new BidiSpan(1, pos, i)) } } if (direction == "ltr") { @@ -199,7 +234,6 @@ let bidiOrdering = (function() { order.push(new BidiSpan(0, len - m[0].length, len)) } } - return direction == "rtl" ? order.reverse() : order } })() @@ -209,6 +243,6 @@ let bidiOrdering = (function() { // BidiSpan objects otherwise. export function getOrder(line, direction) { let order = line.order - if (order == null) order = line.order = bidiOrdering(line.text, direction) + if (order == null) { order = line.order = bidiOrdering(line.text, direction, line.markedSpans); } return order } diff --git a/test/test.js b/test/test.js index a646a0ce19..e091a225a0 100644 --- a/test/test.js +++ b/test/test.js @@ -2557,3 +2557,22 @@ testCM("mode_lookahead", function(cm) { eq(cm.getTokenAt(Pos(0, 1)).type, null) eq(cm.getTokenAt(Pos(1, 1)).type, "atom") }, {value: "foo\na\nx\nx\n", mode: "lookahead_mode"}) + + +testCM("move_bidi_isolates", function(cm) { + + cm.doc.markText({line:0, ch:0}, {line:0, ch:3}, {isolate:"ltr", atomic:true, readOnly:true}) + cm.doc.markText({line:0, ch:3}, {line:0, ch:15}, {isolate:"rtl"}) + cm.doc.markText({line:0, ch:15}, {line:0, ch:20}, {isolate:"ltr", atomic:true, readOnly:true}) + + cm.execCommand("goLineStart"); + cm.execCommand("delLineLeft"); + cm.execCommand("goCharRight"); + pos = cm.doc.getCursor(); + cm.replaceRange("لؤ", pos, pos) + cm.execCommand("goCharLeft"); + cm.execCommand("goCharLeft"); + cm.execCommand("goCharLeft"); + eqCursorPos(pos, cm.doc.getCursor()); + + }, {value: "hello there ", lineWrapping: true}); \ No newline at end of file