You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-12-23 23:33:01 +02:00
Compare commits
26 Commits
server_sha
...
release-2.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
63136a6f0d | ||
|
|
b45585dc21 | ||
|
|
46786cc186 | ||
|
|
eca6e2ff3d | ||
|
|
523382ec83 | ||
|
|
3d87e89753 | ||
|
|
acc5959284 | ||
|
|
6c4f71689c | ||
|
|
bb44c4e6ab | ||
|
|
4b39d30255 | ||
|
|
3a9867db33 | ||
|
|
c831c7bf6f | ||
|
|
c7cc5cc1a9 | ||
|
|
eb4b0e64ea | ||
|
|
9dabac0afe | ||
|
|
73f0f861a5 | ||
|
|
dd0b983a09 | ||
|
|
c45f961b8c | ||
|
|
05ec7cc8fa | ||
|
|
57a1d03b4b | ||
|
|
1df2d8d7af | ||
|
|
b1d0c15210 | ||
|
|
2fd4fb3e73 | ||
|
|
9f17b28f85 | ||
|
|
8ada059401 | ||
|
|
0175348868 |
@@ -856,6 +856,9 @@ packages/generator-joplin/generators/app/templates/api_index.js.map
|
||||
packages/generator-joplin/generators/app/templates/src/index.d.ts
|
||||
packages/generator-joplin/generators/app/templates/src/index.js
|
||||
packages/generator-joplin/generators/app/templates/src/index.js.map
|
||||
packages/htmlpack/src/index.d.ts
|
||||
packages/htmlpack/src/index.js
|
||||
packages/htmlpack/src/index.js.map
|
||||
packages/lib/AsyncActionQueue.d.ts
|
||||
packages/lib/AsyncActionQueue.js
|
||||
packages/lib/AsyncActionQueue.js.map
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -841,6 +841,9 @@ packages/generator-joplin/generators/app/templates/api_index.js.map
|
||||
packages/generator-joplin/generators/app/templates/src/index.d.ts
|
||||
packages/generator-joplin/generators/app/templates/src/index.js
|
||||
packages/generator-joplin/generators/app/templates/src/index.js.map
|
||||
packages/htmlpack/src/index.d.ts
|
||||
packages/htmlpack/src/index.js
|
||||
packages/htmlpack/src/index.js.map
|
||||
packages/lib/AsyncActionQueue.d.ts
|
||||
packages/lib/AsyncActionQueue.js
|
||||
packages/lib/AsyncActionQueue.js.map
|
||||
|
||||
4
packages/app-cli/package-lock.json
generated
4
packages/app-cli/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "joplin",
|
||||
"version": "2.3.2",
|
||||
"version": "2.4.1",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "joplin",
|
||||
"version": "2.3.2",
|
||||
"version": "2.4.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"aws-sdk": "^2.588.0",
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
],
|
||||
"owner": "Laurent Cozic"
|
||||
},
|
||||
"version": "2.4.0",
|
||||
"version": "2.4.1",
|
||||
"bin": {
|
||||
"joplin": "./main.js"
|
||||
},
|
||||
|
||||
@@ -75,6 +75,7 @@ interface Props {
|
||||
shareInvitations: ShareInvitation[];
|
||||
isSafeMode: boolean;
|
||||
needApiAuth: boolean;
|
||||
processingShareInvitationResponse: boolean;
|
||||
}
|
||||
|
||||
interface ShareFolderDialogOptions {
|
||||
@@ -197,6 +198,7 @@ class MainScreenComponent extends React.Component<Props, State> {
|
||||
}
|
||||
|
||||
private showShareInvitationNotification(props: Props): boolean {
|
||||
if (props.processingShareInvitationResponse) return false;
|
||||
return !!props.shareInvitations.find(i => i.status === 0);
|
||||
}
|
||||
|
||||
@@ -546,8 +548,16 @@ class MainScreenComponent extends React.Component<Props, State> {
|
||||
};
|
||||
|
||||
const onInvitationRespond = async (shareUserId: string, accept: boolean) => {
|
||||
await ShareService.instance().respondInvitation(shareUserId, accept);
|
||||
await ShareService.instance().refreshShareInvitations();
|
||||
// The below functions can take a bit of time to complete so in the
|
||||
// meantime we hide the notification so that the user doesn't click
|
||||
// multiple times on the Accept link.
|
||||
ShareService.instance().setProcessingShareInvitationResponse(true);
|
||||
try {
|
||||
await ShareService.instance().respondInvitation(shareUserId, accept);
|
||||
await ShareService.instance().refreshShareInvitations();
|
||||
} finally {
|
||||
ShareService.instance().setProcessingShareInvitationResponse(false);
|
||||
}
|
||||
void reg.scheduleSync(1000);
|
||||
};
|
||||
|
||||
@@ -853,6 +863,7 @@ const mapStateToProps = (state: AppState) => {
|
||||
mainLayout: state.mainLayout,
|
||||
startupPluginsLoaded: state.startupPluginsLoaded,
|
||||
shareInvitations: state.shareService.shareInvitations,
|
||||
processingShareInvitationResponse: state.shareService.processingShareInvitationResponse,
|
||||
isSafeMode: state.settings.isSafeMode,
|
||||
needApiAuth: state.needApiAuth,
|
||||
showInstallTemplatesPlugin: state.hasLegacyTemplates && !state.pluginService.plugins['joplin.plugin.templates'],
|
||||
|
||||
4
packages/app-desktop/package-lock.json
generated
4
packages/app-desktop/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@joplin/app-desktop",
|
||||
"version": "2.4.8",
|
||||
"version": "2.4.12",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@joplin/app-desktop",
|
||||
"version": "2.4.8",
|
||||
"version": "2.4.12",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^5.13.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/app-desktop",
|
||||
"version": "2.4.8",
|
||||
"version": "2.4.12",
|
||||
"description": "Joplin for Desktop",
|
||||
"main": "main.js",
|
||||
"private": true,
|
||||
@@ -37,7 +37,7 @@
|
||||
"asar": true,
|
||||
"asarUnpack": "./node_modules/node-notifier/vendor/**",
|
||||
"win": {
|
||||
"rfc3161TimeStampServer": "http://timestamp.comodoca.com/rfc3161",
|
||||
"rfc3161TimeStampServer": "http://sha256timestamp.ws.symantec.com/sha256/timestamp",
|
||||
"icon": "../../Assets/ImageSources/Joplin.ico",
|
||||
"target": [
|
||||
{
|
||||
|
||||
@@ -141,8 +141,8 @@ android {
|
||||
applicationId "net.cozic.joplin"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 2097650
|
||||
versionName "2.4.2"
|
||||
versionCode 2097651
|
||||
versionName "2.4.3"
|
||||
ndk {
|
||||
abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
|
||||
}
|
||||
|
||||
@@ -486,13 +486,13 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Joplin/Joplin.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 72;
|
||||
CURRENT_PROJECT_VERSION = 76;
|
||||
DEVELOPMENT_TEAM = A9BXAFS6CT;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Joplin/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 12.4.0;
|
||||
MARKETING_VERSION = 12.5.2;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
@@ -514,12 +514,12 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Joplin/Joplin.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 72;
|
||||
CURRENT_PROJECT_VERSION = 76;
|
||||
DEVELOPMENT_TEAM = A9BXAFS6CT;
|
||||
INFOPLIST_FILE = Joplin/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 12.4.0;
|
||||
MARKETING_VERSION = 12.5.2;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
@@ -659,14 +659,14 @@
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 72;
|
||||
CURRENT_PROJECT_VERSION = 76;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = A9BXAFS6CT;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
INFOPLIST_FILE = ShareExtension/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 12.4.0;
|
||||
MARKETING_VERSION = 12.5.2;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = net.cozic.joplin.ShareExtension;
|
||||
@@ -690,14 +690,14 @@
|
||||
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 72;
|
||||
CURRENT_PROJECT_VERSION = 76;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = A9BXAFS6CT;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
INFOPLIST_FILE = ShareExtension/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 12.4.0;
|
||||
MARKETING_VERSION = 12.5.2;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = net.cozic.joplin.ShareExtension;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
||||
@@ -488,7 +488,7 @@ SPEC CHECKSUMS:
|
||||
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
|
||||
DoubleConversion: cf9b38bf0b2d048436d9a82ad2abe1404f11e7de
|
||||
FBLazyVector: e686045572151edef46010a6f819ade377dfeb4b
|
||||
FBReactNativeSpec: d2f54de51f69366bd1f5c1fb9270698dce678f8d
|
||||
FBReactNativeSpec: 6da2c8ff1ebe6b6cf4510fcca58c24c4d02b16fc
|
||||
glog: 73c2498ac6884b13ede40eda8228cb1eee9d9d62
|
||||
JoplinCommonShareExtension: 270b4f8eb4e22828eeda433a04ed689fc1fd09b5
|
||||
JoplinRNShareExtension: 7137e9787374e1b0797ecbef9103d1588d90e403
|
||||
|
||||
@@ -498,6 +498,7 @@ async function initialize(dispatch: Function) {
|
||||
let locale = NativeModules.I18nManager.localeIdentifier;
|
||||
if (!locale) locale = defaultLocale();
|
||||
Setting.setValue('locale', closestSupportedLocale(locale));
|
||||
Setting.setValue('sync.target', 0);
|
||||
Setting.setValue('firstStart', 0);
|
||||
}
|
||||
|
||||
|
||||
2
packages/fork-htmlparser2/package-lock.json
generated
2
packages/fork-htmlparser2/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/fork-htmlparser2",
|
||||
"version": "4.1.34",
|
||||
"version": "4.1.36",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@joplin/fork-htmlparser2",
|
||||
"description": "Fast & forgiving HTML/XML/RSS parser",
|
||||
"version": "4.1.34",
|
||||
"version": "4.1.36",
|
||||
"author": "Felix Boehm <me@feedic.com>",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
@@ -65,5 +65,5 @@
|
||||
"prettier": {
|
||||
"tabWidth": 4
|
||||
},
|
||||
"gitHead": "80c0089d2c52aff608b2bea74389de5a7f12f2e2"
|
||||
"gitHead": "eb4b0e64eab40a51b0895d3a40a9d8c3cb7b1b14"
|
||||
}
|
||||
|
||||
2
packages/fork-sax/package-lock.json
generated
2
packages/fork-sax/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/fork-sax",
|
||||
"version": "1.2.38",
|
||||
"version": "1.2.40",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@joplin/fork-sax",
|
||||
"description": "An evented streaming XML parser in JavaScript",
|
||||
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
|
||||
"version": "1.2.38",
|
||||
"version": "1.2.40",
|
||||
"main": "lib/sax.js",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
@@ -18,5 +18,5 @@
|
||||
"standard": "^8.6.0",
|
||||
"tap": "^10.5.1"
|
||||
},
|
||||
"gitHead": "80c0089d2c52aff608b2bea74389de5a7f12f2e2"
|
||||
"gitHead": "eb4b0e64eab40a51b0895d3a40a9d8c3cb7b1b14"
|
||||
}
|
||||
|
||||
1
packages/htmlpack/.gitignore
vendored
Normal file
1
packages/htmlpack/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
dist/*
|
||||
19
packages/htmlpack/README.md
Normal file
19
packages/htmlpack/README.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# HTMLPACK
|
||||
|
||||
Pack an HTML and all its JavaScript, CSS, image, fonts, and external files into a single HTML file. JavaScript and CSS is embedded in STYLE and SCRIPT tags, while all other files and images are converted to dataUri format and embedded in the document.
|
||||
|
||||
## Usage
|
||||
|
||||
```javascript
|
||||
import htmlpack from '@joplin/htmlpack';
|
||||
htmlpack('/path/to/input.html', '/path/to/output.html');
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- The script works in synchronous way so it will block the calling process while running.
|
||||
- No security check on what's included.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
489
packages/htmlpack/package-lock.json
generated
Normal file
489
packages/htmlpack/package-lock.json
generated
Normal file
@@ -0,0 +1,489 @@
|
||||
{
|
||||
"name": "@joplin/htmlpack",
|
||||
"version": "1.0.1",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@joplin/htmlpack",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@joplin/fork-htmlparser2": "^4.1.34",
|
||||
"css": "^3.0.0",
|
||||
"datauri": "^4.1.0",
|
||||
"fs-extra": "^10.0.0",
|
||||
"html-entities": "^1.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "^9.0.6"
|
||||
}
|
||||
},
|
||||
"../fork-htmlparser2": {
|
||||
"name": "@joplin/fork-htmlparser2",
|
||||
"version": "4.1.34",
|
||||
"extraneous": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^3.0.0",
|
||||
"domutils": "^2.0.0",
|
||||
"entities": "^2.0.0",
|
||||
"fs-extra": "^10.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^25.1.3",
|
||||
"@types/node": "^13.1.1",
|
||||
"@typescript-eslint/eslint-plugin": "^1.13.0",
|
||||
"@typescript-eslint/parser": "^1.13.0",
|
||||
"coveralls": "^3.0.1",
|
||||
"eslint": "^6.0.0",
|
||||
"eslint-config-prettier": "^6.0.0",
|
||||
"jest": "^26.6.3",
|
||||
"prettier": "^1.18.2",
|
||||
"ts-jest": "^24.0.2",
|
||||
"typescript": "^3.5.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@joplin/fork-htmlparser2": {
|
||||
"version": "4.1.34",
|
||||
"resolved": "https://registry.npmjs.org/@joplin/fork-htmlparser2/-/fork-htmlparser2-4.1.34.tgz",
|
||||
"integrity": "sha512-1/tQZEDnI36RaEJte0eumw1/c8OhmJOpgFyW+Nxsk2u/vvcgnEvjFjauiH2ZxtO5FTJB3BMQ4M23+Y5dw2cnnw==",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^3.0.0",
|
||||
"domutils": "^2.0.0",
|
||||
"entities": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/fs-extra": {
|
||||
"version": "9.0.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz",
|
||||
"integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "16.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.10.1.tgz",
|
||||
"integrity": "sha512-4/Z9DMPKFexZj/Gn3LylFgamNKHm4K3QDi0gz9B26Uk0c8izYf97B5fxfpspMNkWlFupblKM/nV8+NA9Ffvr+w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/atob": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
|
||||
"integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
|
||||
"bin": {
|
||||
"atob": "bin/atob.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/css": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/css/-/css-3.0.0.tgz",
|
||||
"integrity": "sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==",
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.4",
|
||||
"source-map": "^0.6.1",
|
||||
"source-map-resolve": "^0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/datauri": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/datauri/-/datauri-4.1.0.tgz",
|
||||
"integrity": "sha512-y17kh32+I82G+ED9MNWFkZiP/Cq/vO1hN9+tSZsT9C9qn3NrvcBnh7crSepg0AQPge1hXx2Ca44s1FRdv0gFWA==",
|
||||
"dependencies": {
|
||||
"image-size": "1.0.0",
|
||||
"mimer": "^2.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/decode-uri-component": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
|
||||
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-serializer": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
|
||||
"integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^4.2.0",
|
||||
"entities": "^2.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-serializer/node_modules/domhandler": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz",
|
||||
"integrity": "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/domelementtype": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
|
||||
"integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/domhandler": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.3.0.tgz",
|
||||
"integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/domutils": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
|
||||
"integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
|
||||
"dependencies": {
|
||||
"dom-serializer": "^1.0.1",
|
||||
"domelementtype": "^2.2.0",
|
||||
"domhandler": "^4.2.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/domutils?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/domutils/node_modules/domhandler": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz",
|
||||
"integrity": "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/entities": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
|
||||
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-extra": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz",
|
||||
"integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.8",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz",
|
||||
"integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg=="
|
||||
},
|
||||
"node_modules/html-entities": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz",
|
||||
"integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA=="
|
||||
},
|
||||
"node_modules/image-size": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.0.tgz",
|
||||
"integrity": "sha512-JLJ6OwBfO1KcA+TvJT+v8gbE6iWbj24LyDNFgFEN0lzegn6cC6a/p3NIDaepMsJjQjlUWqIC7wJv8lBFxPNjcw==",
|
||||
"dependencies": {
|
||||
"queue": "6.0.2"
|
||||
},
|
||||
"bin": {
|
||||
"image-size": "bin/image-size.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"node_modules/jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"dependencies": {
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mimer": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/mimer/-/mimer-2.0.2.tgz",
|
||||
"integrity": "sha512-izxvjsB7Ur5HrTbPu6VKTrzxSMBFBqyZQc6dWlZNQ4/wAvf886fD4lrjtFd8IQ8/WmZKdxKjUtqFFNaj3hQ52g==",
|
||||
"bin": {
|
||||
"mimer": "bin/mimer"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
}
|
||||
},
|
||||
"node_modules/queue": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz",
|
||||
"integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==",
|
||||
"dependencies": {
|
||||
"inherits": "~2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-resolve": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz",
|
||||
"integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==",
|
||||
"dependencies": {
|
||||
"atob": "^2.1.2",
|
||||
"decode-uri-component": "^0.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/universalify": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
|
||||
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@joplin/fork-htmlparser2": {
|
||||
"version": "4.1.34",
|
||||
"resolved": "https://registry.npmjs.org/@joplin/fork-htmlparser2/-/fork-htmlparser2-4.1.34.tgz",
|
||||
"integrity": "sha512-1/tQZEDnI36RaEJte0eumw1/c8OhmJOpgFyW+Nxsk2u/vvcgnEvjFjauiH2ZxtO5FTJB3BMQ4M23+Y5dw2cnnw==",
|
||||
"requires": {
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^3.0.0",
|
||||
"domutils": "^2.0.0",
|
||||
"entities": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"@types/fs-extra": {
|
||||
"version": "9.0.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz",
|
||||
"integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "16.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.10.1.tgz",
|
||||
"integrity": "sha512-4/Z9DMPKFexZj/Gn3LylFgamNKHm4K3QDi0gz9B26Uk0c8izYf97B5fxfpspMNkWlFupblKM/nV8+NA9Ffvr+w==",
|
||||
"dev": true
|
||||
},
|
||||
"atob": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
|
||||
"integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg=="
|
||||
},
|
||||
"css": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/css/-/css-3.0.0.tgz",
|
||||
"integrity": "sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==",
|
||||
"requires": {
|
||||
"inherits": "^2.0.4",
|
||||
"source-map": "^0.6.1",
|
||||
"source-map-resolve": "^0.6.0"
|
||||
}
|
||||
},
|
||||
"datauri": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/datauri/-/datauri-4.1.0.tgz",
|
||||
"integrity": "sha512-y17kh32+I82G+ED9MNWFkZiP/Cq/vO1hN9+tSZsT9C9qn3NrvcBnh7crSepg0AQPge1hXx2Ca44s1FRdv0gFWA==",
|
||||
"requires": {
|
||||
"image-size": "1.0.0",
|
||||
"mimer": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"decode-uri-component": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
|
||||
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
|
||||
},
|
||||
"dom-serializer": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
|
||||
"integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
|
||||
"requires": {
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^4.2.0",
|
||||
"entities": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"domhandler": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz",
|
||||
"integrity": "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==",
|
||||
"requires": {
|
||||
"domelementtype": "^2.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"domelementtype": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
|
||||
"integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A=="
|
||||
},
|
||||
"domhandler": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.3.0.tgz",
|
||||
"integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==",
|
||||
"requires": {
|
||||
"domelementtype": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"domutils": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
|
||||
"integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
|
||||
"requires": {
|
||||
"dom-serializer": "^1.0.1",
|
||||
"domelementtype": "^2.2.0",
|
||||
"domhandler": "^4.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"domhandler": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz",
|
||||
"integrity": "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==",
|
||||
"requires": {
|
||||
"domelementtype": "^2.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"entities": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
|
||||
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="
|
||||
},
|
||||
"fs-extra": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz",
|
||||
"integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.2.8",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz",
|
||||
"integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg=="
|
||||
},
|
||||
"html-entities": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz",
|
||||
"integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA=="
|
||||
},
|
||||
"image-size": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.0.tgz",
|
||||
"integrity": "sha512-JLJ6OwBfO1KcA+TvJT+v8gbE6iWbj24LyDNFgFEN0lzegn6cC6a/p3NIDaepMsJjQjlUWqIC7wJv8lBFxPNjcw==",
|
||||
"requires": {
|
||||
"queue": "6.0.2"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.6",
|
||||
"universalify": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"mimer": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/mimer/-/mimer-2.0.2.tgz",
|
||||
"integrity": "sha512-izxvjsB7Ur5HrTbPu6VKTrzxSMBFBqyZQc6dWlZNQ4/wAvf886fD4lrjtFd8IQ8/WmZKdxKjUtqFFNaj3hQ52g=="
|
||||
},
|
||||
"queue": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz",
|
||||
"integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==",
|
||||
"requires": {
|
||||
"inherits": "~2.0.3"
|
||||
}
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
||||
},
|
||||
"source-map-resolve": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz",
|
||||
"integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==",
|
||||
"requires": {
|
||||
"atob": "^2.1.2",
|
||||
"decode-uri-component": "^0.2.0"
|
||||
}
|
||||
},
|
||||
"universalify": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
|
||||
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
24
packages/htmlpack/package.json
Normal file
24
packages/htmlpack/package.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "@joplin/htmlpack",
|
||||
"version": "1.0.1",
|
||||
"description": "Pack an HTML file and all its linked resources into a single HTML file",
|
||||
"main": "dist/index.js",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"tsc": "tsc --project tsconfig.json",
|
||||
"watch": "tsc --watch --project tsconfig.json"
|
||||
},
|
||||
"author": "Laurent Czoic",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@joplin/fork-htmlparser2": "^4.1.35",
|
||||
"css": "^3.0.0",
|
||||
"datauri": "^4.1.0",
|
||||
"fs-extra": "^10.0.0",
|
||||
"html-entities": "^1.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "^9.0.6"
|
||||
},
|
||||
"gitHead": "eb4b0e64eab40a51b0895d3a40a9d8c3cb7b1b14"
|
||||
}
|
||||
218
packages/htmlpack/src/index.ts
Normal file
218
packages/htmlpack/src/index.ts
Normal file
@@ -0,0 +1,218 @@
|
||||
import * as fs from 'fs-extra';
|
||||
const Entities = require('html-entities').AllHtmlEntities;
|
||||
const htmlparser2 = require('@joplin/fork-htmlparser2');
|
||||
const Datauri = require('datauri/sync');
|
||||
const cssParse = require('css/lib/parse');
|
||||
const cssStringify = require('css/lib/stringify');
|
||||
|
||||
const selfClosingElements = [
|
||||
'area',
|
||||
'base',
|
||||
'basefont',
|
||||
'br',
|
||||
'col',
|
||||
'command',
|
||||
'embed',
|
||||
'frame',
|
||||
'hr',
|
||||
'img',
|
||||
'input',
|
||||
'isindex',
|
||||
'keygen',
|
||||
'link',
|
||||
'meta',
|
||||
'param',
|
||||
'source',
|
||||
'track',
|
||||
'wbr',
|
||||
];
|
||||
|
||||
const htmlentities = (s: string): string => {
|
||||
const output = (new Entities()).encode(s);
|
||||
return output.replace(/	/ig, '\t');
|
||||
};
|
||||
|
||||
const dataUriEncode = (filePath: string): string => {
|
||||
const result = Datauri(filePath);
|
||||
return result.content;
|
||||
};
|
||||
|
||||
const attributesHtml = (attr: any) => {
|
||||
const output = [];
|
||||
|
||||
for (const n in attr) {
|
||||
if (!attr.hasOwnProperty(n)) continue;
|
||||
output.push(`${n}="${htmlentities(attr[n])}"`);
|
||||
}
|
||||
|
||||
return output.join(' ');
|
||||
};
|
||||
|
||||
const attrValue = (attrs: any, name: string): string => {
|
||||
if (!attrs[name]) return '';
|
||||
return attrs[name].toLowerCase();
|
||||
};
|
||||
|
||||
const isSelfClosingTag = (tagName: string) => {
|
||||
return selfClosingElements.includes(tagName.toLowerCase());
|
||||
};
|
||||
|
||||
const processCssContent = (cssBaseDir: string, content: string): string => {
|
||||
const o = cssParse(content, {
|
||||
silent: false,
|
||||
});
|
||||
|
||||
for (const rule of o.stylesheet.rules) {
|
||||
if (rule.type === 'font-face') {
|
||||
for (const declaration of rule.declarations) {
|
||||
if (declaration.property === 'src') {
|
||||
declaration.value = declaration.value.replace(/url\((.*?)\)/g, (_v: any, url: string) => {
|
||||
const cssFilePath = `${cssBaseDir}/${url}`;
|
||||
if (fs.existsSync(cssFilePath)) {
|
||||
return `url(${dataUriEncode(cssFilePath)})`;
|
||||
} else {
|
||||
return `url(${url})`;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cssStringify(o);
|
||||
};
|
||||
|
||||
const processLinkTag = (baseDir: string, _name: string, attrs: any): string => {
|
||||
const href = attrValue(attrs, 'href');
|
||||
if (!href) return null;
|
||||
|
||||
const filePath = `${baseDir}/${href}`;
|
||||
const content = fs.readFileSync(filePath, 'utf8');
|
||||
return `<style>${processCssContent(dirname(filePath), content)}</style>`;
|
||||
};
|
||||
|
||||
const processScriptTag = (baseDir: string, _name: string, attrs: any): string => {
|
||||
const src = attrValue(attrs, 'src');
|
||||
if (!src) return null;
|
||||
|
||||
const content = fs.readFileSync(`${baseDir}/${src}`, 'utf8');
|
||||
return `<script>${htmlentities(content)}</script>`;
|
||||
};
|
||||
|
||||
const processImgTag = (baseDir: string, _name: string, attrs: any): string => {
|
||||
const src = attrValue(attrs, 'src');
|
||||
if (!src) return null;
|
||||
|
||||
const filePath = `${baseDir}/${src}`;
|
||||
if (!fs.existsSync(filePath)) return null;
|
||||
|
||||
const modAttrs = { ...attrs };
|
||||
delete modAttrs.src;
|
||||
return `<img src="${dataUriEncode(filePath)}" ${attributesHtml(modAttrs)}/>`;
|
||||
};
|
||||
|
||||
const processAnchorTag = (baseDir: string, _name: string, attrs: any): string => {
|
||||
const href = attrValue(attrs, 'href');
|
||||
if (!href) return null;
|
||||
|
||||
const filePath = `${baseDir}/${href}`;
|
||||
if (!fs.existsSync(filePath)) return null;
|
||||
|
||||
const modAttrs = { ...attrs };
|
||||
modAttrs.href = dataUriEncode(filePath);
|
||||
modAttrs.download = basename(filePath);
|
||||
return `<a ${attributesHtml(modAttrs)}>`;
|
||||
};
|
||||
|
||||
function basename(path: string) {
|
||||
if (!path) throw new Error('Path is empty');
|
||||
const s = path.split(/\/|\\/);
|
||||
return s[s.length - 1];
|
||||
}
|
||||
|
||||
function dirname(path: string) {
|
||||
if (!path) throw new Error('Path is empty');
|
||||
const s = path.split(/\/|\\/);
|
||||
s.pop();
|
||||
return s.join('/');
|
||||
}
|
||||
|
||||
export default async function htmlpack(inputFile: string, outputFile: string) {
|
||||
const inputHtml = await fs.readFile(inputFile, 'utf8');
|
||||
const baseDir = dirname(inputFile);
|
||||
|
||||
const output: string[] = [];
|
||||
|
||||
interface Tag {
|
||||
name: string;
|
||||
}
|
||||
|
||||
const tagStack: Tag[] = [];
|
||||
|
||||
const currentTag = () => {
|
||||
if (!tagStack.length) return { name: '', processed: false };
|
||||
return tagStack[tagStack.length - 1];
|
||||
};
|
||||
|
||||
const parser = new htmlparser2.Parser({
|
||||
|
||||
onopentag: (name: string, attrs: any) => {
|
||||
name = name.toLowerCase();
|
||||
|
||||
let processedResult = '';
|
||||
|
||||
if (name === 'link') {
|
||||
processedResult = processLinkTag(baseDir, name, attrs);
|
||||
}
|
||||
|
||||
if (name === 'script') {
|
||||
processedResult = processScriptTag(baseDir, name, attrs);
|
||||
}
|
||||
|
||||
if (name === 'img') {
|
||||
processedResult = processImgTag(baseDir, name, attrs);
|
||||
}
|
||||
|
||||
if (name === 'a') {
|
||||
processedResult = processAnchorTag(baseDir, name, attrs);
|
||||
}
|
||||
|
||||
tagStack.push({ name });
|
||||
|
||||
if (processedResult) {
|
||||
output.push(processedResult);
|
||||
} else {
|
||||
let attrHtml = attributesHtml(attrs);
|
||||
if (attrHtml) attrHtml = ` ${attrHtml}`;
|
||||
const closingSign = isSelfClosingTag(name) ? '/>' : '>';
|
||||
output.push(`<${name}${attrHtml}${closingSign}`);
|
||||
}
|
||||
},
|
||||
|
||||
ontext: (decodedText: string) => {
|
||||
if (currentTag().name === 'style') {
|
||||
// For CSS, we have to put the style as-is inside the tag because if we html-entities encode
|
||||
// it, it's not going to work. But it's ok because JavaScript won't run within the style tag.
|
||||
// Ideally CSS should be loaded from an external file.
|
||||
output.push(decodedText);
|
||||
} else {
|
||||
output.push(htmlentities(decodedText));
|
||||
}
|
||||
},
|
||||
|
||||
onclosetag: (name: string) => {
|
||||
const current = currentTag();
|
||||
|
||||
if (current.name === name.toLowerCase()) tagStack.pop();
|
||||
|
||||
if (isSelfClosingTag(name)) return;
|
||||
output.push(`</${name}>`);
|
||||
},
|
||||
|
||||
}, { decodeEntities: true });
|
||||
|
||||
parser.write(inputHtml);
|
||||
parser.end();
|
||||
|
||||
await fs.writeFile(outputFile, output.join(''), 'utf8');
|
||||
}
|
||||
14
packages/htmlpack/tsconfig.json
Normal file
14
packages/htmlpack/tsconfig.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist"
|
||||
},
|
||||
"rootDir": ".",
|
||||
"include": [
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules",
|
||||
],
|
||||
}
|
||||
@@ -790,6 +790,7 @@ export default class BaseApplication {
|
||||
Setting.setValue('sync.interval', 3600);
|
||||
}
|
||||
|
||||
Setting.setValue('sync.target', 0);
|
||||
Setting.setValue('firstStart', 0);
|
||||
} else {
|
||||
setLocale(Setting.value('locale'));
|
||||
|
||||
@@ -301,28 +301,38 @@ interface NoteResourceRecognition {
|
||||
}
|
||||
|
||||
const preProcessFile = async (filePath: string): Promise<string> => {
|
||||
const content: string = await shim.fsDriver().readFile(filePath, 'utf8');
|
||||
// Disabled pre-processing for now because it runs out of memory:
|
||||
// https://github.com/laurent22/joplin/issues/5543
|
||||
//
|
||||
// It could be fixed by not loading the whole file in memory, but there are
|
||||
// other issues because people import 1GB+ files so pre-processing
|
||||
// everything means creating a new copy of that file, and that has its own
|
||||
// problems.
|
||||
|
||||
// The note content in an ENEX file is wrapped in a CDATA block so it means
|
||||
// that any "]]>" inside the note must be somehow escaped, or else the CDATA
|
||||
// block would be closed at the wrong point.
|
||||
//
|
||||
// The problem is that Evernote appears to encode "]]>" as "]]<![CDATA[>]]>"
|
||||
// instead of the more sensible "]]>", or perhaps they have nothing in
|
||||
// place to properly escape data imported from their web clipper. In any
|
||||
// case it results in invalid XML that Evernote cannot even import back.
|
||||
//
|
||||
// Handling that invalid XML with SAX would also be very tricky, so instead
|
||||
// we add a pre-processing step that converts this tags to just ">". It
|
||||
// should be safe to do so because such content can only be within the body
|
||||
// of a note - and ">" or ">" is equivalent.
|
||||
//
|
||||
// Ref: https://discourse.joplinapp.org/t/20470/4
|
||||
const newContent = content.replace(/<!\[CDATA\[>\]\]>/g, '>');
|
||||
if (content === newContent) return filePath;
|
||||
const newFilePath = `${Setting.value('tempDir')}/${md5(Date.now() + Math.random())}.enex`;
|
||||
await shim.fsDriver().writeFile(newFilePath, newContent, 'utf8');
|
||||
return newFilePath;
|
||||
return filePath;
|
||||
|
||||
// const content: string = await shim.fsDriver().readFile(filePath, 'utf8');
|
||||
|
||||
// // The note content in an ENEX file is wrapped in a CDATA block so it means
|
||||
// // that any "]]>" inside the note must be somehow escaped, or else the CDATA
|
||||
// // block would be closed at the wrong point.
|
||||
// //
|
||||
// // The problem is that Evernote appears to encode "]]>" as "]]<![CDATA[>]]>"
|
||||
// // instead of the more sensible "]]>", or perhaps they have nothing in
|
||||
// // place to properly escape data imported from their web clipper. In any
|
||||
// // case it results in invalid XML that Evernote cannot even import back.
|
||||
// //
|
||||
// // Handling that invalid XML with SAX would also be very tricky, so instead
|
||||
// // we add a pre-processing step that converts this tags to just ">". It
|
||||
// // should be safe to do so because such content can only be within the body
|
||||
// // of a note - and ">" or ">" is equivalent.
|
||||
// //
|
||||
// // Ref: https://discourse.joplinapp.org/t/20470/4
|
||||
// const newContent = content.replace(/<!\[CDATA\[>\]\]>/g, '>');
|
||||
// if (content === newContent) return filePath;
|
||||
// const newFilePath = `${Setting.value('tempDir')}/${md5(Date.now() + Math.random())}.enex`;
|
||||
// await shim.fsDriver().writeFile(newFilePath, newContent, 'utf8');
|
||||
// return newFilePath;
|
||||
};
|
||||
|
||||
export default async function importEnex(parentFolderId: string, filePath: string, importOptions: ImportOptions = null) {
|
||||
|
||||
@@ -2,7 +2,7 @@ const { setupDatabaseAndSynchronizer, switchClient } = require('../testing/test-
|
||||
const Folder = require('../models/Folder').default;
|
||||
const Note = require('../models/Note').default;
|
||||
|
||||
describe('models_BaseItem', function() {
|
||||
describe('models/BaseItem', function() {
|
||||
|
||||
beforeEach(async (done) => {
|
||||
await setupDatabaseAndSynchronizer(1);
|
||||
|
||||
@@ -9,7 +9,7 @@ import ResourceService from '../services/ResourceService';
|
||||
|
||||
const testImagePath = `${supportDir}/photo.jpg`;
|
||||
|
||||
describe('models_Folder.sharing', function() {
|
||||
describe('models/Folder.sharing', function() {
|
||||
|
||||
beforeEach(async (done) => {
|
||||
await setupDatabaseAndSynchronizer(1);
|
||||
|
||||
@@ -9,7 +9,7 @@ async function allItems() {
|
||||
return folders.concat(notes);
|
||||
}
|
||||
|
||||
describe('models_Folder', function() {
|
||||
describe('models/Folder', function() {
|
||||
|
||||
beforeEach(async (done) => {
|
||||
await setupDatabaseAndSynchronizer(1);
|
||||
|
||||
@@ -15,7 +15,7 @@ async function allItems() {
|
||||
return folders.concat(notes);
|
||||
}
|
||||
|
||||
describe('models_Note', function() {
|
||||
describe('models/Note', function() {
|
||||
beforeEach(async (done) => {
|
||||
await setupDatabaseAndSynchronizer(1);
|
||||
await switchClient(1);
|
||||
|
||||
@@ -3,7 +3,7 @@ const { setupDatabaseAndSynchronizer, switchClient } = require('../testing/test-
|
||||
const Folder = require('../models/Folder').default;
|
||||
const Note = require('../models/Note').default;
|
||||
|
||||
describe('models_Note_CustomSortOrder', function() {
|
||||
describe('models/Note_CustomSortOrder', function() {
|
||||
beforeEach(async (done) => {
|
||||
await setupDatabaseAndSynchronizer(1);
|
||||
await switchClient(1);
|
||||
|
||||
@@ -6,7 +6,7 @@ const shim = require('../shim').default;
|
||||
|
||||
const testImagePath = `${supportDir}/photo.jpg`;
|
||||
|
||||
describe('models_Resource', function() {
|
||||
describe('models/Resource', function() {
|
||||
|
||||
beforeEach(async (done) => {
|
||||
await setupDatabaseAndSynchronizer(1);
|
||||
|
||||
@@ -7,7 +7,7 @@ async function loadSettingsFromFile(): Promise<any> {
|
||||
return JSON.parse(await fs.readFile(Setting.settingFilePath, 'utf8'));
|
||||
}
|
||||
|
||||
describe('models_Setting', function() {
|
||||
describe('models/Setting', function() {
|
||||
|
||||
beforeEach(async (done) => {
|
||||
await setupDatabaseAndSynchronizer(1);
|
||||
@@ -174,7 +174,7 @@ describe('models_Setting', function() {
|
||||
}));
|
||||
|
||||
it('should not save to file if nothing has changed', (async () => {
|
||||
Setting.setValue('sync.target', 9);
|
||||
Setting.setValue('sync.mobileWifiOnly', true);
|
||||
await Setting.saveAll();
|
||||
|
||||
{
|
||||
@@ -182,7 +182,7 @@ describe('models_Setting', function() {
|
||||
// changed.
|
||||
const beforeStat = await fs.stat(Setting.settingFilePath);
|
||||
await msleep(1001);
|
||||
Setting.setValue('sync.target', 8);
|
||||
Setting.setValue('sync.mobileWifiOnly', false);
|
||||
await Setting.saveAll();
|
||||
const afterStat = await fs.stat(Setting.settingFilePath);
|
||||
expect(afterStat.mtime.getTime()).toBeGreaterThan(beforeStat.mtime.getTime());
|
||||
@@ -191,7 +191,7 @@ describe('models_Setting', function() {
|
||||
{
|
||||
const beforeStat = await fs.stat(Setting.settingFilePath);
|
||||
await msleep(1001);
|
||||
Setting.setValue('sync.target', 8);
|
||||
Setting.setValue('sync.mobileWifiOnly', false);
|
||||
const afterStat = await fs.stat(Setting.settingFilePath);
|
||||
await Setting.saveAll();
|
||||
expect(afterStat.mtime.getTime()).toBe(beforeStat.mtime.getTime());
|
||||
|
||||
@@ -319,7 +319,7 @@ class Setting extends BaseModel {
|
||||
},
|
||||
|
||||
'sync.target': {
|
||||
value: 0,
|
||||
value: 7, // Dropbox
|
||||
type: SettingItemType.Int,
|
||||
isEnum: true,
|
||||
public: true,
|
||||
|
||||
@@ -3,7 +3,7 @@ const Folder = require('../models/Folder').default;
|
||||
const Note = require('../models/Note').default;
|
||||
const Tag = require('../models/Tag').default;
|
||||
|
||||
describe('models_Tag', function() {
|
||||
describe('models/Tag', function() {
|
||||
|
||||
beforeEach(async (done) => {
|
||||
await setupDatabaseAndSynchronizer(1);
|
||||
|
||||
2
packages/lib/package-lock.json
generated
2
packages/lib/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/lib",
|
||||
"version": "2.4.1",
|
||||
"version": "2.4.3",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/lib",
|
||||
"version": "2.4.1",
|
||||
"version": "2.4.3",
|
||||
"description": "Joplin Core library",
|
||||
"author": "Laurent Cozic",
|
||||
"homepage": "",
|
||||
@@ -26,11 +26,11 @@
|
||||
"typescript": "^4.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@joplin/fork-htmlparser2": "^4.1.34",
|
||||
"@joplin/fork-sax": "^1.2.38",
|
||||
"@joplin/renderer": "^2.4.1",
|
||||
"@joplin/turndown": "^4.0.56",
|
||||
"@joplin/turndown-plugin-gfm": "^1.0.38",
|
||||
"@joplin/fork-htmlparser2": "^4.1.36",
|
||||
"@joplin/fork-sax": "^1.2.40",
|
||||
"@joplin/renderer": "^2.4.3",
|
||||
"@joplin/turndown": "^4.0.58",
|
||||
"@joplin/turndown-plugin-gfm": "^1.0.40",
|
||||
"async-mutex": "^0.1.3",
|
||||
"aws-sdk": "^2.588.0",
|
||||
"base-64": "^0.1.0",
|
||||
@@ -85,5 +85,5 @@
|
||||
"word-wrap": "^1.2.3",
|
||||
"xml2js": "^0.4.19"
|
||||
},
|
||||
"gitHead": "80c0089d2c52aff608b2bea74389de5a7f12f2e2"
|
||||
"gitHead": "eb4b0e64eab40a51b0895d3a40a9d8c3cb7b1b14"
|
||||
}
|
||||
|
||||
@@ -127,6 +127,7 @@ export default class InteropService_Exporter_Html extends InteropService_Exporte
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
${assetsToHeaders(result.pluginAssets, { asHtml: true })}
|
||||
<title>${escapeHtml(item.title)}</title>
|
||||
</head>
|
||||
|
||||
@@ -200,6 +200,13 @@ export default class ShareService {
|
||||
return this.api().exec('GET', 'api/share_users');
|
||||
}
|
||||
|
||||
public setProcessingShareInvitationResponse(v: boolean) {
|
||||
this.store.dispatch({
|
||||
type: 'SHARE_INVITATION_RESPONSE_PROCESSING',
|
||||
value: v,
|
||||
});
|
||||
}
|
||||
|
||||
public async respondInvitation(shareUserId: string, accept: boolean) {
|
||||
if (accept) {
|
||||
await this.api().exec('PATCH', `api/share_users/${shareUserId}`, null, { status: 1 });
|
||||
|
||||
@@ -38,6 +38,7 @@ export interface State {
|
||||
shares: StateShare[];
|
||||
shareUsers: Record<string, StateShareUser>;
|
||||
shareInvitations: ShareInvitation[];
|
||||
processingShareInvitationResponse: boolean;
|
||||
}
|
||||
|
||||
export const stateRootKey = 'shareService';
|
||||
@@ -46,6 +47,7 @@ export const defaultState: State = {
|
||||
shares: [],
|
||||
shareUsers: {},
|
||||
shareInvitations: [],
|
||||
processingShareInvitationResponse: false,
|
||||
};
|
||||
|
||||
export function isSharedFolderOwner(state: RootState, folderId: string): boolean {
|
||||
@@ -82,6 +84,11 @@ const reducer = (draftRoot: Draft<RootState>, action: any) => {
|
||||
draft.shareInvitations = action.shareInvitations;
|
||||
break;
|
||||
|
||||
case 'SHARE_INVITATION_RESPONSE_PROCESSING':
|
||||
|
||||
draft.processingShareInvitationResponse = action.value;
|
||||
break;
|
||||
|
||||
}
|
||||
} catch (error) {
|
||||
error.message = `In share reducer: ${error.message} Action: ${JSON.stringify(action)}`;
|
||||
|
||||
2
packages/plugin-repo-cli/package-lock.json
generated
2
packages/plugin-repo-cli/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/plugin-repo-cli",
|
||||
"version": "2.4.1",
|
||||
"version": "2.4.3",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/plugin-repo-cli",
|
||||
"version": "2.4.1",
|
||||
"version": "2.4.3",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"bin": {
|
||||
@@ -19,8 +19,8 @@
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@joplin/lib": "^2.4.1",
|
||||
"@joplin/tools": "^2.4.1",
|
||||
"@joplin/lib": "^2.4.3",
|
||||
"@joplin/tools": "^2.4.3",
|
||||
"fs-extra": "^9.0.1",
|
||||
"gh-release-assets": "^2.0.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
@@ -32,5 +32,6 @@
|
||||
"@types/node": "^14.14.6",
|
||||
"jest": "^26.6.3",
|
||||
"typescript": "^4.1.3"
|
||||
}
|
||||
},
|
||||
"gitHead": "eb4b0e64eab40a51b0895d3a40a9d8c3cb7b1b14"
|
||||
}
|
||||
|
||||
2
packages/renderer/package-lock.json
generated
2
packages/renderer/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/renderer",
|
||||
"version": "2.4.1",
|
||||
"version": "2.4.3",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/renderer",
|
||||
"version": "2.4.1",
|
||||
"version": "2.4.3",
|
||||
"description": "The Joplin note renderer, used the mobile and desktop application",
|
||||
"repository": "https://github.com/laurent22/joplin/tree/dev/packages/renderer",
|
||||
"main": "index.js",
|
||||
@@ -24,7 +24,7 @@
|
||||
"typescript": "^4.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@joplin/fork-htmlparser2": "^4.1.34",
|
||||
"@joplin/fork-htmlparser2": "^4.1.36",
|
||||
"font-awesome-filetypes": "^2.1.0",
|
||||
"fs-extra": "^8.1.0",
|
||||
"highlight.js": "^11.2.0",
|
||||
@@ -48,5 +48,5 @@
|
||||
"mermaid": "^8.12.1",
|
||||
"uslug": "git+https://github.com/laurent22/uslug.git#emoji-support"
|
||||
},
|
||||
"gitHead": "80c0089d2c52aff608b2bea74389de5a7f12f2e2"
|
||||
"gitHead": "eb4b0e64eab40a51b0895d3a40a9d8c3cb7b1b14"
|
||||
}
|
||||
|
||||
4
packages/server/package-lock.json
generated
4
packages/server/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@joplin/server",
|
||||
"version": "2.4.9",
|
||||
"version": "2.4.11",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@joplin/server",
|
||||
"version": "2.4.9",
|
||||
"version": "2.4.11",
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^5.15.1",
|
||||
"@koa/cors": "^3.1.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/server",
|
||||
"version": "2.4.9",
|
||||
"version": "2.4.11",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start-dev": "nodemon --config nodemon.json --ext ts,js,mustache,css,tsx dist/app.js --env dev",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Item, Share, ShareType, ShareUser, ShareUserStatus, User, Uuid } from '../services/database/types';
|
||||
import { ErrorForbidden, ErrorNotFound } from '../utils/errors';
|
||||
import { ErrorBadRequest, ErrorForbidden, ErrorNotFound } from '../utils/errors';
|
||||
import BaseModel, { AclAction, DeleteOptions } from './BaseModel';
|
||||
import { getCanShareFolder } from './utils/user';
|
||||
|
||||
@@ -117,6 +117,8 @@ export default class ShareUserModel extends BaseModel<ShareUser> {
|
||||
const shareUser = await this.byShareAndUserId(shareId, userId);
|
||||
if (!shareUser) throw new ErrorNotFound(`Item has not been shared with this user: ${shareId} / ${userId}`);
|
||||
|
||||
if (shareUser.status === status) throw new ErrorBadRequest(`Share ${shareId} status is already ${status}`);
|
||||
|
||||
const share = await this.models().share().load(shareId);
|
||||
if (!share) throw new ErrorNotFound(`No such share: ${shareId}`);
|
||||
|
||||
|
||||
@@ -28,13 +28,6 @@ export default class UserItemModel extends BaseModel<UserItem> {
|
||||
return false;
|
||||
}
|
||||
|
||||
public async add(userId: Uuid, itemId: Uuid): Promise<UserItem> {
|
||||
return this.save({
|
||||
user_id: userId,
|
||||
item_id: itemId,
|
||||
});
|
||||
}
|
||||
|
||||
public async remove(userId: Uuid, itemId: Uuid): Promise<void> {
|
||||
await this.deleteByUserItem(userId, itemId);
|
||||
}
|
||||
@@ -59,7 +52,6 @@ export default class UserItemModel extends BaseModel<UserItem> {
|
||||
.leftJoin('items', 'user_items.item_id', 'items.id')
|
||||
.select(this.selectFields(options, this.defaultFields, 'user_items'))
|
||||
.where('items.jop_share_id', '=', shareId);
|
||||
// return this.db(this.tableName).select(this.defaultFields).where('share_id', '=', shareId);
|
||||
}
|
||||
|
||||
public async byShareAndUserId(shareId: Uuid, userId: Uuid, options: LoadOptions = {}): Promise<UserItem[]> {
|
||||
@@ -69,10 +61,6 @@ export default class UserItemModel extends BaseModel<UserItem> {
|
||||
.select(this.selectFields(options, this.defaultFields, 'user_items'))
|
||||
.where('items.jop_share_id', '=', shareId)
|
||||
.where('user_items.user_id', '=', userId);
|
||||
|
||||
// return this.db(this.tableName).select(this.defaultFields)
|
||||
// .where('share_id', '=', shareId)
|
||||
// .where('user_id', '=', userId);
|
||||
}
|
||||
|
||||
public async byUserId(userId: Uuid): Promise<UserItem[]> {
|
||||
@@ -91,7 +79,6 @@ export default class UserItemModel extends BaseModel<UserItem> {
|
||||
.select(this.selectFields(options, this.defaultFields, 'user_items'))
|
||||
.where('items.jop_share_id', '!=', '')
|
||||
.where('user_items.user_id', '=', userId);
|
||||
// return this.db(this.tableName).select(this.defaultFields).where('share_id', '!=', '').where('user_id', '=', userId);
|
||||
}
|
||||
|
||||
public async deleteByUserItem(userId: Uuid, itemId: Uuid): Promise<void> {
|
||||
@@ -124,6 +111,11 @@ export default class UserItemModel extends BaseModel<UserItem> {
|
||||
await this.deleteBy({ byShareId: shareId, byUserId: userId });
|
||||
}
|
||||
|
||||
public async add(userId: Uuid, itemId: Uuid, options: SaveOptions = {}): Promise<void> {
|
||||
const item = await this.models().item().load(itemId, { fields: ['id', 'name'] });
|
||||
await this.addMulti(userId, [item], options);
|
||||
}
|
||||
|
||||
public async addMulti(userId: Uuid, itemsQuery: Knex.QueryBuilder | Item[], options: SaveOptions = {}): Promise<void> {
|
||||
const items: Item[] = Array.isArray(itemsQuery) ? itemsQuery : await itemsQuery.whereNotIn('id', this.db('user_items').select('item_id').where('user_id', '=', userId));
|
||||
if (!items.length) return;
|
||||
@@ -151,11 +143,8 @@ export default class UserItemModel extends BaseModel<UserItem> {
|
||||
}, 'UserItemModel::addMulti');
|
||||
}
|
||||
|
||||
public async save(userItem: UserItem, options: SaveOptions = {}): Promise<UserItem> {
|
||||
if (userItem.id) throw new Error('User items cannot be modified (only created or deleted)'); // Sanity check - shouldn't happen
|
||||
const item = await this.models().item().load(userItem.item_id, { fields: ['id', 'name'] });
|
||||
await this.addMulti(userItem.user_id, [item], options);
|
||||
return this.byUserAndItemId(userItem.user_id, item.id);
|
||||
public async save(_userItem: UserItem, _options: SaveOptions = {}): Promise<UserItem> {
|
||||
throw new Error('Call add() or addMulti()');
|
||||
}
|
||||
|
||||
public async delete(_id: string | string[], _options: DeleteOptions = {}): Promise<void> {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { ShareType, ShareUserStatus } from '../../services/database/types';
|
||||
import { beforeAllDb, afterAllTests, beforeEachDb, createUserAndSession, models, createItemTree, expectHttpError } from '../../utils/testing/testUtils';
|
||||
import { getApi, patchApi } from '../../utils/testing/apiUtils';
|
||||
import { shareWithUserAndAccept } from '../../utils/testing/shareApiUtils';
|
||||
import { ErrorForbidden } from '../../utils/errors';
|
||||
import { shareFolderWithUser, shareWithUserAndAccept } from '../../utils/testing/shareApiUtils';
|
||||
import { ErrorBadRequest, ErrorForbidden } from '../../utils/errors';
|
||||
import { PaginatedResults } from '../../models/utils/pagination';
|
||||
|
||||
describe('share_users', function() {
|
||||
@@ -53,4 +53,17 @@ describe('share_users', function() {
|
||||
await expectHttpError(async () => patchApi(session1.id, `share_users/${shareUser.id}`, { status: ShareUserStatus.Accepted }), ErrorForbidden.httpCode);
|
||||
});
|
||||
|
||||
test('should not allow accepting a share twice or more', async function() {
|
||||
const { session: session1 } = await createUserAndSession(1);
|
||||
const { session: session2 } = await createUserAndSession(2);
|
||||
|
||||
const { shareUser } = await shareFolderWithUser(session1.id, session2.id, '000000000000000000000000000000F1', {
|
||||
'000000000000000000000000000000F1': {
|
||||
'00000000000000000000000000000001': null,
|
||||
},
|
||||
});
|
||||
|
||||
await expectHttpError(async () => patchApi(session2.id, `share_users/${shareUser.id}`, { status: ShareUserStatus.Accepted }), ErrorBadRequest.httpCode);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -86,6 +86,8 @@ export const postHandlers: PostHandlers = {
|
||||
};
|
||||
|
||||
if (fields.coupon) {
|
||||
delete checkoutSession.allow_promotion_codes;
|
||||
|
||||
checkoutSession.discounts = [
|
||||
{
|
||||
coupon: fields.coupon.trim(),
|
||||
|
||||
@@ -1118,7 +1118,7 @@ msgstr "请升级 Joplin 以使用此插件"
|
||||
msgid ""
|
||||
"The Joplin team has vetted this plugin and it meets our standards for "
|
||||
"security and performance."
|
||||
msgstr ""
|
||||
msgstr "Joplin 团队已经通过了该插件的审查,它符合我们对于安全和性能的要求。"
|
||||
|
||||
#: packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginBox.js:192
|
||||
#, javascript-format
|
||||
@@ -1144,9 +1144,8 @@ msgid "You do not have any installed plugin."
|
||||
msgstr "您尚未安装任何插件。"
|
||||
|
||||
#: packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginsStates.js:232
|
||||
#, fuzzy
|
||||
msgid "Could not connect to plugin repository."
|
||||
msgstr "无法连接到插件库"
|
||||
msgstr "无法连接到插件库。"
|
||||
|
||||
#: packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginsStates.js:236
|
||||
msgid "Try again"
|
||||
@@ -1395,9 +1394,8 @@ msgstr "加密状态:"
|
||||
|
||||
#: packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.js:103
|
||||
#: packages/app-mobile/components/screens/encryption-config.js:89
|
||||
#, fuzzy
|
||||
msgid "Master password"
|
||||
msgstr "输入主密码:"
|
||||
msgstr "主密码"
|
||||
|
||||
#: packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.js:118
|
||||
msgid "Source: "
|
||||
@@ -1442,20 +1440,17 @@ msgstr "动作"
|
||||
|
||||
#: packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.js:166
|
||||
#: packages/app-mobile/components/screens/encryption-config.js:159
|
||||
#, fuzzy
|
||||
msgid "Master password:"
|
||||
msgstr "输入主密码:"
|
||||
msgstr "主密码:"
|
||||
|
||||
#: packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.js:170
|
||||
#: packages/app-mobile/components/screens/encryption-config.js:160
|
||||
#, fuzzy
|
||||
msgid "Loaded"
|
||||
msgstr "已下载"
|
||||
msgstr "已加载"
|
||||
|
||||
#: packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.js:178
|
||||
#, fuzzy
|
||||
msgid "Enter your master password"
|
||||
msgstr "输入主密码:"
|
||||
msgstr "请输入主密码"
|
||||
|
||||
#: packages/app-desktop/gui/ExtensionBadge.min.js:10
|
||||
msgid "Firefox Extension"
|
||||
@@ -4224,7 +4219,7 @@ msgid "attachment"
|
||||
msgstr "附件"
|
||||
|
||||
#: packages/server/dist/models/UserModel.js:199
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Cannot save %s \"%s\" because it is larger than the allowed limit (%s)"
|
||||
msgstr "无法保存 %s “%s”,因为超过了允许的限制大小(%s)。"
|
||||
|
||||
|
||||
2
packages/tools/package-lock.json
generated
2
packages/tools/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/tools",
|
||||
"version": "2.4.1",
|
||||
"version": "2.4.3",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/tools",
|
||||
"version": "2.4.1",
|
||||
"version": "2.4.3",
|
||||
"description": "Various tools for Joplin",
|
||||
"main": "index.js",
|
||||
"author": "Laurent Cozic",
|
||||
@@ -20,8 +20,8 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@joplin/lib": "^2.4.1",
|
||||
"@joplin/renderer": "^2.4.1",
|
||||
"@joplin/lib": "^2.4.3",
|
||||
"@joplin/renderer": "^2.4.3",
|
||||
"execa": "^4.1.0",
|
||||
"fs-extra": "^4.0.3",
|
||||
"gettext-parser": "^1.3.0",
|
||||
@@ -41,14 +41,14 @@
|
||||
"devDependencies": {
|
||||
"@rmp135/sql-ts": "^1.6.0",
|
||||
"@types/fs-extra": "^9.0.6",
|
||||
"@types/jest": "^26.0.15",
|
||||
"@types/mustache": "^0.8.32",
|
||||
"@types/node": "^14.14.6",
|
||||
"@types/jest": "^26.0.15",
|
||||
"jest": "^26.6.3",
|
||||
"gulp": "^4.0.2",
|
||||
"jest": "^26.6.3",
|
||||
"sass": "^1.39.2",
|
||||
"sqlite3": "^5.0.0",
|
||||
"typescript": "^4.1.3"
|
||||
},
|
||||
"gitHead": "80c0089d2c52aff608b2bea74389de5a7f12f2e2"
|
||||
"gitHead": "eb4b0e64eab40a51b0895d3a40a9d8c3cb7b1b14"
|
||||
}
|
||||
|
||||
2
packages/turndown-plugin-gfm/package-lock.json
generated
2
packages/turndown-plugin-gfm/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/turndown-plugin-gfm",
|
||||
"version": "1.0.38",
|
||||
"version": "1.0.40",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"version": "1.0.38",
|
||||
"version": "1.0.40",
|
||||
"author": "Dom Christie",
|
||||
"main": "lib/turndown-plugin-gfm.cjs.js",
|
||||
"devDependencies": {
|
||||
@@ -41,5 +41,5 @@
|
||||
"build-test": "browserify test/turndown-plugin-gfm-test.js --outfile test/turndown-plugin-gfm-test.browser.js",
|
||||
"prepare": "npm run build"
|
||||
},
|
||||
"gitHead": "80c0089d2c52aff608b2bea74389de5a7f12f2e2"
|
||||
"gitHead": "eb4b0e64eab40a51b0895d3a40a9d8c3cb7b1b14"
|
||||
}
|
||||
|
||||
2
packages/turndown/package-lock.json
generated
2
packages/turndown/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/turndown",
|
||||
"version": "4.0.56",
|
||||
"version": "4.0.58",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@joplin/turndown",
|
||||
"description": "A library that converts HTML to Markdown",
|
||||
"version": "4.0.56",
|
||||
"version": "4.0.58",
|
||||
"author": "Dom Christie",
|
||||
"main": "lib/turndown.cjs.js",
|
||||
"publishConfig": {
|
||||
@@ -48,5 +48,5 @@
|
||||
"build-test": "browserify test/turndown-test.js --outfile test/turndown-test.browser.js",
|
||||
"prepare": "npm run build"
|
||||
},
|
||||
"gitHead": "80c0089d2c52aff608b2bea74389de5a7f12f2e2"
|
||||
"gitHead": "eb4b0e64eab40a51b0895d3a40a9d8c3cb7b1b14"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# Joplin Android app changelog
|
||||
|
||||
## [android-v2.4.3](https://github.com/laurent22/joplin/releases/tag/android-v2.4.3) - 2021-09-29T18:47:24Z
|
||||
|
||||
- Fixed: Fix default sync target (4b39d30)
|
||||
|
||||
## [android-v2.4.2](https://github.com/laurent22/joplin/releases/tag/android-v2.4.2) (Pre-release) - 2021-09-22T17:02:37Z
|
||||
|
||||
- Improved: Allow disabling any master key, including default or active one (9407efd)
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# Joplin terminal app changelog
|
||||
|
||||
## [cli-v2.4.1](https://github.com/laurent22/joplin/releases/tag/cli-v2.4.1) - 2021-09-29T15:28:01Z
|
||||
|
||||
- New: Add a way to disable a master key (7faa58e)
|
||||
- New: Add support for single master password, to simplify handling of multiple encryption keys (ce89ee5)
|
||||
- New: Added "None" sync target to allow disabling synchronisation (f5f05e6)
|
||||
- Improved: Allow importing certain corrupted ENEX files (f144dae)
|
||||
- Improved: Improved sync locks so that they do not prevent upgrading a sync target (06ed58b)
|
||||
- Fixed: Fixed file paths when exporting as HTML (#5325)
|
||||
- Fixed: Misinterpreted search term after filter in quotation marks (#5445) (#5444 by [@JackGruber](https://github.com/JackGruber))
|
||||
- Fixed: Setting note contents using "set" command does not update note timestamp (#5435)
|
||||
|
||||
## [cli-v2.3.2](https://github.com/laurent22/joplin/releases/tag/cli-v2.3.2) - 2021-08-16T09:38:40Z
|
||||
|
||||
- Improved: Improved E2EE usability by making its state a property of the sync target (#5276)
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# Joplin Server Changelog
|
||||
|
||||
## [server-v2.4.11-beta](https://github.com/laurent22/joplin/releases/tag/server-v2.4.11-beta) - 2021-09-26T17:10:57Z
|
||||
|
||||
- Improved: Do not allow accepting share more than once (57a1d03)
|
||||
- Fixed: Fixed Stripe checkout when a coupon is used (c45f961)
|
||||
|
||||
## [server-v2.4.10-beta](https://github.com/laurent22/joplin/releases/tag/server-v2.4.10-beta) (Pre-release) - 2021-09-25T19:07:05Z
|
||||
|
||||
- Improved: Improved share service reliability and optimised performance (0175348)
|
||||
- Security: Implement clickjacking defense (e3fd34e)
|
||||
|
||||
## [server-v2.4.9](https://github.com/laurent22/joplin/releases/tag/server-v2.4.9-beta) - 2021-09-22T16:31:23Z
|
||||
|
||||
- New: Add support for changing user own email (63e88c0)
|
||||
|
||||
Reference in New Issue
Block a user