Compare commits
1 Commits
plugins_cu
...
v1.0.180
Author | SHA1 | Date | |
---|---|---|---|
|
982a048f2a |
1400
.eslintignore
169
.eslintrc.js
@@ -4,9 +4,9 @@ module.exports = {
|
||||
'es6': true,
|
||||
'node': true,
|
||||
},
|
||||
'parser': '@typescript-eslint/parser',
|
||||
"parser": "@typescript-eslint/parser",
|
||||
'extends': ['eslint:recommended'],
|
||||
'settings': {
|
||||
"settings": {
|
||||
'react': {
|
||||
'version': '16.12',
|
||||
},
|
||||
@@ -15,16 +15,12 @@ module.exports = {
|
||||
'Atomics': 'readonly',
|
||||
'SharedArrayBuffer': 'readonly',
|
||||
|
||||
// Jest variables
|
||||
'test': 'readonly',
|
||||
// Jasmine variables
|
||||
'expect': 'readonly',
|
||||
'describe': 'readonly',
|
||||
'it': 'readonly',
|
||||
'beforeAll': 'readonly',
|
||||
'afterAll': 'readonly',
|
||||
'beforeEach': 'readonly',
|
||||
'afterEach': 'readonly',
|
||||
'jest': 'readonly',
|
||||
'jasmine': 'readonly',
|
||||
|
||||
// React Native variables
|
||||
'__DEV__': 'readonly',
|
||||
@@ -33,132 +29,69 @@ module.exports = {
|
||||
'browserSupportsPromises_': true,
|
||||
'chrome': 'readonly',
|
||||
'browser': 'readonly',
|
||||
|
||||
'tinymce': 'readonly',
|
||||
},
|
||||
'parserOptions': {
|
||||
'ecmaVersion': 2018,
|
||||
'ecmaFeatures': {
|
||||
'jsx': true,
|
||||
},
|
||||
'sourceType': 'module',
|
||||
"ecmaFeatures": {
|
||||
"jsx": true,
|
||||
},
|
||||
"sourceType": "module",
|
||||
},
|
||||
'rules': {
|
||||
// -------------------------------
|
||||
// Code correctness
|
||||
// -------------------------------
|
||||
'react/jsx-uses-react': 'error',
|
||||
'react/jsx-uses-vars': 'error',
|
||||
'no-unused-vars': ['error', { 'argsIgnorePattern': '^_' }],
|
||||
'@typescript-eslint/no-unused-vars': ['error', { 'argsIgnorePattern': '^_' }],
|
||||
'@typescript-eslint/explicit-member-accessibility': 'off',
|
||||
'no-constant-condition': 0,
|
||||
'no-prototype-builtins': 0,
|
||||
"react/jsx-uses-react": "error",
|
||||
"react/jsx-uses-vars": "error",
|
||||
"no-unused-vars": "error",
|
||||
"no-constant-condition": 0,
|
||||
"no-prototype-builtins": 0,
|
||||
// This error is always a false positive so far since it detects
|
||||
// possible race conditions in contexts where we know it cannot happen.
|
||||
'require-atomic-updates': 0,
|
||||
'prefer-const': ['error'],
|
||||
'no-var': ['error'],
|
||||
'no-new-func': ['error'],
|
||||
'import/prefer-default-export': ['error'],
|
||||
'import/first': ['error'],
|
||||
'no-array-constructor': ['error'],
|
||||
'radix': ['error'],
|
||||
"require-atomic-updates": 0,
|
||||
|
||||
// Warn only for now because fixing everything would take too much
|
||||
// refactoring, but new code should try to stick to it.
|
||||
'complexity': ['warn', { max: 10 }],
|
||||
|
||||
// Checks rules of Hooks
|
||||
'react-hooks/rules-of-hooks': 'error',
|
||||
// Checks effect dependencies
|
||||
// Disable because of this: https://github.com/facebook/react/issues/16265
|
||||
// "react-hooks/exhaustive-deps": "warn",
|
||||
// -------------------------------
|
||||
// Coding style preferences
|
||||
// -------------------------------
|
||||
"enforce-react-hooks/enforce-react-hooks": 2,
|
||||
|
||||
// -------------------------------
|
||||
// Formatting
|
||||
// -------------------------------
|
||||
'space-in-parens': ['error', 'never'],
|
||||
'space-infix-ops': ['error'],
|
||||
'curly': ['error', 'multi-line', 'consistent'],
|
||||
'semi': ['error', 'always'],
|
||||
'eol-last': ['error', 'always'],
|
||||
'quotes': ['error', 'single'],
|
||||
'indent': ['error', 'tab'],
|
||||
'comma-dangle': ['error', {
|
||||
'arrays': 'always-multiline',
|
||||
'objects': 'always-multiline',
|
||||
'imports': 'always-multiline',
|
||||
'exports': 'always-multiline',
|
||||
'functions': 'never',
|
||||
"space-in-parens": ["error", "never"],
|
||||
"semi": ["error", "always"],
|
||||
"eol-last": ["error", "always"],
|
||||
"quotes": ["error", "single"],
|
||||
"indent": ["error", "tab"],
|
||||
"comma-dangle": ["error", "always-multiline"],
|
||||
"no-trailing-spaces": "error",
|
||||
"linebreak-style": ["error", "unix"],
|
||||
"prefer-template": ["error"],
|
||||
"template-curly-spacing": ["error", "never"],
|
||||
"object-curly-spacing": ["error", "always"],
|
||||
"array-bracket-spacing": ["error", "never"],
|
||||
"key-spacing": ["error", {
|
||||
"beforeColon": false,
|
||||
"afterColon": true,
|
||||
"mode": "strict"
|
||||
}],
|
||||
'no-trailing-spaces': 'error',
|
||||
'linebreak-style': ['error', 'unix'],
|
||||
'prefer-template': ['error'],
|
||||
'template-curly-spacing': ['error', 'never'],
|
||||
'object-curly-spacing': ['error', 'always'],
|
||||
'array-bracket-spacing': ['error', 'never'],
|
||||
'key-spacing': ['error', {
|
||||
'beforeColon': false,
|
||||
'afterColon': true,
|
||||
'mode': 'strict',
|
||||
"block-spacing": ["error"],
|
||||
"brace-style": ["error", "1tbs", { "allowSingleLine": true }],
|
||||
"no-spaced-func": ["error"],
|
||||
"func-call-spacing": ["error"],
|
||||
"space-before-function-paren": ["error", {
|
||||
"anonymous": "never",
|
||||
"named": "never",
|
||||
"asyncArrow": "always"
|
||||
}],
|
||||
'block-spacing': ['error'],
|
||||
'brace-style': ['error', '1tbs', { 'allowSingleLine': true }],
|
||||
'no-spaced-func': ['error'],
|
||||
'func-call-spacing': ['error'],
|
||||
'space-before-function-paren': ['error', {
|
||||
'anonymous': 'never',
|
||||
'named': 'never',
|
||||
'asyncArrow': 'always',
|
||||
}],
|
||||
'multiline-comment-style': ['error', 'separate-lines'],
|
||||
'space-before-blocks': 'error',
|
||||
'spaced-comment': ['error', 'always'],
|
||||
'keyword-spacing': ['error', { 'before': true, 'after': true }],
|
||||
"multiline-comment-style": ["error", "separate-lines"],
|
||||
"space-before-blocks": "error",
|
||||
"spaced-comment": ["error", "always"],
|
||||
"keyword-spacing": ["error", { "before": true, "after": true }]
|
||||
},
|
||||
'plugins': [
|
||||
'react',
|
||||
'@typescript-eslint',
|
||||
'react-hooks',
|
||||
'import',
|
||||
"plugins": [
|
||||
"react",
|
||||
"@typescript-eslint",
|
||||
"enforce-react-hooks",
|
||||
],
|
||||
'overrides': [
|
||||
{
|
||||
// enable the rule specifically for TypeScript files
|
||||
'files': ['*.ts', '*.tsx'],
|
||||
'parserOptions': {
|
||||
// Required for @typescript-eslint/no-floating-promises
|
||||
'project': './tsconfig.eslint.json',
|
||||
},
|
||||
'rules': {
|
||||
// Warn only because it would make it difficult to convert JS classes to TypeScript, unless we
|
||||
// make everything public which is not great. New code however should specify member accessibility.
|
||||
'@typescript-eslint/explicit-member-accessibility': ['warn'],
|
||||
'@typescript-eslint/type-annotation-spacing': ['error', { 'before': false, 'after': true }],
|
||||
'@typescript-eslint/comma-dangle': ['error', {
|
||||
'arrays': 'always-multiline',
|
||||
'objects': 'always-multiline',
|
||||
'imports': 'always-multiline',
|
||||
'exports': 'always-multiline',
|
||||
'enums': 'always-multiline',
|
||||
'generics': 'always-multiline',
|
||||
'tuples': 'always-multiline',
|
||||
'functions': 'never',
|
||||
}],
|
||||
'@typescript-eslint/semi': ['error', 'always'],
|
||||
'@typescript-eslint/member-delimiter-style': ['error', {
|
||||
'multiline': {
|
||||
'delimiter': 'semi',
|
||||
'requireLast': true,
|
||||
},
|
||||
'singleline': {
|
||||
'delimiter': 'semi',
|
||||
'requireLast': false,
|
||||
},
|
||||
}],
|
||||
'@typescript-eslint/no-floating-promises': ['error'],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
23
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,9 +1,8 @@
|
||||
---
|
||||
name: "\U0001F41B Bug Report"
|
||||
name: "🐛 Bug Report"
|
||||
about: Report a reproducible bug or regression in Joplin.
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
labels: 'bug'
|
||||
|
||||
---
|
||||
|
||||
@@ -20,26 +19,24 @@ assignees: ''
|
||||
|
||||
## Environment
|
||||
|
||||
Joplin version:
|
||||
Platform:
|
||||
OS specifics:
|
||||
|
||||
Joplin version:
|
||||
Platform:
|
||||
OS specifcs:
|
||||
<!--
|
||||
Platform can be one of: macOS, Linux, Windows, Android, iOS, terminal (or a combination)
|
||||
OS specifics: e.g. OS version, Linux distribution, Android/iOS version...
|
||||
OS specifcs: e.g. OS version, Linux distribution, Android/iOS version, ...
|
||||
-->
|
||||
|
||||
## Steps to reproduce
|
||||
## Steps To Reproduce
|
||||
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
1.
|
||||
2.
|
||||
|
||||
<!--
|
||||
Issues without reproduction steps are likely to stall.
|
||||
-->
|
||||
|
||||
## Describe what you expected to happen
|
||||
Describe what you expected to happen:
|
||||
|
||||
|
||||
|
||||
|
5
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,5 +0,0 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: "\U0001F914 Feature requests and support"
|
||||
url: https://discourse.joplinapp.org/
|
||||
about: I have a question or feature request …
|
29
.github/ISSUE_TEMPLATE/question.md
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
name: "🤔 Questions and Help"
|
||||
about: The issue tracker is not for questions. Please ask questions on https://discourse.joplinapp.org/.
|
||||
title: ''
|
||||
labels: 'invalid'
|
||||
|
||||
---
|
||||
|
||||
⚠🚨⛔ The issue tracker is not for questions. ⛔🚨⚠
|
||||
|
||||
As it happens, support requests that are created as issues are likely to be closed. We want to make sure you are able to find the help you seek.
|
||||
|
||||
## Questions and Help
|
||||
|
||||
Please read the [documentation](https://joplinapp.org/) and [FAQ](https://joplinapp.org/faq/) first.
|
||||
|
||||
### https://discourse.joplinapp.org/
|
||||
|
||||
If you have still questions related to Joplin, please open a topic in the [forum](https://discourse.joplinapp.org/).
|
||||
You can use your GitHub credentials to login to the forum.
|
||||
|
||||
## Links
|
||||
|
||||
- Documentation: https://joplinapp.org
|
||||
- FAQ: https://joplinapp.org/faq/
|
||||
- Forum: https://discourse.joplinapp.org
|
||||
- How to enable end-to-end encryption: https://joplinapp.org/e2ee/
|
||||
- API documentation: https://joplinapp.org/api/
|
||||
- How to enable debug mode: https://joplinapp.org/debugging/
|
14
.github/PULL_REQUEST_TEMPLATE
vendored
@@ -2,24 +2,14 @@
|
||||
|
||||
Please prefix the title with the platform you are targetting:
|
||||
|
||||
Here are some examples of good titles:
|
||||
|
||||
- Desktop: Resolves #123: Added new setting to change font
|
||||
- Mobile, Desktop: Fixes #456: Fixed config screen error
|
||||
- All: Resolves #777: Made synchronisation faster
|
||||
|
||||
And here's an explanation of the title format:
|
||||
|
||||
- "Desktop" for the Windows/macOS/Linux app (Electron app)
|
||||
- "Mobile" for the mobile app (or "Android" / "iOS" if the pull request only applies to one of the mobile platforms)
|
||||
- "CLI" for the CLI app
|
||||
|
||||
If it's two platforms, separate them with commas - "Desktop, Mobile" or if it's for all platforms, prefix with "All".
|
||||
|
||||
If it's not related to any platform (such as a translation, change to the documentation, etc.), simply don't add a platform.
|
||||
|
||||
Then please append the issue that you've addressed or fixed. Use "Resolves #123" for new features or improvements and "Fixes #123" for bug fixes.
|
||||
For example: "Desktop: Added new setting to change font", or "Mobile: Fixed config screen error"
|
||||
|
||||
AND PLEASE READ THE GUIDE: https://github.com/laurent22/joplin/blob/dev/CONTRIBUTING.md
|
||||
PLEASE READ THE GUIDE FIRST: https://github.com/laurent22/joplin/blob/master/CONTRIBUTING.md
|
||||
|
||||
-->
|
||||
|
8
.github/stale.yml
vendored
@@ -1,15 +1,17 @@
|
||||
# Configuration for probot-stale - https://github.com/probot/stale
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 30
|
||||
daysUntilStale: 90
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 7
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- "good first issue"
|
||||
- "essential"
|
||||
- "essential-reviewed"
|
||||
- "help wanted"
|
||||
- "nice to have"
|
||||
- "upstream"
|
||||
- "backlog"
|
||||
- "high"
|
||||
- "spec"
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
|
1374
.gitignore
vendored
71
.travis.yml
@@ -1,5 +1,5 @@
|
||||
# Only build tags (Doesn't work - doesn't build anything)
|
||||
if: tag IS present OR type = pull_request OR branch = dev
|
||||
if: tag IS present OR type = pull_request
|
||||
|
||||
rvm: 2.3.3
|
||||
|
||||
@@ -9,36 +9,26 @@ rvm: 2.3.3
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- dev
|
||||
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: osx
|
||||
osx_image: xcode12
|
||||
osx_image: xcode9.0
|
||||
language: node_js
|
||||
node_js: "12"
|
||||
cache:
|
||||
npm: false
|
||||
# Cache was disabled because when changing from node_js 10 to node_js 12
|
||||
# it was still using build files from Node 10 when building SQLite which
|
||||
# was making it fail. Might be ok to re-enable later on, although it doesn't
|
||||
# make build that much faster.
|
||||
#
|
||||
# env:
|
||||
# - ELECTRON_CACHE=$HOME/.cache/electron
|
||||
# - ELECTRON_BUILDER_CACHE=$HOME/.cache/electron-builder
|
||||
node_js: "8"
|
||||
env:
|
||||
- ELECTRON_CACHE=$HOME/.cache/electron
|
||||
- ELECTRON_BUILDER_CACHE=$HOME/.cache/electron-builder
|
||||
|
||||
- os: linux
|
||||
sudo: required
|
||||
dist: trusty
|
||||
language: node_js
|
||||
node_js: "12"
|
||||
cache:
|
||||
npm: false
|
||||
# env:
|
||||
# - ELECTRON_CACHE=$HOME/.cache/electron
|
||||
# - ELECTRON_BUILDER_CACHE=$HOME/.cache/electron-builder
|
||||
node_js: "8"
|
||||
env:
|
||||
- ELECTRON_CACHE=$HOME/.cache/electron
|
||||
- ELECTRON_BUILDER_CACHE=$HOME/.cache/electron-builder
|
||||
|
||||
# cache:
|
||||
# directories:
|
||||
@@ -52,8 +42,6 @@ before_install:
|
||||
|
||||
# Silence apt-get update errors (for example when a module doesn't exist) since
|
||||
# otherwise it will make the whole build fails, even though all we need is yarn.
|
||||
|
||||
# libsecret-1-dev is required for keytar - https://github.com/atom/node-keytar
|
||||
- |
|
||||
if [ "$TRAVIS_OS_NAME" == "osx" ]; then
|
||||
HOMEBREW_NO_AUTO_UPDATE=1 brew install yarn
|
||||
@@ -63,29 +51,32 @@ before_install:
|
||||
sudo apt-get update || true
|
||||
sudo apt-get install -y yarn
|
||||
sudo apt-get install -y gettext
|
||||
sudo apt-get install -y libsecret-1-dev
|
||||
fi
|
||||
|
||||
script:
|
||||
- |
|
||||
# Prints some env variables
|
||||
echo "TRAVIS_OS_NAME=$TRAVIS_OS_NAME"
|
||||
echo "TRAVIS_BRANCH=$TRAVIS_BRANCH"
|
||||
echo "TRAVIS_PULL_REQUEST=$TRAVIS_PULL_REQUEST"
|
||||
echo "TRAVIS_TAG=$TRAVIS_TAG"
|
||||
# Copy lib
|
||||
rsync -aP --delete ReactNativeClient/lib/ ElectronClient/app/lib/
|
||||
|
||||
# Install tools
|
||||
npm install
|
||||
npm run tsc
|
||||
cd Tools
|
||||
npm install
|
||||
cd ..
|
||||
|
||||
# Run test units.
|
||||
# Only do it for pull requests because Travis randomly fails to run them
|
||||
# and that would break the desktop release.
|
||||
if [ "$TRAVIS_PULL_REQUEST" != "false" ] || [ "$TRAVIS_BRANCH" = "dev" ]; then
|
||||
npm run test-ci
|
||||
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
|
||||
cd CliClient
|
||||
npm install
|
||||
./run_test.sh
|
||||
testResult=$?
|
||||
if [ $testResult -ne 0 ]; then
|
||||
exit $testResult
|
||||
fi
|
||||
cd ..
|
||||
fi
|
||||
|
||||
# Run linter for pull requests only - this is so that
|
||||
@@ -103,7 +94,7 @@ script:
|
||||
# tool like poedit. Doing it for Linux only is sufficient.
|
||||
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
|
||||
if [ "$TRAVIS_OS_NAME" != "osx" ]; then
|
||||
node packages/tools/validate-translation.js
|
||||
node Tools/validate-translation.js
|
||||
testResult=$?
|
||||
if [ $testResult -ne 0 ]; then
|
||||
exit $testResult
|
||||
@@ -112,7 +103,7 @@ script:
|
||||
fi
|
||||
|
||||
# Find out if we should run the build or not. Electron-builder gets stuck when
|
||||
# building PRs so we disable it in this case. The Linux build should provide
|
||||
# builing PRs so we disable it in this case. The Linux build should provide
|
||||
# enough info if the app builds or not.
|
||||
# https://github.com/electron-userland/electron-builder/issues/4263
|
||||
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
|
||||
@@ -122,17 +113,5 @@ script:
|
||||
fi
|
||||
|
||||
# Prepare the Electron app and build it
|
||||
#
|
||||
# If the current tag is a desktop release tag (starts with "v", such as
|
||||
# "v1.4.7"), we build and publish to github
|
||||
#
|
||||
# Otherwise we only build but don't publish to GitHub. It helps finding
|
||||
# out any issue in pull requests and dev branch.
|
||||
|
||||
cd packages/app-desktop
|
||||
|
||||
if [[ $TRAVIS_TAG = v* ]]; then
|
||||
USE_HARD_LINKS=false npm run dist
|
||||
else
|
||||
USE_HARD_LINKS=false npm run dist -- --publish=never
|
||||
fi
|
||||
cd ElectronClient/app
|
||||
npm install && USE_HARD_LINKS=false yarn dist
|
||||
|
Before Width: | Height: | Size: 59 KiB |
Before Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 480 B |
Before Width: | Height: | Size: 855 B |
@@ -1,36 +0,0 @@
|
||||
function camelCaseToDots(s) {
|
||||
const output = [];
|
||||
for (let i = 0; i < s.length; i++) {
|
||||
const c = s[i];
|
||||
if (c === c.toLowerCase() || i === 0) {
|
||||
output.push(c.toLowerCase());
|
||||
} else {
|
||||
output.push('.');
|
||||
output.push(c.toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
return output.join('');
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
jpFormatClassName: function(className) {
|
||||
if (className.indexOf('Joplin') !== 0 || className.indexOf(' ') >= 0) return className;
|
||||
|
||||
const p = className.substr(6);
|
||||
if (p === '') return 'joplin';
|
||||
|
||||
return `joplin.${camelCaseToDots(p)
|
||||
.replace(/menu\.items/, 'menuItems')
|
||||
.replace(/toolbar\.buttons/, 'toolbarButtons')}`;
|
||||
},
|
||||
|
||||
jpIsAllowedGroup: function(name) {
|
||||
return name !== 'Constructors';
|
||||
},
|
||||
|
||||
jsIsNotKindVariable: function(classes) {
|
||||
if (!classes) return true;
|
||||
return classes.indexOf('tsd-kind-variable') < 0;
|
||||
},
|
||||
};
|
@@ -1,3 +0,0 @@
|
||||
# Joplin Plugin Documentation
|
||||
|
||||
Welcome to Joplin Plugin Documentation
|
@@ -1,51 +0,0 @@
|
||||
<!doctype html>
|
||||
<html class="default no-js">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>{{#ifCond model.name '==' project.name}}{{project.name}}{{else}}{{jpFormatClassName model.name}} | {{project.name}}{{/ifCond}}</title>
|
||||
<meta name="description" content="Documentation for {{project.name}}">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<link rel="stylesheet" href="{{relativeURL "assets/css/main.css"}}">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
{{> header}}
|
||||
|
||||
<div class="container container-main">
|
||||
<div class="row">
|
||||
<div class="col-8 col-content">
|
||||
{{{contents}}}
|
||||
</div>
|
||||
<div class="col-4 col-menu menu-sticky-wrap menu-highlight">
|
||||
<!--
|
||||
<nav class="tsd-navigation primary">
|
||||
<ul>
|
||||
{{#each navigation.children}}
|
||||
{{> navigation}}
|
||||
{{/each}}
|
||||
</ul>
|
||||
</nav>
|
||||
-->
|
||||
|
||||
<nav class="tsd-navigation secondary menu-sticky">
|
||||
<ul class="before-current">
|
||||
{{#each toc.children}}
|
||||
{{> toc.root}}
|
||||
{{/each}}
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{> footer}}
|
||||
|
||||
<div class="overlay"></div>
|
||||
<script src="{{relativeURL "assets/js/main.js"}}"></script>
|
||||
|
||||
{{> analytics}}
|
||||
|
||||
</body>
|
||||
</html>
|
@@ -1,11 +0,0 @@
|
||||
{{#if settings.gaID}}
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', '{{settings.gaID}}', '{{settings.gaSite}}');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
{{/if}}
|
@@ -1,18 +0,0 @@
|
||||
{{#if parent}}
|
||||
{{#with parent}}{{> breadcrumb}}{{/with}}
|
||||
<li>
|
||||
{{#if url}}
|
||||
<a href="{{relativeURL url}}">{{jpFormatClassName name}}</a>
|
||||
{{else}}
|
||||
<span>{{jpFormatClassName name}}</span>
|
||||
{{/if}}
|
||||
</li>
|
||||
{{else}}
|
||||
<!--
|
||||
{{#if url}}
|
||||
<li>
|
||||
<a href="{{relativeURL url}}">Globals</a>
|
||||
</li>
|
||||
{{/if}}
|
||||
-->
|
||||
{{/if}}
|
@@ -1,22 +0,0 @@
|
||||
{{#with comment}}
|
||||
{{#if hasVisibleComponent}}
|
||||
<div class="tsd-comment tsd-typography">
|
||||
{{#if shortText}}
|
||||
<div class="lead">
|
||||
{{#markdown}}{{{shortText}}}{{/markdown}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if text}}
|
||||
{{#markdown}}{{{text}}}{{/markdown}}
|
||||
{{/if}}
|
||||
{{#if tags}}
|
||||
<dl class="tsd-comment-tags">
|
||||
{{#each tags}}
|
||||
<dt>{{tagName}}</dt>
|
||||
<dd>{{#markdown}}{{{text}}}{{/markdown}}</dd>
|
||||
{{/each}}
|
||||
</dl>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/with}}
|
@@ -1,23 +0,0 @@
|
||||
|
||||
<!-- JOPLINCHANGE
|
||||
<footer{{#unless settings.hideGenerator}} class="with-border-bottom"{{/unless}}>
|
||||
<div class="container">
|
||||
<h2>Legend</h2>
|
||||
<div class="tsd-legend-group">
|
||||
{{#each legend}}
|
||||
<ul class="tsd-legend">
|
||||
{{#each .}}
|
||||
<li class="{{#compact}}{{#each classes}} {{.}}{{/each}}{{/compact}}"><span class="tsd-kind-icon">{{name}}</span></li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
{{#unless settings.hideGenerator}}
|
||||
<div class="container tsd-generator">
|
||||
<p>Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p>
|
||||
</div>
|
||||
{{/unless}}
|
||||
-->
|
@@ -1,71 +0,0 @@
|
||||
<header>
|
||||
<div class="tsd-page-toolbar">
|
||||
<div class="container">
|
||||
<div class="table-wrap">
|
||||
<div class="table-cell" id="tsd-search" data-index="{{relativeURL "assets/js/search.json"}}" data-base="{{relativeURL "./"}}">
|
||||
<div class="field">
|
||||
<label for="tsd-search-field" class="tsd-widget search no-caption">Search</label>
|
||||
<input id="tsd-search-field" type="text" />
|
||||
</div>
|
||||
|
||||
<ul class="results">
|
||||
<li class="state loading">Preparing search index...</li>
|
||||
<li class="state failure">The search index is not available</li>
|
||||
</ul>
|
||||
|
||||
<a href="{{relativeURL "classes/joplin.html"}}" class="title">{{project.name}}</a>
|
||||
</div>
|
||||
|
||||
<div class="table-cell" id="tsd-widgets">
|
||||
<div id="tsd-filter">
|
||||
<a href="#" class="tsd-widget options no-caption" data-toggle="options">Options</a>
|
||||
<div class="tsd-filter-group">
|
||||
<div class="tsd-select" id="tsd-filter-visibility">
|
||||
<span class="tsd-select-label">All</span>
|
||||
<ul class="tsd-select-list">
|
||||
<li data-value="public">Public</li>
|
||||
<li data-value="protected">Public/Protected</li>
|
||||
<li data-value="private" class="selected">All</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<input type="checkbox" id="tsd-filter-inherited" checked />
|
||||
<label class="tsd-widget" for="tsd-filter-inherited">Inherited</label>
|
||||
|
||||
{{#unless settings.excludeExternals}}
|
||||
<input type="checkbox" id="tsd-filter-externals" checked />
|
||||
<label class="tsd-widget" for="tsd-filter-externals">Externals</label>
|
||||
{{/unless}}
|
||||
|
||||
{{#unless settings.excludeNotExported}}
|
||||
<input type="checkbox" id="tsd-filter-only-exported" />
|
||||
<label class="tsd-widget" for="tsd-filter-only-exported">Only exported</label>
|
||||
{{/unless}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="#" class="tsd-widget menu no-caption" data-toggle="menu">Menu</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tsd-page-title">
|
||||
<div class="container">
|
||||
<ul class="tsd-breadcrumb">
|
||||
{{#with model}}{{> breadcrumb}}{{/with}}
|
||||
</ul>
|
||||
<h1>{{#compact}}
|
||||
<!-- {{model.kindString}} -->
|
||||
{{jpFormatClassName model.name}}
|
||||
{{#if model.typeParameters}}
|
||||
<
|
||||
{{#each model.typeParameters}}
|
||||
{{#if @index}}, {{/if}}
|
||||
{{name}}
|
||||
{{/each}}
|
||||
>
|
||||
{{/if}}
|
||||
{{/compact}}</h1>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
@@ -1,17 +0,0 @@
|
||||
<ul class="tsd-hierarchy">
|
||||
{{#each types}}
|
||||
<li>
|
||||
{{#if ../isTarget}}
|
||||
<span class="target">{{this}}</span>
|
||||
{{else}}
|
||||
{{#compact}}{{> type}}{{/compact}}
|
||||
{{/if}}
|
||||
|
||||
{{#if @last}}
|
||||
{{#with ../next}}
|
||||
{{> hierarchy}}
|
||||
{{/with}}
|
||||
{{/if}}
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
@@ -1,32 +0,0 @@
|
||||
{{#if groups}}
|
||||
<section class="tsd-panel-group tsd-index-group">
|
||||
<h2>Index</h2>
|
||||
<section class="tsd-panel tsd-index-panel">
|
||||
<div class="tsd-index-content">
|
||||
{{#each groups}}
|
||||
<section class="tsd-index-section {{cssClasses}}">
|
||||
{{#if categories}}
|
||||
{{#each categories}}
|
||||
<h3>{{#if title}}{{title}} {{/if}}{{../title}}</h3>
|
||||
<ul class="tsd-index-list">
|
||||
{{#each children}}
|
||||
<li class="{{cssClasses}}"><a href="{{relativeURL url}}" class="tsd-kind-icon">{{#if name}}{{{wbr name}}}{{else}}<em>{{{wbr kindString}}}</em>{{/if}}</a></li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{/each}}
|
||||
{{else}}
|
||||
{{#if (jpIsAllowedGroup title)}}
|
||||
<h3>{{title}}</h3>
|
||||
<ul class="tsd-index-list">
|
||||
{{#each children}}
|
||||
<li class="{{cssClasses}}"><a href="{{relativeURL url}}" class="tsd-kind-icon">{{#if name}}{{{wbr name}}}{{else}}<em>{{{wbr kindString}}}</em>{{/if}}</a></li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</section>
|
||||
{{/each}}
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
{{/if}}
|
@@ -1,36 +0,0 @@
|
||||
<div class="tsd-signature tsd-kind-icon">{{#compact}}
|
||||
{{{wbr name}}}
|
||||
{{#if typeParameters}}
|
||||
<
|
||||
{{#each typeParameters}}
|
||||
{{#if @index}}, {{/if}}
|
||||
{{name}}
|
||||
{{/each}}
|
||||
>
|
||||
{{/if}}
|
||||
<span class="tsd-signature-symbol">{{#if isOptional}}?{{/if}}:</span> {{#with type}}{{>type}}{{/with}}
|
||||
{{#if defaultValue}}
|
||||
<span class="tsd-signature-symbol">
|
||||
=
|
||||
{{defaultValue}}
|
||||
</span>
|
||||
{{/if}}
|
||||
{{/compact}}</div>
|
||||
|
||||
{{> member.sources}}
|
||||
|
||||
{{> comment}}
|
||||
|
||||
{{#if typeParameters}}
|
||||
<h4 class="tsd-type-parameters-title">Type parameters</h4>
|
||||
{{> typeParameters}}
|
||||
{{/if}}
|
||||
|
||||
{{#if type.declaration}}
|
||||
<div class="tsd-type-declaration">
|
||||
<h4>Type declaration</h4>
|
||||
{{#with type.declaration}}
|
||||
{{> parameter}}
|
||||
{{/with}}
|
||||
</div>
|
||||
{{/if}}
|
@@ -1,37 +0,0 @@
|
||||
<ul class="tsd-signatures {{cssClasses}}">
|
||||
{{#if getSignature}}
|
||||
{{#with getSignature}}
|
||||
<li class="tsd-signature tsd-kind-icon">{{#compact}}
|
||||
<span class="tsd-signature-symbol">get</span>
|
||||
{{../name}}
|
||||
{{> member.signature.title hideName=true }}
|
||||
{{/compact}}</li>
|
||||
{{/with}}
|
||||
{{/if}}
|
||||
{{#if setSignature}}
|
||||
{{#with setSignature}}
|
||||
<li class="tsd-signature tsd-kind-icon">{{#compact}}
|
||||
<span class="tsd-signature-symbol">set</span>
|
||||
{{../name}}
|
||||
{{> member.signature.title hideName=true }}
|
||||
{{/compact}}</li>
|
||||
{{/with}}
|
||||
{{/if}}
|
||||
</ul>
|
||||
|
||||
<ul class="tsd-descriptions">
|
||||
{{#if getSignature}}
|
||||
{{#with getSignature}}
|
||||
<li class="tsd-description">
|
||||
{{> member.signature.body }}
|
||||
</li>
|
||||
{{/with}}
|
||||
{{/if}}
|
||||
{{#if setSignature}}
|
||||
{{#with setSignature}}
|
||||
<li class="tsd-description">
|
||||
{{> member.signature.body }}
|
||||
</li>
|
||||
{{/with}}
|
||||
{{/if}}
|
||||
</ul>
|
@@ -1,24 +0,0 @@
|
||||
<section class="tsd-panel tsd-member {{cssClasses}}">
|
||||
<a name="{{anchor}}" class="tsd-anchor"></a>
|
||||
{{#if name}}
|
||||
<h3>{{#each flags}}<span class="tsd-flag ts-flag{{this}}">{{this}}</span> {{/each}}{{{wbr name}}}</h3>
|
||||
{{/if}}
|
||||
|
||||
{{#if signatures}}
|
||||
{{> member.signatures}}
|
||||
{{else}}{{#if hasGetterOrSetter}}
|
||||
{{> member.getterSetter}}
|
||||
{{else}}{{#if isReference}}
|
||||
{{> member.reference}}
|
||||
{{else}}
|
||||
{{> member.declaration}}
|
||||
{{/if}}{{/if}}{{/if}}
|
||||
|
||||
{{#each groups}}
|
||||
{{#each children}}
|
||||
{{#unless hasOwnDocument}}
|
||||
{{> member}}
|
||||
{{/unless}}
|
||||
{{/each}}
|
||||
{{/each}}
|
||||
</section>
|
@@ -1,11 +0,0 @@
|
||||
{{#with tryGetTargetReflectionDeep}}
|
||||
{{#ifCond ../name '===' name}}
|
||||
Re-exports <a href="{{relativeURL url}}">{{name}}</a>
|
||||
{{else if flags.isExported}}
|
||||
Renames and re-exports <a href="{{relativeURL url}}">{{name}}</a>
|
||||
{{else}}
|
||||
Renames and exports <a href="{{relativeURL url}}">{{name}}</a>
|
||||
{{/ifCond}}
|
||||
{{else}}
|
||||
Re-exports {{name}}
|
||||
{{/with}}
|
@@ -1,58 +0,0 @@
|
||||
{{#unless hideSources}}
|
||||
{{> member.sources}}
|
||||
{{/unless}}
|
||||
|
||||
{{> comment}}
|
||||
|
||||
{{#if typeParameters}}
|
||||
<h4 class="tsd-type-parameters-title">Type parameters</h4>
|
||||
{{> typeParameters}}
|
||||
{{/if}}
|
||||
|
||||
{{#if parameters}}
|
||||
<h4 class="tsd-parameters-title">Parameters</h4>
|
||||
<ul class="tsd-parameters">
|
||||
{{#each parameters}}
|
||||
<li>
|
||||
<h5>{{#compact}}
|
||||
{{#each flags}}
|
||||
<span class="tsd-flag ts-flag{{this}}">{{this}}</span>
|
||||
{{/each}}
|
||||
{{#if flags.isRest}}<span class="tsd-signature-symbol">...</span>{{/if}}
|
||||
{{name}}:
|
||||
{{#with type}}{{>type}}{{/with}}
|
||||
{{#if defaultValue}}
|
||||
<span class="tsd-signature-symbol">
|
||||
=
|
||||
{{defaultValue}}
|
||||
</span>
|
||||
{{/if}}
|
||||
{{/compact}}</h5>
|
||||
|
||||
{{> comment}}
|
||||
|
||||
{{#if type.declaration}}
|
||||
{{#with type.declaration}}
|
||||
{{> parameter}}
|
||||
{{/with}}
|
||||
{{/if}}
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{/if}}
|
||||
|
||||
<!-- JOPLINCHANGE
|
||||
{{#if type}}
|
||||
<h4 class="tsd-returns-title">Returns {{#compact}}{{#with type}}{{>type}}{{/with}}{{/compact}}</h4>
|
||||
|
||||
{{#if comment.returns}}
|
||||
{{#markdown}}{{{comment.returns}}}{{/markdown}}
|
||||
{{/if}}
|
||||
|
||||
{{#if type.declaration}}
|
||||
{{#with type.declaration}}
|
||||
{{> parameter}}
|
||||
{{/with}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
-->
|
@@ -1,32 +0,0 @@
|
||||
{{#unless hideName}}{{{wbr name}}}{{/unless}}
|
||||
{{#if typeParameters}}
|
||||
<
|
||||
{{#each typeParameters}}
|
||||
{{#if @index}}, {{/if}}
|
||||
{{name}}
|
||||
{{/each}}
|
||||
>
|
||||
{{/if}}
|
||||
<span class="tsd-signature-symbol">(</span>
|
||||
{{#each parameters}}
|
||||
{{#if @index}}, {{/if}}
|
||||
{{#if flags.isRest}}<span class="tsd-signature-symbol">...</span>{{/if}}
|
||||
{{name}}
|
||||
<span class="tsd-signature-symbol">
|
||||
{{#if flags.isOptional}}?{{/if}}
|
||||
{{#if defaultValue}}?{{/if}}
|
||||
:
|
||||
</span>
|
||||
{{#with type}}{{>type}}{{/with}}
|
||||
{{/each}}
|
||||
<span class="tsd-signature-symbol">)</span>
|
||||
{{#if type}}
|
||||
{{#if arrowStyle}}
|
||||
<span class="tsd-signature-symbol"> => </span>
|
||||
{{else}}
|
||||
<span class="tsd-signature-symbol">: </span>
|
||||
{{/if}}
|
||||
{{#with type}}
|
||||
{{>type}}
|
||||
{{/with}}
|
||||
{{/if}}
|
@@ -1,13 +0,0 @@
|
||||
<ul class="tsd-signatures {{cssClasses}}">
|
||||
{{#each signatures}}
|
||||
<li class="tsd-signature tsd-kind-icon">{{#compact}}{{> member.signature.title }}{{/compact}}</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
|
||||
<ul class="tsd-descriptions">
|
||||
{{#each signatures}}
|
||||
<li class="tsd-description">
|
||||
{{> member.signature.body }}
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
@@ -1,11 +0,0 @@
|
||||
<aside class="tsd-sources">
|
||||
{{#if implementationOf}}
|
||||
<p>Implementation of {{#with implementationOf}}{{> typeAndParent}}{{/with}}</p>
|
||||
{{/if}}
|
||||
{{#if inheritedFrom}}
|
||||
<p>Inherited from {{#with inheritedFrom}}{{> typeAndParent}}{{/with}}</p>
|
||||
{{/if}}
|
||||
{{#if overwrites}}
|
||||
<p>Overrides {{#with overwrites}}{{> typeAndParent}}{{/with}}</p>
|
||||
{{/if}}
|
||||
</aside>
|
@@ -1,23 +0,0 @@
|
||||
{{#if categories}}
|
||||
{{#each categories}}
|
||||
<section class="tsd-panel-group tsd-member-group {{cssClasses}}">
|
||||
<h2>{{#if title}}{{title}} {{/if}}{{../title}}</h2>
|
||||
{{#each children}}
|
||||
{{#unless hasOwnDocument}}
|
||||
{{> member}}
|
||||
{{/unless}}
|
||||
{{/each}}
|
||||
</section>
|
||||
{{/each}}
|
||||
{{else}}
|
||||
<section class="tsd-panel-group tsd-member-group {{cssClasses}}">
|
||||
{{#if (jpIsAllowedGroup title)}}
|
||||
<h2>{{title}}</h2>
|
||||
{{#each children}}
|
||||
{{#unless hasOwnDocument}}
|
||||
{{> member}}
|
||||
{{/unless}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
</section>
|
||||
{{/if}}
|
@@ -1,20 +0,0 @@
|
||||
{{#if categories}}
|
||||
{{#each categories}}
|
||||
{{#unless allChildrenHaveOwnDocument}}
|
||||
<section class="tsd-panel-group tsd-member-group {{cssClasses}}">
|
||||
<h2>{{title}}</h2>
|
||||
{{#each children}}
|
||||
{{#unless hasOwnDocument}}
|
||||
{{> member}}
|
||||
{{/unless}}
|
||||
{{/each}}
|
||||
</section>
|
||||
{{/unless}}
|
||||
{{/each}}
|
||||
{{else}}
|
||||
{{#each groups}}
|
||||
{{#unless allChildrenHaveOwnDocument}}
|
||||
{{> members.group}}
|
||||
{{/unless}}
|
||||
{{/each}}
|
||||
{{/if}}
|
@@ -1,26 +0,0 @@
|
||||
{{#if isVisible}}
|
||||
{{#if isLabel}}
|
||||
<li class="label {{cssClasses}}">
|
||||
<span>{{{wbr title}}}</span>
|
||||
</li>
|
||||
{{else}}
|
||||
{{#if isGlobals}}
|
||||
<li class="globals {{#if isInPath}}current{{/if}} {{cssClasses}}">
|
||||
<a href="{{relativeURL url}}"><em>{{{wbr title}}}</em></a>
|
||||
</li>
|
||||
{{else}}
|
||||
<li class="{{#if isInPath}}current{{/if}} {{cssClasses}}">
|
||||
<a href="{{relativeURL url}}">{{{wbr title}}}</a>
|
||||
{{#if isInPath}}
|
||||
{{#if children}}
|
||||
<ul>
|
||||
{{#each children}}
|
||||
{{> navigation}}
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/if}}
|
@@ -1,83 +0,0 @@
|
||||
<ul class="tsd-parameters">
|
||||
{{#if signatures}}
|
||||
<li class="tsd-parameter-signature">
|
||||
<ul class="tsd-signatures {{cssClasses}}">
|
||||
{{#each signatures}}
|
||||
<li class="tsd-signature tsd-kind-icon">{{#compact}}
|
||||
{{> member.signature.title hideName=true }}
|
||||
{{/compact}}</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
|
||||
<ul class="tsd-descriptions">
|
||||
{{#each signatures}}
|
||||
<li class="tsd-description">{{> member.signature.body hideSources=true }}</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if indexSignature}}
|
||||
<li class="tsd-parameter-index-signature">
|
||||
<h5>{{#compact}}
|
||||
<span class="tsd-signature-symbol">[</span>
|
||||
{{#each indexSignature.parameters}}
|
||||
{{#if flags.isRest}}<span class="tsd-signature-symbol">...</span>{{/if}}{{name}}: {{#with type}}{{>type}}{{/with}}
|
||||
{{/each}}
|
||||
<span class="tsd-signature-symbol">]: </span>
|
||||
{{#with indexSignature.type}}{{>type}}{{/with}}
|
||||
{{/compact}}</h5>
|
||||
|
||||
{{#with indexSignature}}
|
||||
{{> comment}}
|
||||
{{/with}}
|
||||
|
||||
{{#if indexSignature.type.declaration}}
|
||||
{{#with indexSignature.type.declaration}}
|
||||
{{> parameter}}
|
||||
{{/with}}
|
||||
{{/if}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#each children}}
|
||||
<li class="tsd-parameter">
|
||||
{{#if signatures}}
|
||||
<h5>{{#compact}}
|
||||
{{#if flags.isRest}}<span class="tsd-signature-symbol">...</span>{{/if}}
|
||||
{{{wbr name}}}
|
||||
<span class="tsd-signature-symbol">
|
||||
{{#if isOptional}}?{{/if}}
|
||||
:
|
||||
</span>
|
||||
function
|
||||
{{/compact}}</h5>
|
||||
|
||||
{{> member.signatures}}
|
||||
{{else}}
|
||||
<h5>{{#compact}}
|
||||
{{#each flags}}
|
||||
<span class="tsd-flag ts-flag{{this}}">{{this}}</span>
|
||||
{{/each}}
|
||||
{{#if flags.isRest}}<span class="tsd-signature-symbol">...</span>{{/if}}
|
||||
{{{wbr name}}}
|
||||
<span class="tsd-signature-symbol">
|
||||
{{#if flags.isOptional}}?{{/if}}
|
||||
:
|
||||
</span>
|
||||
{{#with type}}{{>type}}{{/with}}
|
||||
{{/compact}}</h5>
|
||||
|
||||
{{> comment}}
|
||||
|
||||
{{#if children}}
|
||||
{{> parameter}}
|
||||
{{/if}}
|
||||
|
||||
{{#if type.declaration}}
|
||||
{{#with type.declaration}}
|
||||
{{> parameter}}
|
||||
{{/with}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
@@ -1,10 +0,0 @@
|
||||
<li class="{{#if isInPath}}current{{/if}} {{cssClasses}}">
|
||||
<a href="{{relativeURL url}}" class="tsd-kind-icon">{{{wbr title}}}</a>
|
||||
{{#if children}}
|
||||
<ul>
|
||||
{{#each children}}
|
||||
{{> toc}}
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{/if}}
|
||||
</li>
|
@@ -1,21 +0,0 @@
|
||||
{{#if isInPath}}
|
||||
</ul>
|
||||
<ul class="current">
|
||||
{{/if}}
|
||||
|
||||
{{#if (jsIsNotKindVariable cssClasses)}}
|
||||
<li class="{{#if isInPath}}current{{/if}} {{cssClasses}}">
|
||||
<a href="{{relativeURL url}}" class="tsd-kind-icon">{{{jpFormatClassName title}}}</a>
|
||||
{{#if children}}
|
||||
<ul>
|
||||
{{#each children}}
|
||||
{{> toc}}
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{/if}}
|
||||
</li>
|
||||
{{#if isInPath}}
|
||||
</ul>
|
||||
<ul class="after-current">
|
||||
{{/if}}
|
||||
{{/if}}
|
@@ -1,211 +0,0 @@
|
||||
{{! Each type gets its own inline helper to determine how it is rendered. }}
|
||||
{{! The name of the helper is the value of the 'type' property on the type.}}
|
||||
|
||||
{{!
|
||||
The type helper accepts an optional needsParens parameter that is checked
|
||||
if an inner type may result in invalid output without them. For example:
|
||||
1 | 2[] !== (1 | 2)[]
|
||||
() => 1 | 2 !== (() => 1) | 2
|
||||
}}
|
||||
|
||||
{{#*inline 'array'}}
|
||||
{{#with elementType}}
|
||||
{{> type needsParens=true}}
|
||||
<span class="tsd-signature-symbol">[]</span>
|
||||
{{/with}}
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline 'conditional'}}
|
||||
{{#if needsParens}}
|
||||
<span class="tsd-signature-symbol">(</span>
|
||||
{{/if}}
|
||||
{{#with checkType}}
|
||||
{{> type needsParens=true}}
|
||||
{{/with}}
|
||||
<span class="tsd-signature-symbol"> extends </span>
|
||||
{{#with extendsType}}
|
||||
{{> type}}
|
||||
{{/with}}
|
||||
<span class="tsd-signature-symbol"> ? </span>
|
||||
{{#with trueType}}
|
||||
{{> type}}
|
||||
{{/with}}
|
||||
<span class="tsd-signature-symbol"> : </span>
|
||||
{{#with falseType}}
|
||||
{{> type}}
|
||||
{{/with}}
|
||||
{{#if needsParens}}
|
||||
<span class="tsd-signature-symbol">)</span>
|
||||
{{/if}}
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline 'indexedAccess'}}
|
||||
{{#with objectType}}
|
||||
{{> type}}
|
||||
{{/with}}
|
||||
<span class="tsd-signature-symbol">[</span>
|
||||
{{#with indexType}}
|
||||
{{> type}}
|
||||
{{/with}}
|
||||
<span class="tsd-signature-symbol">]</span>
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline 'inferred'}}
|
||||
<span class="tsd-signature-symbol">infer </span> {{name}}
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline 'intersection'}}
|
||||
{{#if needsParens}}
|
||||
<span class="tsd-signature-symbol">(</span>
|
||||
{{/if}}
|
||||
{{#each types}}
|
||||
{{#unless @first}}
|
||||
<span class="tsd-signature-symbol"> & </span>
|
||||
{{/unless}}
|
||||
{{> type}}
|
||||
{{/each}}
|
||||
{{#if needsParens}}
|
||||
<span class="tsd-signature-symbol">)</span>
|
||||
{{/if}}
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline 'intrinsic'}}
|
||||
<span class="tsd-signature-type">{{name}}</span>
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline 'predicate'}}
|
||||
{{#if asserts}}
|
||||
<span class="tsd-signature-symbol">asserts</span>
|
||||
{{/if}}
|
||||
<span class="tsd-signature-type">{{name}}</span>
|
||||
{{#if targetType}}
|
||||
<span class="tsd-signature-symbol"> is </span>
|
||||
{{#with targetType}}
|
||||
{{>type}}
|
||||
{{/with}}
|
||||
{{/if}}
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline 'query'}}
|
||||
<span class="tsd-signature-symbol">typeof </span>
|
||||
{{#with queryType}}
|
||||
{{> type}}
|
||||
{{/with}}
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline 'reference'}}
|
||||
{{#if reflection}}
|
||||
<a href="{{relativeURL reflection.url}}" class="tsd-signature-type">
|
||||
{{jpFormatClassName reflection.name}}
|
||||
</a>
|
||||
{{else}}
|
||||
<span class="tsd-signature-type">{{jpFormatClassName name}}</span>
|
||||
{{/if}}
|
||||
{{#if typeArguments}}
|
||||
<span class="tsd-signature-symbol"><</span>
|
||||
{{#each typeArguments}}
|
||||
{{#unless @first}}
|
||||
<span class="tsd-signature-symbol">, </span>
|
||||
{{/unless}}
|
||||
{{> type}}
|
||||
{{/each}}
|
||||
<span class="tsd-signature-symbol">></span>
|
||||
{{/if}}
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline 'reflection'}}
|
||||
{{#if declaration.children}} {{! object literal }}
|
||||
<span class="tsd-signature-symbol">{ </span>
|
||||
{{#each declaration.children}}
|
||||
{{#unless @first}}
|
||||
<span class="tsd-signature-symbol">; </span>
|
||||
{{/unless}}
|
||||
{{name}}
|
||||
{{#if flags.isOptional }}
|
||||
<span class="tsd-signature-symbol">?: </span>
|
||||
{{else}}
|
||||
<span class="tsd-signature-symbol">: </span>
|
||||
{{/if}}
|
||||
{{#with type}}
|
||||
{{> type}}
|
||||
{{else}}
|
||||
<span class="tsd-signature-type">any</span>
|
||||
{{/with}}
|
||||
{{/each}}
|
||||
<span class="tsd-signature-symbol"> }</span>
|
||||
{{else if declaration.signatures}}
|
||||
{{#if (lookup declaration.signatures 1) }} {{! more than one signature}}
|
||||
<span class="tsd-signature-symbol">{ </span>
|
||||
{{#each declaration.signatures}}
|
||||
{{> member.signature.title hideName=true}}
|
||||
{{#unless @last}}
|
||||
<span class="tsd-signature-symbol">; </span>
|
||||
{{/unless}}
|
||||
{{/each}}
|
||||
<span class="tsd-signature-symbol"> }</span>
|
||||
{{else}}
|
||||
{{#if needsParens}}
|
||||
<span class="tsd-signature-symbol">(</span>
|
||||
{{/if}}
|
||||
{{#with (lookup declaration.signatures '0') }}
|
||||
{{> member.signature.title hideName=true arrowStyle=true}}
|
||||
{{/with}}
|
||||
{{#if needsParens}}
|
||||
<span class="tsd-signature-symbol">)</span>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<span class="tsd-signature-symbol">{}</span>
|
||||
{{/if}}
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline 'stringLiteral'}}
|
||||
<span class="tsd-signature-type">"{{value}}"</span>
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline 'tuple'}}
|
||||
<span class="tsd-signature-symbol">[</span>
|
||||
{{#each elements}}
|
||||
{{#unless @first}}
|
||||
<span class="tsd-signature-symbol">, </span>
|
||||
{{/unless}}
|
||||
{{> type}}
|
||||
{{/each}}
|
||||
<span class="tsd-signature-symbol">]</span>
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline 'typeOperator'}}
|
||||
<span class="tsd-signature-symbol">{{operator}} </span>
|
||||
{{#with target}}
|
||||
{{> type}}
|
||||
{{/with}}
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline 'typeParameter'}}
|
||||
<span class="tsd-signature-type">{{name}}</span>
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline 'union'}}
|
||||
{{#if needsParens}}
|
||||
<span class="tsd-signature-symbol">(</span>
|
||||
{{/if}}
|
||||
{{#each types}}
|
||||
{{#unless @first}}
|
||||
<span class="tsd-signature-symbol"> | </span>
|
||||
{{/unless}}
|
||||
{{> type needsParens=true}}
|
||||
{{/each}}
|
||||
{{#if needsParens}}
|
||||
<span class="tsd-signature-symbol">)</span>
|
||||
{{/if}}
|
||||
{{/inline}}
|
||||
|
||||
{{#*inline 'unknown'}}
|
||||
<span class="tsd-signature-type">{{name}}</span>
|
||||
{{/inline}}
|
||||
|
||||
{{#if this}}
|
||||
{{> (lookup . 'type') }}
|
||||
{{else}}
|
||||
<span class="tsd-signature-type">void</span>
|
||||
{{/if}}
|
@@ -1,42 +0,0 @@
|
||||
{{#compact}}
|
||||
{{#if this}}
|
||||
{{#if elementType}}
|
||||
{{#with elementType}}
|
||||
{{> typeAndParent}}
|
||||
{{/with}}
|
||||
[]
|
||||
{{else}}
|
||||
{{#if reflection}}
|
||||
{{#ifSignature reflection}}
|
||||
{{#if reflection.parent.parent.url}}
|
||||
<a href="{{relativeURL reflection.parent.parent.url}}">{{reflection.parent.parent.name}}</a>
|
||||
{{else}}
|
||||
{{reflection.parent.parent.name}}
|
||||
{{/if}}
|
||||
.
|
||||
{{#if reflection.parent.url}}
|
||||
<a href="{{relativeURL reflection.parent.url}}">{{reflection.parent.name}}</a>
|
||||
{{else}}
|
||||
{{reflection.parent.name}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{#if reflection.parent.url}}
|
||||
<a href="{{relativeURL reflection.parent.url}}">{{reflection.parent.name}}</a>
|
||||
{{else}}
|
||||
{{reflection.parent.name}}
|
||||
{{/if}}
|
||||
.
|
||||
{{#if reflection.url}}
|
||||
<a href="{{relativeURL reflection.url}}">{{reflection.name}}</a>
|
||||
{{else}}
|
||||
{{reflection.name}}
|
||||
{{/if}}
|
||||
{{/ifSignature}}
|
||||
{{else}}
|
||||
{{this}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
void
|
||||
{{/if}}
|
||||
{{/compact}}
|
@@ -1,14 +0,0 @@
|
||||
<ul class="tsd-type-parameters">
|
||||
{{#each typeParameters}}
|
||||
<li>
|
||||
<h4>{{#compact}}
|
||||
{{name}}
|
||||
{{#if type}}
|
||||
<span class="tsd-signature-symbol">: </span>
|
||||
{{#with type}}{{> type}}{{/with}}
|
||||
{{/if}}
|
||||
{{/compact}}</h4>
|
||||
{{> comment}}
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
@@ -1,3 +0,0 @@
|
||||
<div class="tsd-panel tsd-typography">
|
||||
{{#markdown}}{{{model.readme}}}{{/markdown}}
|
||||
</div>
|
@@ -1,81 +0,0 @@
|
||||
{{#with model}}
|
||||
{{#if hasComment}}
|
||||
<section class="tsd-panel tsd-comment">
|
||||
{{> comment}}
|
||||
</section>
|
||||
{{/if}}
|
||||
{{/with}}
|
||||
|
||||
{{#if model.typeParameters}}
|
||||
<section class="tsd-panel tsd-type-parameters">
|
||||
<h3>Type parameters</h3>
|
||||
{{#with model}}{{> typeParameters}}{{/with}}
|
||||
</section>
|
||||
{{/if}}
|
||||
|
||||
{{#if model.typeHierarchy}}
|
||||
<!--
|
||||
<section class="tsd-panel tsd-hierarchy">
|
||||
<h3>Hierarchy</h3>
|
||||
{{#with model.typeHierarchy}}{{> hierarchy}}{{/with}}
|
||||
</section>
|
||||
-->
|
||||
{{/if}}
|
||||
|
||||
{{#if model.implementedTypes}}
|
||||
<section class="tsd-panel">
|
||||
<h3>Implements</h3>
|
||||
<ul class="tsd-hierarchy">
|
||||
{{#each model.implementedTypes}}
|
||||
<li>{{#compact}}{{> type}}{{/compact}}</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</section>
|
||||
{{/if}}
|
||||
|
||||
{{#if model.implementedBy}}
|
||||
<section class="tsd-panel">
|
||||
<h3>Implemented by</h3>
|
||||
<ul class="tsd-hierarchy">
|
||||
{{#each model.implementedBy}}
|
||||
<li>{{#compact}}{{> type}}{{/compact}}</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</section>
|
||||
{{/if}}
|
||||
|
||||
{{#if model.signatures}}
|
||||
<section class="tsd-panel">
|
||||
<h3 class="tsd-before-signature">Callable</h3>
|
||||
{{#with model}}{{> member.signatures}}{{/with}}
|
||||
</section>
|
||||
{{/if}}
|
||||
|
||||
{{#if model.indexSignature}}
|
||||
<section class="tsd-panel {{model.cssClasses}}">
|
||||
<h3 class="tsd-before-signature">Indexable</h3>
|
||||
<div class="tsd-signature tsd-kind-icon">{{#compact}}
|
||||
<span class="tsd-signature-symbol">[</span>
|
||||
{{#each model.indexSignature.parameters}}
|
||||
{{name}}: {{#with type}}{{>type}}{{/with}}
|
||||
{{/each}}
|
||||
<span class="tsd-signature-symbol">]: </span>
|
||||
{{#with model.indexSignature.type}}{{>type}}{{/with}}
|
||||
{{/compact}}</div>
|
||||
|
||||
{{#with model.indexSignature}}
|
||||
{{> comment}}
|
||||
{{/with}}
|
||||
|
||||
{{#if model.indexSignature.type.declaration}}
|
||||
{{#with model.indexSignature.type.declaration}}
|
||||
{{> parameter}}
|
||||
{{/with}}
|
||||
{{/if}}
|
||||
</section>
|
||||
{{/if}}
|
||||
|
||||
{{#with model}}
|
||||
{{> index}}
|
||||
{{> members}}
|
||||
{{/with}}
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 300 KiB |
@@ -1,109 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
sodipodi:docname="disegno.svg"
|
||||
inkscape:version="1.0rc1 (09960d6, 2020-04-09)"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 70 70"
|
||||
height="70"
|
||||
width="70">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:window-y="25"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-height="775"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:guide-bbox="true"
|
||||
showguides="true"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:showpageshadow="false"
|
||||
showborder="true"
|
||||
showgrid="false"
|
||||
inkscape:document-rotation="0"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:document-units="px"
|
||||
inkscape:cy="39.253064"
|
||||
inkscape:cx="25.246811"
|
||||
inkscape:zoom="5.8562241"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
borderopacity="1.0"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#ffffff"
|
||||
id="base"
|
||||
units="px">
|
||||
<sodipodi:guide
|
||||
inkscape:color="rgb(0,0,255)"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
id="guide1932"
|
||||
orientation="-1,0"
|
||||
position="12,70" />
|
||||
<sodipodi:guide
|
||||
inkscape:color="rgb(0,0,255)"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
id="guide1934"
|
||||
orientation="-1,0"
|
||||
position="58,70" />
|
||||
<sodipodi:guide
|
||||
inkscape:color="rgb(0,0,255)"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
id="guide1936"
|
||||
orientation="0,1"
|
||||
position="0,58" />
|
||||
<sodipodi:guide
|
||||
inkscape:color="rgb(0,0,255)"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
id="guide1938"
|
||||
orientation="0,1"
|
||||
position="0,12" />
|
||||
<sodipodi:guide
|
||||
inkscape:color="rgb(0,0,255)"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
id="guide2021"
|
||||
orientation="-1,0"
|
||||
position="35,70" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Livello 1">
|
||||
<path
|
||||
inkscape:transform-center-y="23.027731"
|
||||
inkscape:transform-center-x="-17.510929"
|
||||
id="path30"
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.133334;stop-opacity:1"
|
||||
d="M 52.1731,12 H 35.107236 c -0.161294,0 -0.291666,0.130494 -0.291666,0.291543 v 5.419239 c 0,0.182381 0.147678,0.330176 0.330178,0.330176 h 2.339824 c 0.94638,0 1.713811,0.727936 1.795988,1.652976 v 3.715485 2.069989 19.715998 0.139708 h -6.44e-4 c 0.0058,0.206545 -0.0023,0.409658 -0.02244,0.609702 -0.0023,0.02918 -0.0062,0.05801 -0.0097,0.08697 -0.01349,0.116897 -0.02846,0.233161 -0.05114,0.346981 -0.01243,0.06489 -0.02993,0.128044 -0.0455,0.191949 -0.02097,0.08499 -0.0379,0.171342 -0.06401,0.254505 -0.1543,0.493916 -0.39825,0.95202 -0.735666,1.355297 -0.01243,0.01438 -0.02771,0.02761 -0.03998,0.04182 -0.102908,0.119222 -0.210962,0.235367 -0.330548,0.34416 -0.120695,0.109778 -0.248492,0.211819 -0.382795,0.306628 -0.954719,0.676302 -2.23974,0.973854 -3.6755,0.836485 -1.830697,-0.172088 -3.646921,-1.002309 -5.114939,-2.337984 -1.467772,-1.335554 -2.380422,-2.988039 -2.569305,-4.653525 -0.169868,-1.489971 0.276578,-2.801116 1.256197,-3.692426 0.0027,-0.0019 0.005,-0.0037 0.0069,-0.0058 0.0379,-0.03398 0.0796,-0.06379 0.1186,-0.09654 0.701076,-0.58738 1.614951,-0.943313 2.657858,-1.041435 0.01172,-0.0011 0.02306,-0.003 0.03423,-0.0039 0.109777,-0.0097 0.221631,-0.01402 0.334471,-0.01827 0.05899,-0.0019 0.117251,-0.0062 0.177111,-0.0065 0.01986,-2.76e-4 0.03875,-0.0023 0.05864,-0.0023 0.03557,0 0.07248,0.0046 0.108055,0.0051 0.164347,0.0027 0.329933,0.0094 0.498825,0.02379 0.02134,0.0017 0.0417,9.78e-4 0.06365,0.003 0.01562,0.0016 0.03103,0.005 0.04662,0.0065 0.956682,0.09592 1.90392,0.381568 2.802834,0.814406 0.01876,8.39e-4 0.04047,0.0065 0.06759,0.02159 0.274004,0.151353 0.326498,-0.01101 0.334593,-0.118351 v -4.688237 -3.46883 c 0,-0.233653 -0.162519,-0.440321 -0.3904,-0.490484 -4.841795,-1.065597 -9.592336,0.04355 -12.944402,3.09499 -2.928307,2.663747 -4.344811,6.507647 -3.885849,10.545461 0.409535,3.596512 2.255685,7.05173 5.198956,9.730318 2.868698,2.609903 6.521262,4.242028 10.288996,4.596993 0.519184,0.04805 1.040822,0.07283 1.549826,0.07283 3.598351,0 6.937296,-1.233851 9.401735,-3.475688 2.33455,-2.125552 3.732902,-5.044294 3.938097,-8.219619 l 0.01901,-20.825138 h 0.0021 V 19.91155 h 7.7e-4 v -0.09714 c 0.02109,-0.982682 0.822378,-1.773296 1.81046,-1.773296 h 2.339824 c 0.182259,0 0.330177,-0.147802 0.330177,-0.330177 v -5.419299 c -2.1e-5,-0.161046 -0.130406,-0.291543 -0.291686,-0.291543"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<inkscape:templateinfo>
|
||||
<inkscape:name>SmallTile</inkscape:name>
|
||||
<inkscape:shortdesc>Small tile</inkscape:shortdesc>
|
||||
<inkscape:date>2020-04-15</inkscape:date>
|
||||
</inkscape:templateinfo>
|
||||
</svg>
|
Before Width: | Height: | Size: 5.4 KiB |
@@ -1,109 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
sodipodi:docname="disegno-1.svg"
|
||||
inkscape:version="1.0rc1 (09960d6, 2020-04-09)"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 150 150"
|
||||
height="150"
|
||||
width="150">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:window-y="25"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-height="775"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:guide-bbox="true"
|
||||
showguides="true"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:showpageshadow="false"
|
||||
showborder="true"
|
||||
showgrid="false"
|
||||
inkscape:document-rotation="0"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:document-units="px"
|
||||
inkscape:cy="79.075594"
|
||||
inkscape:cx="91.835957"
|
||||
inkscape:zoom="3.1892627"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
borderopacity="1.0"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#ffffff"
|
||||
id="base"
|
||||
units="px">
|
||||
<sodipodi:guide
|
||||
inkscape:color="rgb(0,0,255)"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
id="guide1919"
|
||||
orientation="0,1"
|
||||
position="0,115" />
|
||||
<sodipodi:guide
|
||||
inkscape:color="rgb(0,0,255)"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
id="guide1921"
|
||||
orientation="-1,0"
|
||||
position="25,150" />
|
||||
<sodipodi:guide
|
||||
inkscape:color="rgb(0,0,255)"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
id="guide1923"
|
||||
orientation="-1,0"
|
||||
position="125,150" />
|
||||
<sodipodi:guide
|
||||
inkscape:color="rgb(0,0,255)"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
id="guide1925"
|
||||
orientation="0,1"
|
||||
position="0,35" />
|
||||
<sodipodi:guide
|
||||
inkscape:color="rgb(0,0,255)"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
id="guide2879"
|
||||
orientation="-1,0"
|
||||
position="75,150" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Livello 1">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="M 105.30102,35.000001 H 75.621261 c -0.280511,0 -0.507245,0.226946 -0.507245,0.507031 v 9.424762 c 0,0.317185 0.256831,0.574219 0.574223,0.574219 h 4.069258 c 1.645878,0 2.980541,1.265976 3.123457,2.874741 v 6.461712 3.599981 34.288687 0.24297 h -0.0011 c 0.01009,0.359209 -0.004,0.712449 -0.03903,1.060352 -0.004,0.05075 -0.01078,0.100887 -0.01687,0.151252 -0.02346,0.203299 -0.0495,0.405497 -0.08894,0.603445 -0.02162,0.112852 -0.05205,0.222685 -0.07913,0.333824 -0.03647,0.147809 -0.06591,0.297986 -0.111322,0.442618 -0.268348,0.858984 -0.692608,1.655686 -1.279419,2.357038 -0.02162,0.02501 -0.04819,0.04802 -0.06953,0.07273 -0.178971,0.207343 -0.366891,0.409334 -0.574866,0.598539 -0.209904,0.190918 -0.43216,0.368381 -0.66573,0.533266 -1.660381,1.176182 -3.8952,1.693662 -6.392174,1.454752 -3.18382,-0.29928 -6.34247,-1.743142 -8.895544,-4.066054 -2.552647,-2.322703 -4.139864,-5.196589 -4.468356,-8.093086 -0.295423,-2.591254 0.481005,-4.871506 2.18469,-6.42161 0.0047,-0.0033 0.0087,-0.0064 0.012,-0.01009 0.06591,-0.05909 0.138435,-0.110939 0.206261,-0.167895 1.219262,-1.021531 2.80861,-1.640544 4.622361,-1.811191 0.02038,-0.0019 0.0401,-0.0052 0.05953,-0.0068 0.190917,-0.01687 0.385445,-0.02438 0.581689,-0.03177 0.102591,-0.0033 0.203915,-0.01078 0.308019,-0.0113 0.03454,-4.8e-4 0.06739,-0.004 0.101982,-0.004 0.06186,0 0.126053,0.008 0.187922,0.0089 0.285821,0.0047 0.573797,0.01635 0.867522,0.04137 0.03711,0.003 0.07252,0.0017 0.110695,0.0052 0.02717,0.0028 0.05397,0.0087 0.08108,0.0113 1.663794,0.166817 3.311164,0.663596 4.874493,1.416358 0.03263,0.0015 0.07038,0.0113 0.117548,0.03755 0.476528,0.263222 0.567822,-0.01915 0.581901,-0.205828 V 73.11952 67.086773 c 0,-0.406353 -0.282642,-0.765776 -0.678957,-0.853016 -8.420512,-1.853212 -16.682323,0.07574 -22.512002,5.382591 -5.092707,4.632602 -7.556192,11.317645 -6.757997,18.339929 0.712234,6.254803 3.92293,12.263883 9.041661,16.922293 4.989039,4.53896 11.341325,7.37744 17.893905,7.99477 0.902929,0.0836 1.810125,0.12666 2.69535,0.12666 6.258001,0 12.064861,-2.14583 16.350841,-6.04467 4.060086,-3.69661 6.492006,-8.77269 6.848866,-14.294994 l 0.0331,-36.217627 h 0.004 v -9.683497 h 10e-4 v -0.16894 c 0.0367,-1.709012 1.43023,-3.083992 3.148627,-3.083992 h 4.06926 c 0.31697,0 0.57422,-0.257047 0.57422,-0.574221 v -9.424867 c -4e-5,-0.28008 -0.22679,-0.507031 -0.50728,-0.507031"
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.133334;stop-opacity:1"
|
||||
id="path30"
|
||||
inkscape:transform-center-x="-30.453831"
|
||||
inkscape:transform-center-y="40.048222" />
|
||||
</g>
|
||||
<inkscape:templateinfo>
|
||||
<inkscape:name>Square150x150Logo</inkscape:name>
|
||||
<inkscape:shortdesc>Medium tile</inkscape:shortdesc>
|
||||
<inkscape:date>2020-04-15</inkscape:date>
|
||||
</inkscape:templateinfo>
|
||||
</svg>
|
Before Width: | Height: | Size: 5.4 KiB |
2
Assets/TinyMCE/IconPack/.gitignore
vendored
@@ -1,2 +0,0 @@
|
||||
node_modules
|
||||
dist
|
Before Width: | Height: | Size: 97 KiB |
@@ -1,19 +0,0 @@
|
||||
# Joplin TinyMCE Icon Pack
|
||||
|
||||
Created from template: https://raw.githubusercontent.com/tinymce/oxide-icon-pack-template
|
||||
|
||||
## Adding an icon
|
||||
|
||||
- Get it from [Fork Awesome](https://forkaweso.me/)
|
||||
- Using https://vectr.com/Resize Resize vector graphics to between 15x15 to 20x20 max. Set page dimensions to 24x24 pixels
|
||||
- Save to src/svg
|
||||
|
||||

|
||||
|
||||
## Building
|
||||
|
||||
Open a terminal and navigate to the project folder, then
|
||||
|
||||
1. Install dependencies using `npm install`.
|
||||
2. Place your icons in `src/svg`
|
||||
3. Run `gulp` to build the icon pack
|
@@ -1,27 +0,0 @@
|
||||
const iconPackager = require('@ephox/oxide-icons-tools').iconPackager;
|
||||
const clean = require('gulp-clean');
|
||||
const gulp = require('gulp');
|
||||
const fs = require('fs');
|
||||
|
||||
gulp.task('icon-packager', function() {
|
||||
const contents = fs.readFileSync('package.json');
|
||||
const name = JSON.parse(contents).iconPackName;
|
||||
|
||||
return gulp.src('src/svg/**/*.svg')
|
||||
.pipe(iconPackager({ name }))
|
||||
.pipe(gulp.dest('dist'));
|
||||
});
|
||||
|
||||
gulp.task('deploy', function() {
|
||||
fs.copyFileSync(`${__dirname}/dist/icons/Joplin/icons.js`, `${__dirname}/../../../packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/icons.js`);
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
gulp.task('clean', function() {
|
||||
return gulp.src('./dist', {
|
||||
read: false,
|
||||
allowEmpty: true,
|
||||
}).pipe(clean());
|
||||
});
|
||||
|
||||
gulp.task('default', gulp.series('clean', 'icon-packager', 'deploy'));
|
4116
Assets/TinyMCE/IconPack/package-lock.json
generated
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"name": "oxide-icon-pack-template",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"postinstall": "node postinstall.js"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@ephox/oxide-icons-tools": "^2.1.1",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-clean": "^0.4.0",
|
||||
"prompts": "^2.2.1"
|
||||
},
|
||||
"iconPackName": "Joplin"
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
const prompts = require('prompts');
|
||||
const fs = require('fs');
|
||||
|
||||
(async function() {
|
||||
const response = await prompts({
|
||||
type: 'text',
|
||||
name: 'iconPackName',
|
||||
message: 'Enter the name of the icon pack.',
|
||||
validate: function(iconPackName) { return iconPackName.length > 0; },
|
||||
});
|
||||
|
||||
try {
|
||||
const contents = fs.readFileSync('package.json');
|
||||
obj = JSON.parse(contents);
|
||||
obj.iconPackName = response.iconPackName;
|
||||
fs.writeFileSync('package.json', JSON.stringify(obj, undefined, 2));
|
||||
} catch (err) {
|
||||
console.error(err.message);
|
||||
}
|
||||
})();
|
@@ -1,3 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24" width="24" height="24"><defs><path d="M17.53 21.82C16.44 21.82 15.38 21.35 14.61 20.58C13.64 19.61 5.91 11.89 4.95 10.93C4.07 10.03 3.54 8.82 3.54 7.56C3.54 4.92 5.62 2.82 8.26 2.82C9.52 2.82 10.74 3.33 11.65 4.23C12.4 4.98 18.42 11.01 19.18 11.76C19.25 11.84 19.3 11.94 19.3 12.04C19.3 12.3 18.6 12.99 18.34 12.99C18.23 12.99 18.13 12.94 18.06 12.87C17.3 12.11 11.27 6.08 10.52 5.32C9.92 4.74 9.11 4.36 8.27 4.36C6.5 4.36 5.14 5.79 5.14 7.55C5.14 8.39 5.48 9.2 6.08 9.8C7.05 10.76 14.77 18.49 15.73 19.46C16.2 19.93 16.86 20.24 17.53 20.24C18.59 20.24 19.37 19.46 19.37 18.4C19.37 17.72 19.06 17.07 18.59 16.6C17.87 15.88 12.09 10.1 11.37 9.38C11.17 9.19 10.89 9.08 10.62 9.08C10.15 9.08 9.79 9.42 9.79 9.91C9.79 10.18 9.91 10.44 10.1 10.64C10.61 11.15 14.69 15.23 15.2 15.74C15.27 15.82 15.32 15.92 15.32 16.02C15.32 16.28 14.61 16.99 14.35 16.99C14.25 16.99 14.15 16.94 14.08 16.86C13.57 16.35 9.49 12.27 8.98 11.76C8.48 11.28 8.19 10.59 8.19 9.91C8.19 8.54 9.26 7.47 10.63 7.47C11.33 7.47 12 7.76 12.48 8.26C13.21 8.98 18.99 14.76 19.71 15.48C20.49 16.25 20.95 17.31 20.95 18.4C20.95 20.34 19.47 21.82 17.53 21.82Z" id="a3MUovWvUV"></path></defs><g><g><g><use xlink:href="#a3MUovWvUV" opacity="1" fill="#000000" fill-opacity="1"></use><g><use xlink:href="#a3MUovWvUV" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g></g></g></svg>
|
Before Width: | Height: | Size: 1.6 KiB |
14
Assets/TinyMCE/JoplinLists/.gitignore
vendored
@@ -1,14 +0,0 @@
|
||||
.DS_Store
|
||||
*~
|
||||
*.iws
|
||||
*.sublime-workspace
|
||||
.cache
|
||||
/lib
|
||||
/dist
|
||||
/scratch
|
||||
node_modules
|
||||
/config/repl
|
||||
/*.log
|
||||
ephox-*.tgz
|
||||
package-lock.json
|
||||
jenkins-plumbing
|
@@ -1,196 +0,0 @@
|
||||
const { CheckerPlugin } = require('awesome-typescript-loader');
|
||||
const LiveReloadPlugin = require('webpack-livereload-plugin');
|
||||
const path = require('path');
|
||||
const swag = require('@ephox/swag');
|
||||
|
||||
module.exports = function(grunt) {
|
||||
const packageData = grunt.file.readJSON('package.json');
|
||||
const BUILD_VERSION = `${packageData.version}-${process.env.BUILD_NUMBER ? process.env.BUILD_NUMBER : '0'}`;
|
||||
const libPluginPath = 'lib/Main.js';
|
||||
const scratchPluginPath = 'scratch/compiled/joplinLists.js';
|
||||
const scratchPluginMinPath = 'scratch/compiled/joplinLists.min.js';
|
||||
const tsDemoSourceFile = path.resolve('src/demo/ts/Demo.ts');
|
||||
const jsDemoDestFile = path.resolve('scratch/compiled/demo.js');
|
||||
|
||||
grunt.initConfig({
|
||||
pkg: packageData,
|
||||
|
||||
clean: {
|
||||
dirs: ['dist', 'scratch'],
|
||||
},
|
||||
|
||||
// tslint: {
|
||||
// options: {
|
||||
// configuration: 'tslint.json'
|
||||
// },
|
||||
// plugin: ['src/**/*.ts']
|
||||
// },
|
||||
|
||||
shell: {
|
||||
command: 'tsc --project tsconfig.json',
|
||||
},
|
||||
|
||||
rollup: {
|
||||
options: {
|
||||
treeshake: true,
|
||||
external: [
|
||||
'tinymce/core/api/PluginManager',
|
||||
'tinymce/core/api/util/Tools',
|
||||
'tinymce/core/api/dom/BookmarkManager',
|
||||
'tinymce/core/api/Editor',
|
||||
'tinymce/core/api/dom/DOMUtils',
|
||||
'tinymce/core/api/dom/RangeUtils',
|
||||
'tinymce/core/api/dom/TreeWalker',
|
||||
'tinymce/core/api/util/VK',
|
||||
'tinymce/core/api/dom/DomQuery',
|
||||
],
|
||||
globals: {
|
||||
'tinymce/core/api/PluginManager': 'tinymce.PluginManager',
|
||||
'tinymce/core/api/util/Tools': 'tinymce.util.Tools',
|
||||
'tinymce/core/api/dom/BookmarkManager': 'tinymce.dom.BookmarkManager',
|
||||
'tinymce/core/api/Editor': 'tinymce.Editor',
|
||||
'tinymce/core/api/dom/DOMUtils': 'tinymce.dom.DOMUtils',
|
||||
'tinymce/core/api/dom/RangeUtils': 'tinymce.dom.RangeUtils',
|
||||
'tinymce/core/api/dom/TreeWalker': 'tinymce.dom.TreeWalker',
|
||||
'tinymce/core/api/util/VK': 'tinymce.util.VK',
|
||||
'tinymce/core/api/dom/DomQuery': 'tinymce.dom.DomQuery',
|
||||
},
|
||||
format: 'iife',
|
||||
onwarn: swag.onwarn,
|
||||
plugins: [
|
||||
swag.nodeResolve({
|
||||
basedir: __dirname,
|
||||
prefixes: {},
|
||||
}),
|
||||
swag.remapImports(),
|
||||
],
|
||||
},
|
||||
plugin: {
|
||||
files: [
|
||||
{
|
||||
src: libPluginPath,
|
||||
dest: scratchPluginPath,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
uglify: {
|
||||
plugin: {
|
||||
files: [
|
||||
{
|
||||
src: scratchPluginPath,
|
||||
dest: scratchPluginMinPath,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
concat: {
|
||||
license: {
|
||||
options: {
|
||||
process: function(src) {
|
||||
const buildSuffix = process.env.BUILD_NUMBER
|
||||
? `-${process.env.BUILD_NUMBER}`
|
||||
: '';
|
||||
return src.replace(
|
||||
/@BUILD_NUMBER@/g,
|
||||
packageData.version + buildSuffix
|
||||
);
|
||||
},
|
||||
},
|
||||
// scratchPluginMinPath is used twice on purpose, all outputs will be minified for premium plugins
|
||||
files: {
|
||||
'dist/joplinLists.js': [
|
||||
'src/text/license-header.js',
|
||||
scratchPluginPath,
|
||||
],
|
||||
'dist/joplinLists.min.js': [
|
||||
'src/text/license-header.js',
|
||||
scratchPluginMinPath,
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
copy: {
|
||||
css: {
|
||||
files: [
|
||||
// {
|
||||
// cwd: 'src/text',
|
||||
// src: ['license.txt'],
|
||||
// dest: 'dist',
|
||||
// expand: true,
|
||||
// },
|
||||
// { src: ['changelog.txt'], dest: 'dist', expand: true },
|
||||
{
|
||||
src: ['dist/joplinLists.js'],
|
||||
dest: '../../../packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/plugins/lists.js',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
webpack: {
|
||||
options: {
|
||||
mode: 'development',
|
||||
watch: true,
|
||||
},
|
||||
dev: {
|
||||
entry: tsDemoSourceFile,
|
||||
devtool: 'source-map',
|
||||
|
||||
resolve: {
|
||||
extensions: ['.ts', '.js'],
|
||||
},
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
use: ['source-map-loader'],
|
||||
enforce: 'pre',
|
||||
},
|
||||
{
|
||||
test: /\.ts$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'ts-loader',
|
||||
options: {
|
||||
transpileOnly: true,
|
||||
experimentalWatchApi: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
plugins: [new LiveReloadPlugin(), new CheckerPlugin()],
|
||||
|
||||
output: {
|
||||
filename: path.basename(jsDemoDestFile),
|
||||
path: path.dirname(jsDemoDestFile),
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
require('load-grunt-tasks')(grunt);
|
||||
grunt.loadNpmTasks('@ephox/swag');
|
||||
|
||||
// grunt.registerTask('version', 'Creates a version file', function() {
|
||||
// grunt.file.write('dist/version.txt', BUILD_VERSION);
|
||||
// });
|
||||
|
||||
grunt.registerTask('default', [
|
||||
'clean',
|
||||
// 'tslint',
|
||||
'shell',
|
||||
'rollup',
|
||||
'uglify',
|
||||
'concat',
|
||||
'copy',
|
||||
// 'version',
|
||||
]);
|
||||
};
|
@@ -1,502 +0,0 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
@@ -1,13 +0,0 @@
|
||||
# TinyMCE Joplin Lists Plugin
|
||||
|
||||
**As of 2020-11-02 this module no longer builds (a ton of TypeScript errors). No idea why since nothing was changed but should be investigated if modifying this plugin is ever needed.**
|
||||
|
||||
This is based on https://github.com/tinymce/tinymce/tree/59748a11303fb7cf00fdb8c9392dcb082ee9d965/modules/tinymce/src/plugins/lists
|
||||
|
||||
But with support for Joplin checkboxes.
|
||||
|
||||
## Building
|
||||
|
||||
Use `npm i && npm run build` to build the plugin, which will also copy the compiled version to the right packages/app-desktop sub-directory.
|
||||
|
||||
To test the plugin, use `npm run buildAndStart`, which will build the plugin and start the desktop application.
|
57
Assets/TinyMCE/JoplinLists/global.d.ts
vendored
@@ -1,57 +0,0 @@
|
||||
declare module 'tinymce/core/api/util/Tools' {
|
||||
const Tools:any;
|
||||
export default Tools;
|
||||
}
|
||||
|
||||
declare module 'tinymce/core/api/Editor' {
|
||||
export default interface Editor {
|
||||
on: Function,
|
||||
off: Function,
|
||||
execCommand: Function,
|
||||
getBody: Function,
|
||||
getParam: Function,
|
||||
fire: Function,
|
||||
nodeChanged: Function,
|
||||
selection: any,
|
||||
contentDocument: any,
|
||||
dom: any,
|
||||
schema: any,
|
||||
undoManager: any,
|
||||
ui: any,
|
||||
}
|
||||
}
|
||||
|
||||
declare module 'tinymce/core/api/dom/BookmarkManager' {
|
||||
const BookmarkManager:any;
|
||||
export default BookmarkManager;
|
||||
}
|
||||
|
||||
declare module 'tinymce/core/api/dom/DOMUtils' {
|
||||
const DOMUtils:any;
|
||||
export default DOMUtils;
|
||||
}
|
||||
|
||||
declare module 'tinymce/core/api/dom/RangeUtils' {
|
||||
const RangeUtils:any;
|
||||
export default RangeUtils;
|
||||
}
|
||||
|
||||
declare module 'tinymce/core/api/dom/TreeWalker' {
|
||||
const TreeWalker:any;
|
||||
export default TreeWalker;
|
||||
}
|
||||
|
||||
declare module 'tinymce/core/api/util/VK' {
|
||||
const VK:any;
|
||||
export default VK;
|
||||
}
|
||||
|
||||
declare module 'tinymce/core/api/dom/DomQuery' {
|
||||
const DomQuery:any;
|
||||
export default DomQuery;
|
||||
}
|
||||
|
||||
declare module 'tinymce/core/api/PluginManager' {
|
||||
const PluginManager:any;
|
||||
export default PluginManager;
|
||||
}
|
@@ -1,54 +0,0 @@
|
||||
{
|
||||
"name": "joplin-tinymce-lists",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"scripts": {
|
||||
"prepublishOnly": "npm run lint && npm run build",
|
||||
"lint": "tslint src/**/*.ts",
|
||||
"build": "grunt",
|
||||
"test": "bedrock-auto -b phantomjs -d src/test/ts/",
|
||||
"test-manual": "bedrock -d src/test/ts/",
|
||||
"start": "grunt webpack",
|
||||
"buildAndStart": "yarn build && cd .. && cd .. && cd .. && cd packages/app-desktop && npm start"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "Tiny Technologies Inc.",
|
||||
"devDependencies": {
|
||||
"@ephox/agar": "latest",
|
||||
"@ephox/bedrock": "latest",
|
||||
"@ephox/mcagar": "latest",
|
||||
"@ephox/swag": "latest",
|
||||
"@ephox/tslint-rules": "latest",
|
||||
"awesome-typescript-loader": "^5.2.1",
|
||||
"grunt": "^1.0.4",
|
||||
"grunt-contrib-clean": "^2.0.0",
|
||||
"grunt-contrib-concat": "^1.0.1",
|
||||
"grunt-contrib-copy": "^1.0.0",
|
||||
"grunt-contrib-uglify": "^4.0.0",
|
||||
"grunt-shell": "^2.1.0",
|
||||
"grunt-tslint": "^5.0.2",
|
||||
"grunt-webpack": "^3.1.3",
|
||||
"load-grunt-tasks": "^4.0.0",
|
||||
"tinymce": "latest",
|
||||
"ts-loader": "^5.3.0",
|
||||
"tslib": "^1.9.3",
|
||||
"tslint": "^5.11.0",
|
||||
"typescript": "^3.1.6",
|
||||
"webpack": "^4.25.1",
|
||||
"webpack-livereload-plugin": "^2.1.1"
|
||||
},
|
||||
"files": [
|
||||
"lib/main",
|
||||
"lib/demo",
|
||||
"lib/test",
|
||||
"src",
|
||||
"tsconfig.json",
|
||||
"readme.md",
|
||||
"LEGAL.txt",
|
||||
"LICENSE.txt"
|
||||
],
|
||||
"main": "./lib/main/ts/api/Main.js",
|
||||
"module": "./lib/main/ts/api/Main.js",
|
||||
"types": "./lib/main/ts/api/Main.d.ts",
|
||||
"license": "Apache-2.0"
|
||||
}
|
@@ -1,16 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import Plugin from './Plugin';
|
||||
|
||||
Plugin();
|
||||
|
||||
/*******
|
||||
* DO NOT EXPORT ANYTHING
|
||||
*
|
||||
* IF YOU DO ROLLUP WILL LEAVE A GLOBAL ON THE PAGE
|
||||
*******/
|
@@ -1,22 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import PluginManager from 'tinymce/core/api/PluginManager';
|
||||
import * as Api from './api/Api';
|
||||
import * as Commands from './api/Commands';
|
||||
import * as Keyboard from './core/Keyboard';
|
||||
import * as Buttons from './ui/Buttons';
|
||||
|
||||
export default function () {
|
||||
PluginManager.add('joplinLists', function (editor) {
|
||||
Keyboard.setup(editor);
|
||||
Buttons.register(editor);
|
||||
Commands.register(editor);
|
||||
|
||||
return Api.get(editor);
|
||||
});
|
||||
}
|
@@ -1,53 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import { Arr } from '@ephox/katamari';
|
||||
import { Element} from '@ephox/sugar';
|
||||
import Editor from 'tinymce/core/api/Editor';
|
||||
import { Indentation } from '../listModel/Indentation';
|
||||
import { listIndentation } from '../listModel/ListsIndendation';
|
||||
import { dlIndentation } from '../core/DlIndentation';
|
||||
import * as Range from '../core/Range';
|
||||
import * as Selection from '../core/Selection';
|
||||
|
||||
const selectionIndentation = (editor: Editor, indentation: Indentation): boolean => {
|
||||
const lists = Arr.map(Selection.getSelectedListRoots(editor), Element.fromDom);
|
||||
const dlItems = Arr.map(Selection.getSelectedDlItems(editor), Element.fromDom);
|
||||
let isHandled = false;
|
||||
|
||||
if (lists.length || dlItems.length) {
|
||||
const bookmark = editor.selection.getBookmark();
|
||||
|
||||
listIndentation(editor, lists, indentation);
|
||||
dlIndentation(editor, indentation, dlItems);
|
||||
|
||||
editor.selection.moveToBookmark(bookmark);
|
||||
editor.selection.setRng(Range.normalizeRange(editor.selection.getRng()));
|
||||
editor.nodeChanged();
|
||||
isHandled = true;
|
||||
}
|
||||
|
||||
return isHandled;
|
||||
};
|
||||
|
||||
const indentListSelection = (editor: Editor): boolean => {
|
||||
return selectionIndentation(editor, Indentation.Indent);
|
||||
};
|
||||
|
||||
const outdentListSelection = (editor: Editor): boolean => {
|
||||
return selectionIndentation(editor, Indentation.Outdent);
|
||||
};
|
||||
|
||||
const flattenListSelection = (editor: Editor): boolean => {
|
||||
return selectionIndentation(editor, Indentation.Flatten);
|
||||
};
|
||||
|
||||
export {
|
||||
indentListSelection,
|
||||
outdentListSelection,
|
||||
flattenListSelection
|
||||
};
|
@@ -1,307 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import BookmarkManager from 'tinymce/core/api/dom/BookmarkManager';
|
||||
import Tools from 'tinymce/core/api/util/Tools';
|
||||
import * as Bookmark from '../core/Bookmark';
|
||||
import * as NodeType from '../core/NodeType';
|
||||
import * as Selection from '../core/Selection';
|
||||
import { HTMLElement } from '@ephox/dom-globals';
|
||||
import { flattenListSelection } from './Indendation';
|
||||
import { fireListEvent } from '../api/Events';
|
||||
import { isCustomList } from '../core/Util';
|
||||
import Editor from 'tinymce/core/api/Editor';
|
||||
import { listToggleActionFromListName } from '../core/ListAction';
|
||||
import { findContainerListTypeFromElement } from '../listModel/JoplinListUtil';
|
||||
|
||||
const updateListStyle = function (dom, el, detail) {
|
||||
const type = detail['list-style-type'] ? detail['list-style-type'] : null;
|
||||
dom.setStyle(el, 'list-style-type', type);
|
||||
};
|
||||
|
||||
const setAttribs = function (elm, attrs) {
|
||||
Tools.each(attrs, function (value, key) {
|
||||
elm.setAttribute(key, value);
|
||||
});
|
||||
};
|
||||
|
||||
const updateListAttrs = function (dom, el, detail) {
|
||||
setAttribs(el, detail['list-attributes']);
|
||||
Tools.each(dom.select('li', el), function (li) {
|
||||
setAttribs(li, detail['list-item-attributes']);
|
||||
});
|
||||
};
|
||||
|
||||
const updateListWithDetails = function (dom, el, detail) {
|
||||
updateListStyle(dom, el, detail);
|
||||
updateListAttrs(dom, el, detail);
|
||||
|
||||
if (detail.listType === 'joplinChecklist') {
|
||||
el.classList.add('joplin-checklist');
|
||||
} else {
|
||||
el.classList.remove('joplin-checklist');
|
||||
}
|
||||
};
|
||||
|
||||
const removeStyles = (dom, element: HTMLElement, styles: string[]) => {
|
||||
Tools.each(styles, (style) => dom.setStyle(element, { [style]: '' }));
|
||||
};
|
||||
|
||||
const getEndPointNode = function (editor, rng, start, root) {
|
||||
let container, offset;
|
||||
|
||||
container = rng[start ? 'startContainer' : 'endContainer'];
|
||||
offset = rng[start ? 'startOffset' : 'endOffset'];
|
||||
|
||||
// Resolve node index
|
||||
if (container.nodeType === 1) {
|
||||
container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container;
|
||||
}
|
||||
|
||||
if (!start && NodeType.isBr(container.nextSibling)) {
|
||||
container = container.nextSibling;
|
||||
}
|
||||
|
||||
while (container.parentNode !== root) {
|
||||
if (NodeType.isTextBlock(editor, container)) {
|
||||
return container;
|
||||
}
|
||||
|
||||
if (/^(TD|TH)$/.test(container.parentNode.nodeName)) {
|
||||
return container;
|
||||
}
|
||||
|
||||
container = container.parentNode;
|
||||
}
|
||||
|
||||
return container;
|
||||
};
|
||||
|
||||
const getSelectedTextBlocks = function (editor, rng, root) {
|
||||
const textBlocks = [], dom = editor.dom;
|
||||
|
||||
const startNode = getEndPointNode(editor, rng, true, root);
|
||||
const endNode = getEndPointNode(editor, rng, false, root);
|
||||
let block;
|
||||
const siblings = [];
|
||||
|
||||
for (let node = startNode; node; node = node.nextSibling) {
|
||||
siblings.push(node);
|
||||
|
||||
if (node === endNode) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Tools.each(siblings, function (node) {
|
||||
if (NodeType.isTextBlock(editor, node)) {
|
||||
textBlocks.push(node);
|
||||
block = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (dom.isBlock(node) || NodeType.isBr(node)) {
|
||||
if (NodeType.isBr(node)) {
|
||||
dom.remove(node);
|
||||
}
|
||||
|
||||
block = null;
|
||||
return;
|
||||
}
|
||||
|
||||
const nextSibling = node.nextSibling;
|
||||
if (BookmarkManager.isBookmarkNode(node)) {
|
||||
if (NodeType.isTextBlock(editor, nextSibling) || (!nextSibling && node.parentNode === root)) {
|
||||
block = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!block) {
|
||||
block = dom.create('p');
|
||||
node.parentNode.insertBefore(block, node);
|
||||
textBlocks.push(block);
|
||||
}
|
||||
|
||||
block.appendChild(node);
|
||||
});
|
||||
|
||||
return textBlocks;
|
||||
};
|
||||
|
||||
const hasCompatibleStyle = function (dom, sib, detail) {
|
||||
const sibStyle = dom.getStyle(sib, 'list-style-type');
|
||||
let detailStyle = detail ? detail['list-style-type'] : '';
|
||||
|
||||
detailStyle = detailStyle === null ? '' : detailStyle;
|
||||
|
||||
return sibStyle === detailStyle;
|
||||
};
|
||||
|
||||
const applyList = function (editor, listName: string, detail:any = {}) {
|
||||
const rng = editor.selection.getRng(true);
|
||||
let bookmark;
|
||||
let listItemName = 'LI';
|
||||
const root = Selection.getClosestListRootElm(editor, editor.selection.getStart(true));
|
||||
const dom = editor.dom;
|
||||
|
||||
if (dom.getContentEditable(editor.selection.getNode()) === 'false') {
|
||||
return;
|
||||
}
|
||||
|
||||
listName = listName.toUpperCase();
|
||||
|
||||
if (listName === 'DL') {
|
||||
listItemName = 'DT';
|
||||
}
|
||||
|
||||
bookmark = Bookmark.createBookmark(rng);
|
||||
|
||||
Tools.each(getSelectedTextBlocks(editor, rng, root), function (block) {
|
||||
let listBlock, sibling;
|
||||
|
||||
sibling = block.previousSibling;
|
||||
if (sibling && NodeType.isListNode(sibling) && sibling.nodeName === listName && hasCompatibleStyle(dom, sibling, detail)) {
|
||||
listBlock = sibling;
|
||||
block = dom.rename(block, listItemName);
|
||||
sibling.appendChild(block);
|
||||
} else {
|
||||
listBlock = dom.create(listName);
|
||||
if (detail.listType === 'joplinChecklist') {
|
||||
listBlock.classList.add('joplin-checklist');
|
||||
} else {
|
||||
listBlock.classList.remove('joplin-checklist');
|
||||
}
|
||||
block.parentNode.insertBefore(listBlock, block);
|
||||
listBlock.appendChild(block);
|
||||
block = dom.rename(block, listItemName);
|
||||
}
|
||||
|
||||
removeStyles(dom, block, [
|
||||
'margin', 'margin-right', 'margin-bottom', 'margin-left', 'margin-top',
|
||||
'padding', 'padding-right', 'padding-bottom', 'padding-left', 'padding-top',
|
||||
]);
|
||||
|
||||
updateListWithDetails(dom, listBlock, detail);
|
||||
mergeWithAdjacentLists(editor.dom, listBlock);
|
||||
});
|
||||
|
||||
editor.selection.setRng(Bookmark.resolveBookmark(bookmark));
|
||||
};
|
||||
|
||||
const isValidLists = function (list1, list2) {
|
||||
return list1 && list2 && NodeType.isListNode(list1) && list1.nodeName === list2.nodeName;
|
||||
};
|
||||
|
||||
const hasSameListStyle = function (dom, list1, list2) {
|
||||
const targetStyle = dom.getStyle(list1, 'list-style-type', true);
|
||||
const style = dom.getStyle(list2, 'list-style-type', true);
|
||||
return targetStyle === style;
|
||||
};
|
||||
|
||||
const hasSameClasses = function (elm1, elm2) {
|
||||
return elm1.className === elm2.className;
|
||||
};
|
||||
|
||||
const shouldMerge = function (dom, list1, list2) {
|
||||
return isValidLists(list1, list2) && hasSameListStyle(dom, list1, list2) && hasSameClasses(list1, list2);
|
||||
};
|
||||
|
||||
const mergeWithAdjacentLists = function (dom, listBlock) {
|
||||
let sibling, node;
|
||||
|
||||
sibling = listBlock.nextSibling;
|
||||
if (shouldMerge(dom, listBlock, sibling)) {
|
||||
while ((node = sibling.firstChild)) {
|
||||
listBlock.appendChild(node);
|
||||
}
|
||||
|
||||
dom.remove(sibling);
|
||||
}
|
||||
|
||||
sibling = listBlock.previousSibling;
|
||||
if (shouldMerge(dom, listBlock, sibling)) {
|
||||
while ((node = sibling.lastChild)) {
|
||||
listBlock.insertBefore(node, listBlock.firstChild);
|
||||
}
|
||||
|
||||
dom.remove(sibling);
|
||||
}
|
||||
};
|
||||
|
||||
const updateList = function (editor: Editor, list, listName, detail) {
|
||||
if (list.nodeName !== listName) {
|
||||
const newList = editor.dom.rename(list, listName);
|
||||
updateListWithDetails(editor.dom, newList, detail);
|
||||
fireListEvent(editor, listToggleActionFromListName(listName), newList);
|
||||
} else {
|
||||
updateListWithDetails(editor.dom, list, detail);
|
||||
fireListEvent(editor, listToggleActionFromListName(listName), list);
|
||||
}
|
||||
};
|
||||
|
||||
const toggleMultipleLists = function (editor, parentList, lists, listName, detail) {
|
||||
if (parentList.nodeName === listName && !hasListStyleDetail(detail)) {
|
||||
flattenListSelection(editor);
|
||||
} else {
|
||||
const bookmark = Bookmark.createBookmark(editor.selection.getRng(true));
|
||||
|
||||
Tools.each([parentList].concat(lists), function (elm) {
|
||||
updateList(editor, elm, listName, detail);
|
||||
});
|
||||
|
||||
editor.selection.setRng(Bookmark.resolveBookmark(bookmark));
|
||||
}
|
||||
};
|
||||
|
||||
const hasListStyleDetail = function (detail) {
|
||||
return 'list-style-type' in detail;
|
||||
};
|
||||
|
||||
const toggleSingleList = function (editor, parentList, listName, detail) {
|
||||
if (parentList === editor.getBody()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (parentList) {
|
||||
const listType = findContainerListTypeFromElement(parentList);
|
||||
if (parentList.nodeName === listName && !hasListStyleDetail(detail) && !isCustomList(parentList) && listType === detail.listType) {
|
||||
flattenListSelection(editor);
|
||||
} else {
|
||||
const bookmark = Bookmark.createBookmark(editor.selection.getRng(true));
|
||||
updateListWithDetails(editor.dom, parentList, detail);
|
||||
const newList = editor.dom.rename(parentList, listName);
|
||||
mergeWithAdjacentLists(editor.dom, newList);
|
||||
editor.selection.setRng(Bookmark.resolveBookmark(bookmark));
|
||||
fireListEvent(editor, listToggleActionFromListName(listName), newList);
|
||||
}
|
||||
} else {
|
||||
applyList(editor, listName, detail);
|
||||
fireListEvent(editor, listToggleActionFromListName(listName), parentList);
|
||||
}
|
||||
};
|
||||
|
||||
const toggleList = function (editor, listName, detail) {
|
||||
const parentList = Selection.getParentList(editor);
|
||||
const selectedSubLists = Selection.getSelectedSubLists(editor);
|
||||
|
||||
detail = {
|
||||
listType: 'regular',
|
||||
...detail,
|
||||
}
|
||||
|
||||
if (parentList && selectedSubLists.length > 0) {
|
||||
toggleMultipleLists(editor, parentList, selectedSubLists, listName, detail);
|
||||
} else {
|
||||
toggleSingleList(editor, parentList, listName, detail);
|
||||
}
|
||||
};
|
||||
|
||||
export {
|
||||
toggleList,
|
||||
mergeWithAdjacentLists
|
||||
};
|
@@ -1,21 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import * as Delete from '../core/Delete';
|
||||
import Editor from 'tinymce/core/api/Editor';
|
||||
|
||||
const get = function (editor: Editor) {
|
||||
return {
|
||||
backspaceDelete (isForward: boolean) {
|
||||
Delete.backspaceDelete(editor, isForward);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export {
|
||||
get
|
||||
};
|
@@ -1,55 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import * as ToggleList from '../actions/ToggleList';
|
||||
import { indentListSelection, outdentListSelection, flattenListSelection } from '../actions/Indendation';
|
||||
import { addJoplinChecklistCommands } from '../listModel/JoplinListUtil';
|
||||
|
||||
const queryListCommandState = function (editor, listName) {
|
||||
return function () {
|
||||
const parentList = editor.dom.getParent(editor.selection.getStart(), 'UL,OL,DL');
|
||||
return parentList && parentList.nodeName === listName;
|
||||
};
|
||||
};
|
||||
|
||||
const register = function (editor) {
|
||||
editor.on('BeforeExecCommand', function (e) {
|
||||
const cmd = e.command.toLowerCase();
|
||||
|
||||
if (cmd === 'indent') {
|
||||
indentListSelection(editor);
|
||||
} else if (cmd === 'outdent') {
|
||||
outdentListSelection(editor);
|
||||
}
|
||||
});
|
||||
|
||||
editor.addCommand('InsertUnorderedList', function (ui, detail) {
|
||||
ToggleList.toggleList(editor, 'UL', detail);
|
||||
});
|
||||
|
||||
editor.addCommand('InsertOrderedList', function (ui, detail) {
|
||||
ToggleList.toggleList(editor, 'OL', detail);
|
||||
});
|
||||
|
||||
editor.addCommand('InsertDefinitionList', function (ui, detail) {
|
||||
ToggleList.toggleList(editor, 'DL', detail);
|
||||
});
|
||||
|
||||
editor.addCommand('RemoveList', () => {
|
||||
flattenListSelection(editor);
|
||||
});
|
||||
|
||||
editor.addQueryStateHandler('InsertUnorderedList', queryListCommandState(editor, 'UL'));
|
||||
editor.addQueryStateHandler('InsertOrderedList', queryListCommandState(editor, 'OL'));
|
||||
editor.addQueryStateHandler('InsertDefinitionList', queryListCommandState(editor, 'DL'));
|
||||
|
||||
addJoplinChecklistCommands(editor, ToggleList);
|
||||
};
|
||||
|
||||
export {
|
||||
register
|
||||
};
|
@@ -1,4 +0,0 @@
|
||||
import Editor from 'tinymce/core/api/Editor';
|
||||
import { ListAction } from '../core/ListAction';
|
||||
|
||||
export const fireListEvent = (editor: Editor, action: ListAction, element) => editor.fire('ListMutation', { action, element });
|
@@ -1,38 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import Editor from 'tinymce/core/api/Editor';
|
||||
|
||||
const shouldIndentOnTab = function (editor: Editor) {
|
||||
return editor.getParam('lists_indent_on_tab', true);
|
||||
};
|
||||
|
||||
const getForcedRootBlock = (editor: Editor): string => {
|
||||
const block = editor.getParam('forced_root_block', 'p');
|
||||
if (block === false) {
|
||||
return '';
|
||||
} else if (block === true) {
|
||||
return 'p';
|
||||
} else {
|
||||
return block;
|
||||
}
|
||||
};
|
||||
|
||||
const getForcedRootBlockAttrs = (editor: Editor): Record<string, string> => {
|
||||
return editor.getParam('forced_root_block_attrs', {});
|
||||
};
|
||||
|
||||
const getLocalizationFunction = (editor:Editor):Function => {
|
||||
return editor.getParam('localization_function', (s:string) => s);
|
||||
}
|
||||
|
||||
export {
|
||||
shouldIndentOnTab,
|
||||
getForcedRootBlock,
|
||||
getForcedRootBlockAttrs,
|
||||
getLocalizationFunction,
|
||||
};
|
@@ -1,126 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import DOMUtils from 'tinymce/core/api/dom/DOMUtils';
|
||||
import * as Range from './Range';
|
||||
|
||||
const DOM = DOMUtils.DOM;
|
||||
|
||||
/**
|
||||
* Returns a range bookmark. This will convert indexed bookmarks into temporary span elements with
|
||||
* index 0 so that they can be restored properly after the DOM has been modified. Text bookmarks will not have spans
|
||||
* added to them since they can be restored after a dom operation.
|
||||
*
|
||||
* So this: <p><b>|</b><b>|</b></p>
|
||||
* becomes: <p><b><span data-mce-type="bookmark">|</span></b><b data-mce-type="bookmark">|</span></b></p>
|
||||
*
|
||||
* @param {DOMRange} rng DOM Range to get bookmark on.
|
||||
* @return {Object} Bookmark object.
|
||||
*/
|
||||
const createBookmark = function (rng) {
|
||||
const bookmark = {};
|
||||
|
||||
const setupEndPoint = function (start?) {
|
||||
let offsetNode, container, offset;
|
||||
|
||||
container = rng[start ? 'startContainer' : 'endContainer'];
|
||||
offset = rng[start ? 'startOffset' : 'endOffset'];
|
||||
|
||||
if (container.nodeType === 1) {
|
||||
offsetNode = DOM.create('span', { 'data-mce-type': 'bookmark' });
|
||||
|
||||
if (container.hasChildNodes()) {
|
||||
offset = Math.min(offset, container.childNodes.length - 1);
|
||||
|
||||
if (start) {
|
||||
container.insertBefore(offsetNode, container.childNodes[offset]);
|
||||
} else {
|
||||
DOM.insertAfter(offsetNode, container.childNodes[offset]);
|
||||
}
|
||||
} else {
|
||||
container.appendChild(offsetNode);
|
||||
}
|
||||
|
||||
container = offsetNode;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
bookmark[start ? 'startContainer' : 'endContainer'] = container;
|
||||
bookmark[start ? 'startOffset' : 'endOffset'] = offset;
|
||||
};
|
||||
|
||||
setupEndPoint(true);
|
||||
|
||||
if (!rng.collapsed) {
|
||||
setupEndPoint();
|
||||
}
|
||||
|
||||
return bookmark;
|
||||
};
|
||||
|
||||
const resolveBookmark = function (bookmark) {
|
||||
function restoreEndPoint(start?) {
|
||||
let container, offset, node;
|
||||
|
||||
const nodeIndex = function (container) {
|
||||
let node = container.parentNode.firstChild, idx = 0;
|
||||
|
||||
while (node) {
|
||||
if (node === container) {
|
||||
return idx;
|
||||
}
|
||||
|
||||
// Skip data-mce-type=bookmark nodes
|
||||
if (node.nodeType !== 1 || node.getAttribute('data-mce-type') !== 'bookmark') {
|
||||
idx++;
|
||||
}
|
||||
|
||||
node = node.nextSibling;
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
|
||||
container = node = bookmark[start ? 'startContainer' : 'endContainer'];
|
||||
offset = bookmark[start ? 'startOffset' : 'endOffset'];
|
||||
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (container.nodeType === 1) {
|
||||
offset = nodeIndex(container);
|
||||
container = container.parentNode;
|
||||
DOM.remove(node);
|
||||
|
||||
if (!container.hasChildNodes() && DOM.isBlock(container)) {
|
||||
container.appendChild(DOM.create('br'));
|
||||
}
|
||||
}
|
||||
|
||||
bookmark[start ? 'startContainer' : 'endContainer'] = container;
|
||||
bookmark[start ? 'startOffset' : 'endOffset'] = offset;
|
||||
}
|
||||
|
||||
restoreEndPoint(true);
|
||||
restoreEndPoint();
|
||||
|
||||
const rng = DOM.createRng();
|
||||
|
||||
rng.setStart(bookmark.startContainer, bookmark.startOffset);
|
||||
|
||||
if (bookmark.endContainer) {
|
||||
rng.setEnd(bookmark.endContainer, bookmark.endOffset);
|
||||
}
|
||||
|
||||
return Range.normalizeRange(rng);
|
||||
};
|
||||
|
||||
export {
|
||||
createBookmark,
|
||||
resolveBookmark
|
||||
};
|
@@ -1,285 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
interface DOMUtils {
|
||||
isBlock: Function,
|
||||
remove: Function,
|
||||
$: Function,
|
||||
getParent: Function,
|
||||
getParents: Function,
|
||||
getRoot: Function,
|
||||
isEmpty: Function,
|
||||
}
|
||||
|
||||
import { Element, HTMLLIElement, Node, Range as DomRange } from '@ephox/dom-globals';
|
||||
import { Arr } from '@ephox/katamari';
|
||||
import { Compare, Element as SugarElement } from '@ephox/sugar';
|
||||
// import DOMUtils from 'tinymce/core/api/dom/DOMUtils';
|
||||
import RangeUtils from 'tinymce/core/api/dom/RangeUtils';
|
||||
import TreeWalker from 'tinymce/core/api/dom/TreeWalker';
|
||||
import Editor from 'tinymce/core/api/Editor';
|
||||
import VK from 'tinymce/core/api/util/VK';
|
||||
import { flattenListSelection, outdentListSelection } from '../actions/Indendation';
|
||||
import * as ToggleList from '../actions/ToggleList';
|
||||
import * as Bookmark from './Bookmark';
|
||||
import * as NodeType from './NodeType';
|
||||
import * as NormalizeLists from './NormalizeLists';
|
||||
import * as Range from './Range';
|
||||
import * as Selection from './Selection';
|
||||
|
||||
const findNextCaretContainer = function (editor: Editor, rng: DomRange, isForward: Boolean, root: Node): Node {
|
||||
let node = rng.startContainer;
|
||||
const offset = rng.startOffset;
|
||||
|
||||
if (NodeType.isTextNode(node) && (isForward ? offset < node.data.length : offset > 0)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
const nonEmptyBlocks = editor.schema.getNonEmptyElements();
|
||||
if (node.nodeType === 1) {
|
||||
node = RangeUtils.getNode(node, offset);
|
||||
}
|
||||
|
||||
const walker = new TreeWalker(node, root);
|
||||
|
||||
// Delete at <li>|<br></li> then jump over the bogus br
|
||||
if (isForward) {
|
||||
if (NodeType.isBogusBr(editor.dom, node)) {
|
||||
walker.next();
|
||||
}
|
||||
}
|
||||
|
||||
while ((node = walker[isForward ? 'next' : 'prev2']())) {
|
||||
if (node.nodeName === 'LI' && !node.hasChildNodes()) {
|
||||
return node;
|
||||
}
|
||||
|
||||
if (nonEmptyBlocks[node.nodeName]) {
|
||||
return node;
|
||||
}
|
||||
|
||||
if (NodeType.isTextNode(node) && node.data.length > 0) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const hasOnlyOneBlockChild = function (dom: DOMUtils, elm: Element): boolean {
|
||||
const childNodes = elm.childNodes;
|
||||
return childNodes.length === 1 && !NodeType.isListNode(childNodes[0]) && dom.isBlock(childNodes[0]);
|
||||
};
|
||||
|
||||
const unwrapSingleBlockChild = function (dom: DOMUtils, elm: Element) {
|
||||
if (hasOnlyOneBlockChild(dom, elm)) {
|
||||
dom.remove(elm.firstChild, true);
|
||||
}
|
||||
};
|
||||
|
||||
const moveChildren = function (dom: DOMUtils, fromElm: Element, toElm: Element) {
|
||||
let node, targetElm;
|
||||
|
||||
targetElm = hasOnlyOneBlockChild(dom, toElm) ? toElm.firstChild : toElm;
|
||||
unwrapSingleBlockChild(dom, fromElm);
|
||||
|
||||
if (!NodeType.isEmpty(dom, fromElm, true)) {
|
||||
while ((node = fromElm.firstChild)) {
|
||||
targetElm.appendChild(node);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const mergeLiElements = function (dom: DOMUtils, fromElm: Element, toElm: Element) {
|
||||
let node, listNode;
|
||||
const ul = fromElm.parentNode;
|
||||
|
||||
if (!NodeType.isChildOfBody(dom, fromElm) || !NodeType.isChildOfBody(dom, toElm)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (NodeType.isListNode(toElm.lastChild)) {
|
||||
listNode = toElm.lastChild;
|
||||
}
|
||||
|
||||
if (ul === toElm.lastChild) {
|
||||
if (NodeType.isBr(ul.previousSibling)) {
|
||||
dom.remove(ul.previousSibling);
|
||||
}
|
||||
}
|
||||
|
||||
node = toElm.lastChild;
|
||||
if (node && NodeType.isBr(node) && fromElm.hasChildNodes()) {
|
||||
dom.remove(node);
|
||||
}
|
||||
|
||||
if (NodeType.isEmpty(dom, toElm, true)) {
|
||||
dom.$(toElm).empty();
|
||||
}
|
||||
|
||||
moveChildren(dom, fromElm, toElm);
|
||||
|
||||
if (listNode) {
|
||||
toElm.appendChild(listNode);
|
||||
}
|
||||
|
||||
const contains = Compare.contains(SugarElement.fromDom(toElm), SugarElement.fromDom(fromElm));
|
||||
|
||||
const nestedLists = contains ? dom.getParents(fromElm, NodeType.isListNode, toElm) : [];
|
||||
|
||||
dom.remove(fromElm);
|
||||
|
||||
Arr.each(nestedLists, (list) => {
|
||||
if (NodeType.isEmpty(dom, list) && list !== dom.getRoot()) {
|
||||
dom.remove(list);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const mergeIntoEmptyLi = function (editor: Editor, fromLi: HTMLLIElement, toLi: HTMLLIElement) {
|
||||
editor.dom.$(toLi).empty();
|
||||
mergeLiElements(editor.dom, fromLi, toLi);
|
||||
editor.selection.setCursorLocation(toLi);
|
||||
};
|
||||
|
||||
const mergeForward = function (editor: Editor, rng: DomRange, fromLi: HTMLLIElement, toLi: HTMLLIElement) {
|
||||
const dom = editor.dom;
|
||||
|
||||
if (dom.isEmpty(toLi)) {
|
||||
mergeIntoEmptyLi(editor, fromLi, toLi);
|
||||
} else {
|
||||
const bookmark = Bookmark.createBookmark(rng);
|
||||
mergeLiElements(dom, fromLi, toLi);
|
||||
editor.selection.setRng(Bookmark.resolveBookmark(bookmark));
|
||||
}
|
||||
};
|
||||
|
||||
const mergeBackward = function (editor: Editor, rng: DomRange, fromLi: HTMLLIElement, toLi: HTMLLIElement) {
|
||||
const bookmark = Bookmark.createBookmark(rng);
|
||||
mergeLiElements(editor.dom, fromLi, toLi);
|
||||
const resolvedBookmark = Bookmark.resolveBookmark(bookmark);
|
||||
editor.selection.setRng(resolvedBookmark);
|
||||
};
|
||||
|
||||
const backspaceDeleteFromListToListCaret = function (editor: Editor, isForward: boolean) {
|
||||
const dom = editor.dom, selection = editor.selection;
|
||||
const selectionStartElm = selection.getStart();
|
||||
const root = Selection.getClosestListRootElm(editor, selectionStartElm);
|
||||
const li = dom.getParent(selection.getStart(), 'LI', root) as HTMLLIElement;
|
||||
|
||||
if (li) {
|
||||
const ul = li.parentNode;
|
||||
if (ul === editor.getBody() && NodeType.isEmpty(dom, ul)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const rng = Range.normalizeRange(selection.getRng());
|
||||
const otherLi = dom.getParent(findNextCaretContainer(editor, rng, isForward, root), 'LI', root) as HTMLLIElement;
|
||||
|
||||
if (otherLi && otherLi !== li) {
|
||||
editor.undoManager.transact(() => {
|
||||
if (isForward) {
|
||||
mergeForward(editor, rng, otherLi, li);
|
||||
} else {
|
||||
if (NodeType.isFirstChild(li)) {
|
||||
outdentListSelection(editor);
|
||||
} else {
|
||||
mergeBackward(editor, rng, li, otherLi);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
} else if (!otherLi) {
|
||||
if (!isForward && rng.startOffset === 0 && rng.endOffset === 0) {
|
||||
editor.undoManager.transact(() => {
|
||||
flattenListSelection(editor);
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const removeBlock = function (dom: DOMUtils, block: Element, root: Node) {
|
||||
const parentBlock = dom.getParent(block.parentNode, dom.isBlock, root);
|
||||
|
||||
dom.remove(block);
|
||||
if (parentBlock && dom.isEmpty(parentBlock)) {
|
||||
dom.remove(parentBlock);
|
||||
}
|
||||
};
|
||||
|
||||
const backspaceDeleteIntoListCaret = function (editor: Editor, isForward: boolean) {
|
||||
const dom = editor.dom;
|
||||
const selectionStartElm = editor.selection.getStart();
|
||||
const root = Selection.getClosestListRootElm(editor, selectionStartElm);
|
||||
const block = dom.getParent(selectionStartElm, dom.isBlock, root);
|
||||
|
||||
if (block && dom.isEmpty(block)) {
|
||||
const rng = Range.normalizeRange(editor.selection.getRng());
|
||||
const otherLi = dom.getParent(findNextCaretContainer(editor, rng, isForward, root), 'LI', root);
|
||||
|
||||
if (otherLi) {
|
||||
editor.undoManager.transact(function () {
|
||||
removeBlock(dom, block, root);
|
||||
ToggleList.mergeWithAdjacentLists(dom, otherLi.parentNode);
|
||||
editor.selection.select(otherLi, true);
|
||||
editor.selection.collapse(isForward);
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const backspaceDeleteCaret = function (editor: Editor, isForward: boolean): boolean {
|
||||
return backspaceDeleteFromListToListCaret(editor, isForward) || backspaceDeleteIntoListCaret(editor, isForward);
|
||||
};
|
||||
|
||||
const backspaceDeleteRange = function (editor: Editor): boolean {
|
||||
const selectionStartElm = editor.selection.getStart();
|
||||
const root = Selection.getClosestListRootElm(editor, selectionStartElm);
|
||||
const startListParent = editor.dom.getParent(selectionStartElm, 'LI,DT,DD', root);
|
||||
|
||||
if (startListParent || Selection.getSelectedListItems(editor).length > 0) {
|
||||
editor.undoManager.transact(function () {
|
||||
editor.execCommand('Delete');
|
||||
NormalizeLists.normalizeLists(editor.dom, editor.getBody());
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const backspaceDelete = function (editor: Editor, isForward: boolean): boolean {
|
||||
return editor.selection.isCollapsed() ? backspaceDeleteCaret(editor, isForward) : backspaceDeleteRange(editor);
|
||||
};
|
||||
|
||||
const setup = function (editor: Editor) {
|
||||
editor.on('keydown', function (e) {
|
||||
if (e.keyCode === VK.BACKSPACE) {
|
||||
if (backspaceDelete(editor, false)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
} else if (e.keyCode === VK.DELETE) {
|
||||
if (backspaceDelete(editor, true)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export {
|
||||
setup,
|
||||
backspaceDelete
|
||||
};
|
@@ -1,38 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import Editor from 'tinymce/core/api/Editor';
|
||||
import { Compare, Replication, Element, Traverse } from '@ephox/sugar';
|
||||
import * as SplitList from './SplitList';
|
||||
import { Indentation } from '../listModel/Indentation';
|
||||
import { Arr } from '@ephox/katamari';
|
||||
|
||||
const outdentDlItem = (editor: Editor, item: Element): void => {
|
||||
if (Compare.is(item, 'dd')) {
|
||||
Replication.mutate(item, 'dt');
|
||||
} else if (Compare.is(item, 'dt')) {
|
||||
Traverse.parent(item).each((dl) => SplitList.splitList(editor, dl.dom(), item.dom()));
|
||||
}
|
||||
};
|
||||
|
||||
const indentDlItem = (item: Element): void => {
|
||||
if (Compare.is(item, 'dt')) {
|
||||
Replication.mutate(item, 'dd');
|
||||
}
|
||||
};
|
||||
|
||||
const dlIndentation = (editor: Editor, indentation: Indentation, dlItems: Element[]) => {
|
||||
if (indentation === Indentation.Indent) {
|
||||
Arr.each(dlItems, indentDlItem);
|
||||
} else {
|
||||
Arr.each(dlItems, (item) => outdentDlItem(editor, item));
|
||||
}
|
||||
};
|
||||
|
||||
export {
|
||||
dlIndentation
|
||||
};
|
@@ -1,38 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import VK from 'tinymce/core/api/util/VK';
|
||||
import * as Settings from '../api/Settings';
|
||||
import * as Delete from './Delete';
|
||||
import { outdentListSelection, indentListSelection } from '../actions/Indendation';
|
||||
|
||||
const setupTabKey = function (editor) {
|
||||
editor.on('keydown', function (e) {
|
||||
// Check for tab but not ctrl/cmd+tab since it switches browser tabs
|
||||
if (e.keyCode !== VK.TAB || VK.metaKeyPressed(e)) {
|
||||
return;
|
||||
}
|
||||
|
||||
editor.undoManager.transact(() => {
|
||||
if (e.shiftKey ? outdentListSelection(editor) : indentListSelection(editor)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const setup = function (editor) {
|
||||
if (Settings.shouldIndentOnTab(editor)) {
|
||||
setupTabKey(editor);
|
||||
}
|
||||
|
||||
Delete.setup(editor);
|
||||
};
|
||||
|
||||
export {
|
||||
setup
|
||||
};
|
@@ -1,15 +0,0 @@
|
||||
export const enum ListAction {
|
||||
ToggleUlList = 'ToggleUlList',
|
||||
ToggleOlList = 'ToggleOlList',
|
||||
ToggleDLList = 'ToggleDLList',
|
||||
IndentList = 'IndentList',
|
||||
OutdentList = 'OutdentList'
|
||||
}
|
||||
|
||||
export const listToggleActionFromListName = (listName: 'UL' | 'OL' | 'DL'): ListAction => {
|
||||
switch (listName) {
|
||||
case 'UL': return ListAction.ToggleUlList;
|
||||
case 'OL': return ListAction.ToggleOlList;
|
||||
case 'DL': return ListAction.ToggleDLList;
|
||||
}
|
||||
};
|
@@ -1,95 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import { Node, Text } from '@ephox/dom-globals';
|
||||
|
||||
const isTextNode = function (node: Node): node is Text {
|
||||
return node && node.nodeType === 3;
|
||||
};
|
||||
|
||||
const isListNode = function (node: Node) {
|
||||
return node && (/^(OL|UL|DL)$/).test(node.nodeName);
|
||||
};
|
||||
|
||||
const isOlUlNode = function (node: Node) {
|
||||
return node && (/^(OL|UL)$/).test(node.nodeName);
|
||||
};
|
||||
|
||||
const isListItemNode = function (node: Node) {
|
||||
return node && /^(LI|DT|DD)$/.test(node.nodeName);
|
||||
};
|
||||
|
||||
const isDlItemNode = function (node: Node) {
|
||||
return node && /^(DT|DD)$/.test(node.nodeName);
|
||||
};
|
||||
|
||||
const isTableCellNode = function (node: Node) {
|
||||
return node && /^(TH|TD)$/.test(node.nodeName);
|
||||
};
|
||||
|
||||
const isBr = function (node: Node) {
|
||||
return node && node.nodeName === 'BR';
|
||||
};
|
||||
|
||||
const isFirstChild = function (node: Node) {
|
||||
return node.parentNode.firstChild === node;
|
||||
};
|
||||
|
||||
const isLastChild = function (node: Node) {
|
||||
return node.parentNode.lastChild === node;
|
||||
};
|
||||
|
||||
const isTextBlock = function (editor, node: Node) {
|
||||
return node && !!editor.schema.getTextBlockElements()[node.nodeName];
|
||||
};
|
||||
|
||||
const isBlock = function (node: Node, blockElements) {
|
||||
return node && node.nodeName in blockElements;
|
||||
};
|
||||
|
||||
const isBogusBr = function (dom, node: Node) {
|
||||
if (!isBr(node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dom.isBlock(node.nextSibling) && !isBr(node.previousSibling)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const isEmpty = function (dom, elm, keepBookmarks?) {
|
||||
const empty = dom.isEmpty(elm);
|
||||
|
||||
if (keepBookmarks && dom.select('span[data-mce-type=bookmark]', elm).length > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return empty;
|
||||
};
|
||||
|
||||
const isChildOfBody = function (dom, elm) {
|
||||
return dom.isChildOf(elm, dom.getRoot());
|
||||
};
|
||||
|
||||
export {
|
||||
isTextNode,
|
||||
isListNode,
|
||||
isOlUlNode,
|
||||
isDlItemNode,
|
||||
isListItemNode,
|
||||
isTableCellNode,
|
||||
isBr,
|
||||
isFirstChild,
|
||||
isLastChild,
|
||||
isTextBlock,
|
||||
isBlock,
|
||||
isBogusBr,
|
||||
isEmpty,
|
||||
isChildOfBody
|
||||
};
|
@@ -1,50 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import DOMUtils from 'tinymce/core/api/dom/DOMUtils';
|
||||
import Tools from 'tinymce/core/api/util/Tools';
|
||||
import * as NodeType from './NodeType';
|
||||
|
||||
const DOM = DOMUtils.DOM;
|
||||
|
||||
const normalizeList = function (dom, ul) {
|
||||
let sibling;
|
||||
const parentNode = ul.parentNode;
|
||||
|
||||
// Move UL/OL to previous LI if it's the only child of a LI
|
||||
if (parentNode.nodeName === 'LI' && parentNode.firstChild === ul) {
|
||||
sibling = parentNode.previousSibling;
|
||||
if (sibling && sibling.nodeName === 'LI') {
|
||||
sibling.appendChild(ul);
|
||||
|
||||
if (NodeType.isEmpty(dom, parentNode)) {
|
||||
DOM.remove(parentNode);
|
||||
}
|
||||
} else {
|
||||
DOM.setStyle(parentNode, 'listStyleType', 'none');
|
||||
}
|
||||
}
|
||||
|
||||
// Append OL/UL to previous LI if it's in a parent OL/UL i.e. old HTML4
|
||||
if (NodeType.isListNode(parentNode)) {
|
||||
sibling = parentNode.previousSibling;
|
||||
if (sibling && sibling.nodeName === 'LI') {
|
||||
sibling.appendChild(ul);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const normalizeLists = function (dom, element) {
|
||||
Tools.each(Tools.grep(dom.select('ol,ul', element)), function (ul) {
|
||||
normalizeList(dom, ul);
|
||||
});
|
||||
};
|
||||
|
||||
export {
|
||||
normalizeList,
|
||||
normalizeLists
|
||||
};
|
@@ -1,58 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import RangeUtils from 'tinymce/core/api/dom/RangeUtils';
|
||||
import * as NodeType from './NodeType';
|
||||
import { Range, Node } from '@ephox/dom-globals';
|
||||
|
||||
interface Point {
|
||||
container: Node;
|
||||
offset: number;
|
||||
}
|
||||
|
||||
const getNormalizedPoint = (container: Node, offset: number): Point => {
|
||||
if (NodeType.isTextNode(container)) {
|
||||
return { container, offset };
|
||||
}
|
||||
|
||||
const node = RangeUtils.getNode(container, offset);
|
||||
if (NodeType.isTextNode(node)) {
|
||||
return {
|
||||
container: node,
|
||||
offset: offset >= container.childNodes.length ? node.data.length : 0
|
||||
};
|
||||
} else if (node.previousSibling && NodeType.isTextNode(node.previousSibling)) {
|
||||
return {
|
||||
container: node.previousSibling,
|
||||
offset: node.previousSibling.data.length
|
||||
};
|
||||
} else if (node.nextSibling && NodeType.isTextNode(node.nextSibling)) {
|
||||
return {
|
||||
container: node.nextSibling,
|
||||
offset: 0
|
||||
};
|
||||
}
|
||||
|
||||
return { container, offset };
|
||||
};
|
||||
|
||||
const normalizeRange = (rng: Range): Range => {
|
||||
const outRng = rng.cloneRange();
|
||||
|
||||
const rangeStart = getNormalizedPoint(rng.startContainer, rng.startOffset);
|
||||
outRng.setStart(rangeStart.container, rangeStart.offset);
|
||||
|
||||
const rangeEnd = getNormalizedPoint(rng.endContainer, rng.endOffset);
|
||||
outRng.setEnd(rangeEnd.container, rangeEnd.offset);
|
||||
|
||||
return outRng;
|
||||
};
|
||||
|
||||
export {
|
||||
getNormalizedPoint,
|
||||
normalizeRange
|
||||
};
|
@@ -1,108 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import { Node } from '@ephox/dom-globals';
|
||||
import { Arr, Option } from '@ephox/katamari';
|
||||
import { HTMLElement } from '@ephox/sand';
|
||||
import DomQuery from 'tinymce/core/api/dom/DomQuery';
|
||||
import Editor from 'tinymce/core/api/Editor';
|
||||
import Tools from 'tinymce/core/api/util/Tools';
|
||||
import * as NodeType from './NodeType';
|
||||
|
||||
const getParentList = function (editor) {
|
||||
const selectionStart = editor.selection.getStart(true);
|
||||
|
||||
return editor.dom.getParent(selectionStart, 'OL,UL,DL', getClosestListRootElm(editor, selectionStart));
|
||||
};
|
||||
|
||||
const isParentListSelected = function (parentList, selectedBlocks) {
|
||||
return parentList && selectedBlocks.length === 1 && selectedBlocks[0] === parentList;
|
||||
};
|
||||
|
||||
const findSubLists = function (parentList) {
|
||||
return Tools.grep(parentList.querySelectorAll('ol,ul,dl'), function (elm: Node) {
|
||||
return NodeType.isListNode(elm);
|
||||
});
|
||||
};
|
||||
|
||||
const getSelectedSubLists = function (editor) {
|
||||
const parentList = getParentList(editor);
|
||||
const selectedBlocks = editor.selection.getSelectedBlocks();
|
||||
|
||||
if (isParentListSelected(parentList, selectedBlocks)) {
|
||||
return findSubLists(parentList);
|
||||
} else {
|
||||
return Tools.grep(selectedBlocks, function (elm: Node) {
|
||||
return NodeType.isListNode(elm) && parentList !== elm;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const findParentListItemsNodes = function (editor, elms) {
|
||||
const listItemsElms = Tools.map(elms, function (elm) {
|
||||
const parentLi = editor.dom.getParent(elm, 'li,dd,dt', getClosestListRootElm(editor, elm));
|
||||
|
||||
return parentLi ? parentLi : elm;
|
||||
});
|
||||
|
||||
return DomQuery.unique(listItemsElms);
|
||||
};
|
||||
|
||||
const getSelectedListItems = function (editor) {
|
||||
const selectedBlocks = editor.selection.getSelectedBlocks();
|
||||
return Tools.grep(findParentListItemsNodes(editor, selectedBlocks), function (block) {
|
||||
return NodeType.isListItemNode(block);
|
||||
});
|
||||
};
|
||||
|
||||
const getSelectedDlItems = (editor: Editor): Node[] => {
|
||||
return Arr.filter(getSelectedListItems(editor), NodeType.isDlItemNode);
|
||||
};
|
||||
|
||||
const getClosestListRootElm = function (editor, elm) {
|
||||
const parentTableCell = editor.dom.getParents(elm, 'TD,TH');
|
||||
const root = parentTableCell.length > 0 ? parentTableCell[0] : editor.getBody();
|
||||
|
||||
return root;
|
||||
};
|
||||
|
||||
const findLastParentListNode = (editor: Editor, elm: Node): Option<Node> => {
|
||||
const parentLists = editor.dom.getParents(elm, 'ol,ul', getClosestListRootElm(editor, elm));
|
||||
return Arr.last(parentLists);
|
||||
};
|
||||
|
||||
const getSelectedLists = (editor: Editor): Node[] => {
|
||||
const firstList = findLastParentListNode(editor, editor.selection.getStart());
|
||||
const subsequentLists = Arr.filter(editor.selection.getSelectedBlocks(), NodeType.isOlUlNode);
|
||||
|
||||
return firstList.toArray().concat(subsequentLists);
|
||||
};
|
||||
|
||||
const getSelectedListRoots = (editor: Editor): Node[] => {
|
||||
const selectedLists = getSelectedLists(editor);
|
||||
return getUniqueListRoots(editor, selectedLists);
|
||||
};
|
||||
|
||||
const getUniqueListRoots = (editor: Editor, lists: Node[]): Node[] => {
|
||||
const listRoots = Arr.map(lists, (list) => findLastParentListNode(editor, list).getOr(list));
|
||||
return DomQuery.unique(listRoots);
|
||||
};
|
||||
|
||||
const isList = (editor: Editor): boolean => {
|
||||
const list = getParentList(editor);
|
||||
return HTMLElement.isPrototypeOf(list);
|
||||
};
|
||||
|
||||
export {
|
||||
isList,
|
||||
getParentList,
|
||||
getSelectedSubLists,
|
||||
getSelectedListItems,
|
||||
getClosestListRootElm,
|
||||
getSelectedDlItems,
|
||||
getSelectedListRoots
|
||||
};
|
@@ -1,59 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import DOMUtils from 'tinymce/core/api/dom/DOMUtils';
|
||||
import * as NodeType from './NodeType';
|
||||
import { createTextBlock } from './TextBlock';
|
||||
import Tools from 'tinymce/core/api/util/Tools';
|
||||
|
||||
const DOM = DOMUtils.DOM;
|
||||
|
||||
const splitList = function (editor, ul, li) {
|
||||
let tmpRng, fragment, bookmarks, node, newBlock;
|
||||
|
||||
const removeAndKeepBookmarks = function (targetNode) {
|
||||
Tools.each(bookmarks, function (node) {
|
||||
targetNode.parentNode.insertBefore(node, li.parentNode);
|
||||
});
|
||||
|
||||
DOM.remove(targetNode);
|
||||
};
|
||||
|
||||
bookmarks = DOM.select('span[data-mce-type="bookmark"]', ul);
|
||||
newBlock = createTextBlock(editor, li);
|
||||
tmpRng = DOM.createRng();
|
||||
tmpRng.setStartAfter(li);
|
||||
tmpRng.setEndAfter(ul);
|
||||
fragment = tmpRng.extractContents();
|
||||
|
||||
for (node = fragment.firstChild; node; node = node.firstChild) {
|
||||
if (node.nodeName === 'LI' && editor.dom.isEmpty(node)) {
|
||||
DOM.remove(node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!editor.dom.isEmpty(fragment)) {
|
||||
DOM.insertAfter(fragment, ul);
|
||||
}
|
||||
|
||||
DOM.insertAfter(newBlock, ul);
|
||||
|
||||
if (NodeType.isEmpty(editor.dom, li.parentNode)) {
|
||||
removeAndKeepBookmarks(li.parentNode);
|
||||
}
|
||||
|
||||
DOM.remove(li);
|
||||
|
||||
if (NodeType.isEmpty(editor.dom, ul)) {
|
||||
DOM.remove(ul);
|
||||
}
|
||||
};
|
||||
|
||||
export {
|
||||
splitList
|
||||
};
|
@@ -1,72 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import * as NodeType from './NodeType';
|
||||
import { DocumentFragment, Node } from '@ephox/dom-globals';
|
||||
import Editor from 'tinymce/core/api/Editor';
|
||||
import * as Settings from '../api/Settings';
|
||||
|
||||
const createTextBlock = (editor: Editor, contentNode: Node): DocumentFragment => {
|
||||
const dom = editor.dom;
|
||||
const blockElements = editor.schema.getBlockElements();
|
||||
const fragment = dom.createFragment();
|
||||
const blockName = Settings.getForcedRootBlock(editor);
|
||||
let node, textBlock, hasContentNode;
|
||||
|
||||
if (blockName) {
|
||||
textBlock = dom.create(blockName);
|
||||
|
||||
if (textBlock.tagName === blockName.toUpperCase()) {
|
||||
dom.setAttribs(textBlock, Settings.getForcedRootBlockAttrs(editor));
|
||||
}
|
||||
|
||||
if (!NodeType.isBlock(contentNode.firstChild, blockElements)) {
|
||||
fragment.appendChild(textBlock);
|
||||
}
|
||||
}
|
||||
|
||||
if (contentNode) {
|
||||
while ((node = contentNode.firstChild)) {
|
||||
const nodeName = node.nodeName;
|
||||
|
||||
if (!hasContentNode && (nodeName !== 'SPAN' || node.getAttribute('data-mce-type') !== 'bookmark')) {
|
||||
hasContentNode = true;
|
||||
}
|
||||
|
||||
if (NodeType.isBlock(node, blockElements)) {
|
||||
fragment.appendChild(node);
|
||||
textBlock = null;
|
||||
} else {
|
||||
if (blockName) {
|
||||
if (!textBlock) {
|
||||
textBlock = dom.create(blockName);
|
||||
fragment.appendChild(textBlock);
|
||||
}
|
||||
|
||||
textBlock.appendChild(node);
|
||||
} else {
|
||||
fragment.appendChild(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!blockName) {
|
||||
fragment.appendChild(dom.create('br'));
|
||||
} else {
|
||||
// BR is needed in empty blocks
|
||||
if (!hasContentNode) {
|
||||
textBlock.appendChild(dom.create('br', { 'data-mce-bogus': '1' }));
|
||||
}
|
||||
}
|
||||
|
||||
return fragment;
|
||||
};
|
||||
|
||||
export {
|
||||
createTextBlock
|
||||
};
|
@@ -1,3 +0,0 @@
|
||||
import { HTMLElement } from '@ephox/dom-globals';
|
||||
|
||||
export const isCustomList = (list: HTMLElement) => /\btox\-/.test(list.className);
|
@@ -1,109 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import { Document } from '@ephox/dom-globals';
|
||||
import { Arr, Option, Options } from '@ephox/katamari';
|
||||
import { Attr, Css, Element, Insert, InsertAll, Node, Replication } from '@ephox/sugar';
|
||||
import { Entry } from './Entry';
|
||||
import { ListType } from './Util';
|
||||
|
||||
interface Segment {
|
||||
list: Element;
|
||||
item: Element;
|
||||
}
|
||||
|
||||
const joinSegment = (parent: Segment, child: Segment): void => {
|
||||
Insert.append(parent.item, child.list);
|
||||
};
|
||||
|
||||
const joinSegments = (segments: Segment[]): void => {
|
||||
for (let i = 1; i < segments.length; i++) {
|
||||
joinSegment(segments[i - 1], segments[i]);
|
||||
}
|
||||
};
|
||||
|
||||
const appendSegments = (head: Segment[], tail: Segment[]): void => {
|
||||
Options.lift2(Arr.last(head), Arr.head(tail), joinSegment);
|
||||
};
|
||||
|
||||
const createSegment = (scope: Document, listType: ListType): Segment => {
|
||||
const segment: Segment = {
|
||||
list: Element.fromTag(listType, scope),
|
||||
item: Element.fromTag('li', scope)
|
||||
};
|
||||
Insert.append(segment.list, segment.item);
|
||||
return segment;
|
||||
};
|
||||
|
||||
const createSegments = (scope: Document, entry: Entry, size: number): Segment[] => {
|
||||
const segments: Segment[] = [];
|
||||
for (let i = 0; i < size; i++) {
|
||||
segments.push(createSegment(scope, entry.listType));
|
||||
}
|
||||
return segments;
|
||||
};
|
||||
|
||||
const populateSegments = (segments: Segment[], entry: Entry): void => {
|
||||
for (let i = 0; i < segments.length - 1; i++) {
|
||||
Css.set(segments[i].item, 'list-style-type', 'none');
|
||||
}
|
||||
Arr.last(segments).each((segment) => {
|
||||
Attr.setAll(segment.list, entry.listAttributes);
|
||||
Attr.setAll(segment.item, entry.itemAttributes);
|
||||
InsertAll.append(segment.item, entry.content);
|
||||
});
|
||||
};
|
||||
|
||||
const normalizeSegment = (segment: Segment, entry: Entry): void => {
|
||||
if (Node.name(segment.list) !== entry.listType) {
|
||||
segment.list = Replication.mutate(segment.list, entry.listType);
|
||||
}
|
||||
Attr.setAll(segment.list, entry.listAttributes);
|
||||
};
|
||||
|
||||
const createItem = (scope: Document, attr: Record<string, any>, content: Element[]): Element => {
|
||||
const item = Element.fromTag('li', scope);
|
||||
Attr.setAll(item, attr);
|
||||
InsertAll.append(item, content);
|
||||
return item;
|
||||
};
|
||||
|
||||
const appendItem = (segment: Segment, item: Element): void => {
|
||||
Insert.append(segment.list, item);
|
||||
segment.item = item;
|
||||
};
|
||||
|
||||
const writeShallow = (scope: Document, cast: Segment[], entry: Entry): Segment[] => {
|
||||
const newCast = cast.slice(0, entry.depth);
|
||||
|
||||
Arr.last(newCast).each((segment) => {
|
||||
const item = createItem(scope, entry.itemAttributes, entry.content);
|
||||
appendItem(segment, item);
|
||||
normalizeSegment(segment, entry);
|
||||
});
|
||||
|
||||
return newCast;
|
||||
};
|
||||
|
||||
const writeDeep = (scope: Document, cast: Segment[], entry: Entry): Segment[] => {
|
||||
const segments = createSegments(scope, entry, entry.depth - cast.length);
|
||||
joinSegments(segments);
|
||||
populateSegments(segments, entry);
|
||||
appendSegments(cast, segments);
|
||||
|
||||
return cast.concat(segments);
|
||||
};
|
||||
|
||||
const composeList = (scope: Document, entries: Entry[]): Option<Element> => {
|
||||
const cast: Segment[] = Arr.foldl(entries, (cast, entry) => {
|
||||
return entry.depth > cast.length ? writeDeep(scope, cast, entry) : writeShallow(scope, cast, entry);
|
||||
}, []);
|
||||
|
||||
return Arr.head(cast).map((segment) => segment.list);
|
||||
};
|
||||
|
||||
export { composeList };
|
@@ -1,67 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import { Element, Traverse, Replication, Attr, Node } from '@ephox/sugar';
|
||||
import { Arr, Option } from '@ephox/katamari';
|
||||
import { hasLastChildList, ListType } from './Util';
|
||||
|
||||
/*
|
||||
General workflow: Parse lists to entries -> Manipulate entries -> Compose entries to lists
|
||||
|
||||
0-------1---2--------->Depth
|
||||
<ol> |
|
||||
<li>a</li> | Entry { depth: 1, content: [a], listType: ListType.OL, ... }
|
||||
<li>b | Entry { depth: 1, content: [b], listType: ListType.OL, ... }
|
||||
<ul> |
|
||||
<li>c</li> | Entry { depth: 2, content: [c], listType: ListType.UL, ... }
|
||||
</ul> |
|
||||
</li> |
|
||||
</ol> |
|
||||
0-------1---2--------->Depth
|
||||
*/
|
||||
|
||||
export interface Entry {
|
||||
depth: number;
|
||||
content: Element[];
|
||||
isSelected: boolean;
|
||||
listType: ListType;
|
||||
listAttributes: Record<string, any>;
|
||||
itemAttributes: Record<string, any>;
|
||||
}
|
||||
|
||||
const isIndented = (entry: Entry) => {
|
||||
return entry.depth > 0;
|
||||
};
|
||||
|
||||
const isSelected = (entry: Entry) => {
|
||||
return entry.isSelected;
|
||||
};
|
||||
|
||||
const cloneItemContent = (li: Element): Element[] => {
|
||||
const children = Traverse.children(li);
|
||||
const content = hasLastChildList(li) ? children.slice(0, -1) : children;
|
||||
return Arr.map(content, Replication.deep);
|
||||
};
|
||||
|
||||
const createEntry = (li: Element, depth: number, isSelected: boolean): Option<Entry> => {
|
||||
return Traverse.parent(li).filter(Node.isElement).map((list) => {
|
||||
return {
|
||||
depth,
|
||||
isSelected,
|
||||
content: cloneItemContent(li),
|
||||
itemAttributes: Attr.clone(li),
|
||||
listAttributes: Attr.clone(list),
|
||||
listType: Node.name(list) as ListType
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
export {
|
||||
createEntry,
|
||||
isIndented,
|
||||
isSelected
|
||||
};
|
@@ -1,29 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import { Entry } from './Entry';
|
||||
|
||||
export const enum Indentation {
|
||||
Indent = 'Indent',
|
||||
Outdent = 'Outdent',
|
||||
Flatten = 'Flatten'
|
||||
}
|
||||
|
||||
export const indentEntry = (indentation: Indentation, entry: Entry): void => {
|
||||
switch (indentation) {
|
||||
case Indentation.Indent:
|
||||
entry.depth ++;
|
||||
break;
|
||||
|
||||
case Indentation.Outdent:
|
||||
entry.depth --;
|
||||
break;
|
||||
|
||||
case Indentation.Flatten:
|
||||
entry.depth = 0;
|
||||
}
|
||||
};
|
@@ -1,48 +0,0 @@
|
||||
export function isCheckboxListItem(element) {
|
||||
return element.classList && element.classList.contains('joplin-checklist');
|
||||
}
|
||||
|
||||
export function findContainerListTypeFromEvent(event) {
|
||||
if (isCheckboxListItem(event.element)) return 'joplinChecklist';
|
||||
|
||||
for (const parent of event.parents) {
|
||||
if (isCheckboxListItem(parent)) return 'joplinChecklist';
|
||||
}
|
||||
|
||||
return 'regular';
|
||||
}
|
||||
|
||||
export function findContainerListTypeFromElement(element) {
|
||||
while (element) {
|
||||
if (element.nodeName === 'UL' || element.nodName === 'OL') {
|
||||
return isCheckboxListItem(element) ? 'joplinChecklist' : 'regular';
|
||||
}
|
||||
element = element.parentNode;
|
||||
}
|
||||
|
||||
return 'regular';
|
||||
}
|
||||
|
||||
export function isJoplinChecklistItem(element) {
|
||||
if (element.nodeName !== 'LI') return false;
|
||||
const listType = findContainerListTypeFromElement(element);
|
||||
return listType === 'joplinChecklist';
|
||||
}
|
||||
|
||||
export function addJoplinChecklistCommands(editor, ToggleList) {
|
||||
editor.addCommand('ToggleJoplinChecklistItem', function (ui, detail) {
|
||||
const element = detail.element;
|
||||
if (!isJoplinChecklistItem(element)) return;
|
||||
|
||||
if (!element.classList || !element.classList.contains('checked')) {
|
||||
element.classList.add('checked');
|
||||
} else {
|
||||
element.classList.remove('checked');
|
||||
}
|
||||
});
|
||||
|
||||
editor.addCommand('InsertJoplinChecklist', function (ui, detail) {
|
||||
detail = Object.assign({}, detail, { listType: 'joplinChecklist' });
|
||||
ToggleList.toggleList(editor, 'UL', detail);
|
||||
});
|
||||
}
|
@@ -1,68 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import { Arr, Fun, Option, Options } from '@ephox/katamari';
|
||||
import { Element, Fragment, InsertAll, Remove } from '@ephox/sugar';
|
||||
import Editor from 'tinymce/core/api/Editor';
|
||||
import { fireListEvent } from '../api/Events';
|
||||
import { ListAction } from '../core/ListAction';
|
||||
import * as Selection from '../core/Selection';
|
||||
import { createTextBlock } from '../core/TextBlock';
|
||||
import { composeList } from './ComposeList';
|
||||
import { Entry, isIndented, isSelected } from './Entry';
|
||||
import { Indentation, indentEntry } from './Indentation';
|
||||
import { normalizeEntries } from './NormalizeEntries';
|
||||
import { EntrySet, ItemSelection, parseLists } from './ParseLists';
|
||||
import { hasFirstChildList } from './Util';
|
||||
|
||||
const outdentedComposer = (editor: Editor, entries: Entry[]): Element[] => {
|
||||
return Arr.map(entries, (entry) => {
|
||||
const content = Fragment.fromElements(entry.content);
|
||||
return Element.fromDom(createTextBlock(editor, content.dom()));
|
||||
});
|
||||
};
|
||||
|
||||
const indentedComposer = (editor: Editor, entries: Entry[]): Element[] => {
|
||||
normalizeEntries(entries);
|
||||
return composeList(editor.contentDocument, entries).toArray();
|
||||
};
|
||||
|
||||
const composeEntries = (editor, entries: Entry[]): Element[] => {
|
||||
return Arr.bind(Arr.groupBy(entries, isIndented), (entries) => {
|
||||
const groupIsIndented = Arr.head(entries).map(isIndented).getOr(false);
|
||||
return groupIsIndented ? indentedComposer(editor, entries) : outdentedComposer(editor, entries);
|
||||
});
|
||||
};
|
||||
|
||||
const indentSelectedEntries = (entries: Entry[], indentation: Indentation): void => {
|
||||
Arr.each(Arr.filter(entries, isSelected), (entry) => indentEntry(indentation, entry));
|
||||
};
|
||||
|
||||
const getItemSelection = (editor: Editor): Option<ItemSelection> => {
|
||||
const selectedListItems = Arr.map(Selection.getSelectedListItems(editor), Element.fromDom);
|
||||
|
||||
return Options.lift2(
|
||||
Arr.find(selectedListItems, Fun.not(hasFirstChildList)),
|
||||
Arr.find(Arr.reverse(selectedListItems), Fun.not(hasFirstChildList)),
|
||||
(start, end) => ({ start, end }));
|
||||
};
|
||||
|
||||
const listIndentation = (editor: Editor, lists: Element[], indentation: Indentation) => {
|
||||
const entrySets: EntrySet[] = parseLists(lists, getItemSelection(editor));
|
||||
|
||||
Arr.each(entrySets, (entrySet) => {
|
||||
indentSelectedEntries(entrySet.entries, indentation);
|
||||
const composedLists = composeEntries(editor, entrySet.entries);
|
||||
Arr.each(composedLists, (composedList) => {
|
||||
fireListEvent(editor, indentation === Indentation.Indent ? ListAction.IndentList : ListAction.OutdentList, composedList.dom());
|
||||
});
|
||||
InsertAll.before(entrySet.sourceList, composedLists);
|
||||
Remove.remove(entrySet.sourceList);
|
||||
});
|
||||
};
|
||||
|
||||
export { listIndentation };
|
@@ -1,40 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import { Arr, Option } from '@ephox/katamari';
|
||||
import { Entry } from './Entry';
|
||||
|
||||
const cloneListProperties = (target: Entry, source: Entry): void => {
|
||||
target.listType = source.listType;
|
||||
target.listAttributes = { ...source.listAttributes };
|
||||
};
|
||||
|
||||
// Closest entry above in the same list
|
||||
const previousSiblingEntry = (entries: Entry[], start: number): Option<Entry> => {
|
||||
const depth = entries[start].depth;
|
||||
for (let i = start - 1; i >= 0; i--) {
|
||||
if (entries[i].depth === depth) {
|
||||
return Option.some(entries[i]);
|
||||
}
|
||||
if (entries[i].depth < depth) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Option.none();
|
||||
};
|
||||
|
||||
const normalizeEntries = (entries: Entry[]): void => {
|
||||
Arr.each(entries, (entry, i) => {
|
||||
previousSiblingEntry(entries, i).each((matchingEntry) => {
|
||||
cloneListProperties(entry, matchingEntry);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export {
|
||||
normalizeEntries
|
||||
};
|
@@ -1,71 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import { Arr, Cell, Option } from '@ephox/katamari';
|
||||
import { Compare, Element, Traverse } from '@ephox/sugar';
|
||||
import { createEntry, Entry } from './Entry';
|
||||
import { isList } from './Util';
|
||||
|
||||
type Parser = (depth: number, itemSelection: Option<ItemSelection>, selectionState: Cell<boolean>, element: Element) => Entry[];
|
||||
|
||||
export interface ItemSelection {
|
||||
start: Element;
|
||||
end: Element;
|
||||
}
|
||||
|
||||
export interface EntrySet {
|
||||
entries: Entry[];
|
||||
sourceList: Element;
|
||||
}
|
||||
|
||||
const parseItem: Parser = (depth: number, itemSelection: Option<ItemSelection>, selectionState: Cell<boolean>, item: Element): Entry[] => {
|
||||
return Traverse.firstChild(item).filter(isList).fold(() => {
|
||||
|
||||
// Update selectionState (start)
|
||||
itemSelection.each((selection) => {
|
||||
if (Compare.eq(selection.start, item)) {
|
||||
selectionState.set(true);
|
||||
}
|
||||
});
|
||||
|
||||
const currentItemEntry = createEntry(item, depth, selectionState.get());
|
||||
|
||||
// Update selectionState (end)
|
||||
itemSelection.each((selection) => {
|
||||
if (Compare.eq(selection.end, item)) {
|
||||
selectionState.set(false);
|
||||
}
|
||||
});
|
||||
|
||||
const childListEntries: Entry[] = Traverse.lastChild(item)
|
||||
.filter(isList)
|
||||
.map((list) => parseList(depth, itemSelection, selectionState, list))
|
||||
.getOr([]);
|
||||
|
||||
return currentItemEntry.toArray().concat(childListEntries);
|
||||
}, (list) => parseList(depth, itemSelection, selectionState, list));
|
||||
};
|
||||
|
||||
const parseList: Parser = (depth: number, itemSelection: Option<ItemSelection>, selectionState: Cell<boolean>, list: Element): Entry[] => {
|
||||
return Arr.bind(Traverse.children(list), (element) => {
|
||||
const parser = isList(element) ? parseList : parseItem;
|
||||
const newDepth = depth + 1;
|
||||
return parser(newDepth, itemSelection, selectionState, element);
|
||||
});
|
||||
};
|
||||
|
||||
const parseLists = (lists: Element[], itemSelection: Option<ItemSelection>): EntrySet[] => {
|
||||
const selectionState = Cell(false);
|
||||
const initialDepth = 0;
|
||||
|
||||
return Arr.map(lists, (list) => ({
|
||||
sourceList: list,
|
||||
entries: parseList(initialDepth, itemSelection, selectionState, list)
|
||||
}));
|
||||
};
|
||||
|
||||
export { parseLists };
|
@@ -1,31 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import { Element, Traverse, Compare } from '@ephox/sugar';
|
||||
|
||||
export const enum ListType {
|
||||
OL = 'ol',
|
||||
UL = 'ul'
|
||||
}
|
||||
|
||||
const isList = (el: Element) => {
|
||||
return Compare.is(el, 'OL,UL');
|
||||
};
|
||||
|
||||
const hasFirstChildList = (el: Element) => {
|
||||
return Traverse.firstChild(el).map(isList).getOr(false);
|
||||
};
|
||||
|
||||
const hasLastChildList = (el: Element) => {
|
||||
return Traverse.lastChild(el).map(isList).getOr(false);
|
||||
};
|
||||
|
||||
export {
|
||||
isList,
|
||||
hasFirstChildList,
|
||||
hasLastChildList
|
||||
};
|
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "amd",
|
||||
"target": "es6",
|
||||
"sourceMap": true,
|
||||
"outFile": "list.js"
|
||||
},
|
||||
"include": [
|
||||
"./**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules"
|
||||
]
|
||||
}
|
@@ -1,113 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import Tools from 'tinymce/core/api/util/Tools';
|
||||
import * as Settings from '../api/Settings';
|
||||
import * as NodeType from '../core/NodeType';
|
||||
import Editor from 'tinymce/core/api/Editor';
|
||||
import { isCustomList } from '../core/Util';
|
||||
import { findContainerListTypeFromEvent, isJoplinChecklistItem } from '../listModel/JoplinListUtil';
|
||||
|
||||
const findIndex = function (list, predicate) {
|
||||
for (let index = 0; index < list.length; index++) {
|
||||
const element = list[index];
|
||||
|
||||
if (predicate(element)) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
const listState = function (editor: Editor, listName, options:any = {}) {
|
||||
options = {
|
||||
listType: 'regular',
|
||||
...options,
|
||||
};
|
||||
|
||||
return function (buttonApi) {
|
||||
const nodeChangeHandler = (e) => {
|
||||
const tableCellIndex = findIndex(e.parents, NodeType.isTableCellNode);
|
||||
const parents = tableCellIndex !== -1 ? e.parents.slice(0, tableCellIndex) : e.parents;
|
||||
const lists = Tools.grep(parents, NodeType.isListNode);
|
||||
const listType = findContainerListTypeFromEvent(e);
|
||||
buttonApi.setActive(listType === options.listType && lists.length > 0 && lists[0].nodeName === listName && !isCustomList(lists[0]));
|
||||
};
|
||||
|
||||
const editorClickHandler = (event) => {
|
||||
if (!isJoplinChecklistItem(event.target)) return;
|
||||
|
||||
// We only process the click if it's within the checkbox itself (and not the label).
|
||||
// That checkbox, based on
|
||||
// the current styling is in the negative margin, so offsetX is negative when clicking
|
||||
// on the checkbox itself, and positive when clicking on the label. This is strongly
|
||||
// dependent on how the checkbox is styled, so if the style is changed, this might need
|
||||
// to be updated too.
|
||||
// For the styling, see:
|
||||
// packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/checkbox.ts
|
||||
//
|
||||
// The previous solution was to use "pointer-event: none", which mostly work, however
|
||||
// it means that links are no longer clickable when they are within the checkbox label.
|
||||
if (event.offsetX >= 0) return;
|
||||
|
||||
editor.execCommand('ToggleJoplinChecklistItem', false, { element: event.target });
|
||||
}
|
||||
|
||||
if (options.listType === 'joplinChecklist') {
|
||||
editor.on('click', editorClickHandler);
|
||||
}
|
||||
|
||||
editor.on('NodeChange', nodeChangeHandler);
|
||||
|
||||
return () => {
|
||||
if (options.listType === 'joplinChecklist') {
|
||||
editor.off('click', editorClickHandler);
|
||||
}
|
||||
editor.off('NodeChange', nodeChangeHandler);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const register = function (editor: Editor) {
|
||||
const hasPlugin = function (editor, plugin) {
|
||||
const plugins = editor.settings.plugins ? editor.settings.plugins : '';
|
||||
return Tools.inArray(plugins.split(/[ ,]/), plugin) !== -1;
|
||||
};
|
||||
|
||||
const _ = Settings.getLocalizationFunction(editor);
|
||||
const exec = (command) => () => editor.execCommand(command);
|
||||
|
||||
if (!hasPlugin(editor, 'advlist')) {
|
||||
editor.ui.registry.addToggleButton('numlist', {
|
||||
icon: 'ordered-list',
|
||||
active: false,
|
||||
tooltip: 'Numbered list',
|
||||
onAction: exec('InsertOrderedList'),
|
||||
onSetup: listState(editor, 'OL')
|
||||
});
|
||||
|
||||
editor.ui.registry.addToggleButton('bullist', {
|
||||
icon: 'unordered-list',
|
||||
active: false,
|
||||
tooltip: 'Bullet list',
|
||||
onAction: exec('InsertUnorderedList'),
|
||||
onSetup: listState(editor, 'UL')
|
||||
});
|
||||
|
||||
editor.ui.registry.addToggleButton('joplinChecklist', {
|
||||
icon: 'checklist',
|
||||
active: false,
|
||||
tooltip: _('Checkbox list'),
|
||||
onAction: exec('InsertJoplinChecklist'),
|
||||
onSetup: listState(editor, 'UL', { listType: 'joplinChecklist' })
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export {
|
||||
register
|
||||
};
|
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"moduleResolution": "node",
|
||||
"target": "es5",
|
||||
"module": "es2015",
|
||||
"importHelpers": true,
|
||||
"lib": ["es2015"],
|
||||
"declaration": true,
|
||||
"noUnusedLocals": true,
|
||||
"sourceMap": true,
|
||||
"outDir": "lib",
|
||||
"baseUrl": "."
|
||||
},
|
||||
"include": [
|
||||
"src/demo/ts",
|
||||
"src/main/ts",
|
||||
"src/test/ts",
|
||||
"node_modules/@ephox/**/*/api/Main.d.ts"
|
||||
],
|
||||
"files": [
|
||||
"global.d.ts",
|
||||
],
|
||||
}
|
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"defaultSeverity": "error",
|
||||
"extends": [
|
||||
"@ephox/tslint-rules/tslint.json"
|
||||
],
|
||||
"jsRules": {},
|
||||
"rules": {},
|
||||
"rulesDirectory": []
|
||||
}
|