You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-08-30 20:39:46 +02:00
Compare commits
19 Commits
remove-pdf
...
test-binar
Author | SHA1 | Date | |
---|---|---|---|
|
376de4ccbd | ||
|
ed58ed91fd | ||
|
a0fd942a1c | ||
|
0b3919fd62 | ||
|
897fd0f727 | ||
|
9edb402b18 | ||
|
36ae58ffe1 | ||
|
5ef8b86957 | ||
|
c7228cfcd6 | ||
|
7a791dbf98 | ||
|
a543588527 | ||
|
998ad142a6 | ||
|
b6a53f96f7 | ||
|
841a9c6e09 | ||
|
d25c078ef0 | ||
|
ff69ac17be | ||
|
b44945b3a0 | ||
|
2584224026 | ||
|
46136871bf |
@@ -396,7 +396,6 @@ packages/app-mobile/components/NoteEditor/NoteEditor.js
|
||||
packages/app-mobile/components/NoteEditor/SearchPanel.js
|
||||
packages/app-mobile/components/NoteEditor/SelectionFormatting.js
|
||||
packages/app-mobile/components/NoteEditor/types.js
|
||||
packages/app-mobile/components/NoteList.js
|
||||
packages/app-mobile/components/ProfileSwitcher/ProfileEditor.js
|
||||
packages/app-mobile/components/ProfileSwitcher/ProfileSwitcher.js
|
||||
packages/app-mobile/components/ProfileSwitcher/useProfileConfig.js
|
||||
@@ -712,7 +711,6 @@ packages/lib/services/searchengine/SearchFilter.test.js
|
||||
packages/lib/services/searchengine/filterParser.js
|
||||
packages/lib/services/searchengine/filterParser.test.js
|
||||
packages/lib/services/searchengine/gotoAnythingStyleQuery.js
|
||||
packages/lib/services/searchengine/gotoAnythingStyleQuery.test.js
|
||||
packages/lib/services/searchengine/queryBuilder.js
|
||||
packages/lib/services/share/ShareService.js
|
||||
packages/lib/services/share/ShareService.test.js
|
||||
@@ -874,8 +872,6 @@ packages/tools/website/updateDownloadPage.js
|
||||
packages/tools/website/updateNews.js
|
||||
packages/tools/website/utils/applyTranslations.js
|
||||
packages/tools/website/utils/applyTranslations.test.js
|
||||
packages/tools/website/utils/convertLinksToLocale.js
|
||||
packages/tools/website/utils/convertLinksToLocale.test.js
|
||||
packages/tools/website/utils/frontMatter.js
|
||||
packages/tools/website/utils/news.js
|
||||
packages/tools/website/utils/openGraph.js
|
||||
|
3
.github/scripts/run_ci.sh
vendored
3
.github/scripts/run_ci.sh
vendored
@@ -180,9 +180,6 @@ cd "$ROOT_DIR/packages/app-desktop"
|
||||
|
||||
if [[ $GIT_TAG_NAME = v* ]]; then
|
||||
echo "Step: Building and publishing desktop application..."
|
||||
# cd "$ROOT_DIR/packages/tools"
|
||||
# node bundleDefaultPlugins.js
|
||||
cd "$ROOT_DIR/packages/app-desktop"
|
||||
USE_HARD_LINKS=false yarn run dist
|
||||
elif [[ $IS_LINUX = 1 ]] && [[ $GIT_TAG_NAME = $SERVER_TAG_PREFIX-* ]]; then
|
||||
echo "Step: Building Docker Image..."
|
||||
|
4
.github/workflows/github-actions-main.yml
vendored
4
.github/workflows/github-actions-main.yml
vendored
@@ -71,9 +71,7 @@ jobs:
|
||||
- uses: olegtarasov/get-tag@v2.1
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
# We need to pin the version to 18.15, because 18.16+ fails with this error:
|
||||
# https://github.com/facebook/react-native/issues/36440
|
||||
node-version: '18.15.0'
|
||||
node-version: '18'
|
||||
|
||||
- name: Install Yarn
|
||||
run: |
|
||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@@ -383,7 +383,6 @@ packages/app-mobile/components/NoteEditor/NoteEditor.js
|
||||
packages/app-mobile/components/NoteEditor/SearchPanel.js
|
||||
packages/app-mobile/components/NoteEditor/SelectionFormatting.js
|
||||
packages/app-mobile/components/NoteEditor/types.js
|
||||
packages/app-mobile/components/NoteList.js
|
||||
packages/app-mobile/components/ProfileSwitcher/ProfileEditor.js
|
||||
packages/app-mobile/components/ProfileSwitcher/ProfileSwitcher.js
|
||||
packages/app-mobile/components/ProfileSwitcher/useProfileConfig.js
|
||||
@@ -699,7 +698,6 @@ packages/lib/services/searchengine/SearchFilter.test.js
|
||||
packages/lib/services/searchengine/filterParser.js
|
||||
packages/lib/services/searchengine/filterParser.test.js
|
||||
packages/lib/services/searchengine/gotoAnythingStyleQuery.js
|
||||
packages/lib/services/searchengine/gotoAnythingStyleQuery.test.js
|
||||
packages/lib/services/searchengine/queryBuilder.js
|
||||
packages/lib/services/share/ShareService.js
|
||||
packages/lib/services/share/ShareService.test.js
|
||||
@@ -861,8 +859,6 @@ packages/tools/website/updateDownloadPage.js
|
||||
packages/tools/website/updateNews.js
|
||||
packages/tools/website/utils/applyTranslations.js
|
||||
packages/tools/website/utils/applyTranslations.test.js
|
||||
packages/tools/website/utils/convertLinksToLocale.js
|
||||
packages/tools/website/utils/convertLinksToLocale.test.js
|
||||
packages/tools/website/utils/frontMatter.js
|
||||
packages/tools/website/utils/news.js
|
||||
packages/tools/website/utils/openGraph.js
|
||||
|
@@ -1,30 +0,0 @@
|
||||
diff --git a/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java b/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java
|
||||
index a8abd71833879201e3438b2fa51d712a311c4551..ffe9c2c6dfa5c703ba76b65d94d5dd6784102c19 100644
|
||||
--- a/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java
|
||||
+++ b/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java
|
||||
@@ -591,7 +591,7 @@ public class RNFetchBlobReq extends BroadcastReceiver implements Runnable {
|
||||
// ignored.printStackTrace();
|
||||
}
|
||||
|
||||
- RNFetchBlobFileResp rnFetchBlobFileResp = (RNFetchBlobFileResp) responseBody;
|
||||
+ RNFetchBlobFileResp rnFetchBlobFileResp = new RNFetchBlobFileResp(responseBody);
|
||||
|
||||
if(rnFetchBlobFileResp != null && !rnFetchBlobFileResp.isDownloadComplete()){
|
||||
callback.invoke("Download interrupted.", null);
|
||||
diff --git a/android/src/main/java/com/RNFetchBlob/Response/RNFetchBlobFileResp.java b/android/src/main/java/com/RNFetchBlob/Response/RNFetchBlobFileResp.java
|
||||
index 2470eef612308c15a89dfea5a1f16937469be29f..965f8becc195965907699182c764ec9e51811450 100644
|
||||
--- a/android/src/main/java/com/RNFetchBlob/Response/RNFetchBlobFileResp.java
|
||||
+++ b/android/src/main/java/com/RNFetchBlob/Response/RNFetchBlobFileResp.java
|
||||
@@ -35,6 +35,12 @@ public class RNFetchBlobFileResp extends ResponseBody {
|
||||
FileOutputStream ofStream;
|
||||
boolean isEndMarkerReceived;
|
||||
|
||||
+ // ref: https://github.com/joltup/rn-fetch-blob/issues/490#issuecomment-990899440
|
||||
+ public RNFetchBlobFileResp(ResponseBody body) {
|
||||
+ super();
|
||||
+ this.originalBody = body;
|
||||
+ }
|
||||
+
|
||||
public RNFetchBlobFileResp(ReactApplicationContext ctx, String taskId, ResponseBody body, String path, boolean overwrite) throws IOException {
|
||||
super();
|
||||
this.rctContext = ctx;
|
@@ -657,16 +657,6 @@ footer .bottom-links-row p {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.language-switcher {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.language-switcher > button {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
color: #0557ba;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
WHAT'S NEW PAGE
|
||||
*****************************************************************/
|
||||
|
File diff suppressed because one or more lines are too long
5016
Assets/WebsiteAssets/js/bootstrap5.0.2.js
vendored
Normal file
5016
Assets/WebsiteAssets/js/bootstrap5.0.2.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
7
Assets/WebsiteAssets/js/bootstrap5.0.2.min.js
vendored
Normal file
7
Assets/WebsiteAssets/js/bootstrap5.0.2.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -421,7 +421,7 @@
|
||||
</div>
|
||||
|
||||
<script
|
||||
src="{{jsBaseUrl}}/bootstrap5.0.2.bundle.min.js"
|
||||
src="{{jsBaseUrl}}/bootstrap5.0.2.min.js"
|
||||
rel="preload"
|
||||
as="script"
|
||||
></script>
|
||||
|
@@ -85,11 +85,6 @@ https://github.com/laurent22/joplin/blob/dev/{{{sourceMarkdownFile}}}
|
||||
{{> footer}}
|
||||
</div>
|
||||
|
||||
<script
|
||||
src="{{jsBaseUrl}}/bootstrap5.0.2.bundle.min.js"
|
||||
rel="preload"
|
||||
as="script"
|
||||
></script>
|
||||
<script src="{{{assetUrls.js.script}}}"></script>
|
||||
|
||||
{{> analytics}}
|
||||
|
@@ -17,21 +17,6 @@
|
||||
<a href="{{baseUrl}}/help/" class="fw500">Help</a>
|
||||
<a href="{{forumUrl}}" class="fw500">Forum</a>
|
||||
<a href="{{baseUrl}}/cn/" class="fw500">中文</a>
|
||||
|
||||
<!--
|
||||
<div class="dropdown language-switcher">
|
||||
<button class="fw500" type="button" id="dropdownMenuButton1" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Language
|
||||
</button>
|
||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton1">
|
||||
<li><a class="dropdown-item" href="#">Action</a></li>
|
||||
<li><a class="dropdown-item" href="#">Another action</a></li>
|
||||
<li><a class="dropdown-item" href="#">Something else here</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
-->
|
||||
|
||||
|
||||
{{#showJoplinCloudLinks}}
|
||||
{{> joplinCloudButton}}
|
||||
{{/showJoplinCloudLinks}}
|
||||
|
7
bootstrap.bundle.min.js
vendored
7
bootstrap.bundle.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -95,7 +95,6 @@
|
||||
},
|
||||
"packageManager": "yarn@3.3.1",
|
||||
"resolutions": {
|
||||
"react-native-camera@4.2.1": "patch:react-native-camera@npm%3A4.2.1#./.yarn/patches/react-native-camera-npm-4.2.1-24b2600a7e.patch",
|
||||
"rn-fetch-blob@0.12.0": "patch:rn-fetch-blob@npm%3A0.12.0#./.yarn/patches/rn-fetch-blob-npm-0.12.0-cf02e3c544.patch"
|
||||
"react-native-camera@4.2.1": "patch:react-native-camera@npm%3A4.2.1#./.yarn/patches/react-native-camera-npm-4.2.1-24b2600a7e.patch"
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
sz_program=${SZA_PATH:-7za}
|
||||
sz_type=${SZA_ARCHIVE_TYPE:-xz}
|
||||
|
||||
case $1 in
|
||||
-d) "$sz_program" e -si -so -t${sz_type} ;;
|
||||
*) "$sz_program" a f -si -so -t${sz_type} -mx${SZA_COMPRESSION_LEVEL:-9} ;;
|
||||
esac 2> /dev/null
|
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Vladimir Krivosheev
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
@@ -0,0 +1 @@
|
||||
7-Zip precompiled binaries.
|
2
packages/app-desktop/build/defaultPlugins/io.github.jackgruber.backup/7zip-bin/index.d.ts
vendored
Normal file
2
packages/app-desktop/build/defaultPlugins/io.github.jackgruber.backup/7zip-bin/index.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export const path7za: string
|
||||
export const path7x: string
|
@@ -0,0 +1,22 @@
|
||||
"use strict"
|
||||
|
||||
const path = require("path")
|
||||
|
||||
function getPath() {
|
||||
if (process.env.USE_SYSTEM_7ZA === "true") {
|
||||
return "7za"
|
||||
}
|
||||
|
||||
if (process.platform === "darwin") {
|
||||
return path.join(__dirname, "mac", process.arch, "7za")
|
||||
}
|
||||
else if (process.platform === "win32") {
|
||||
return path.join(__dirname, "win", process.arch, "7za.exe")
|
||||
}
|
||||
else {
|
||||
return path.join(__dirname, "linux", process.arch, "7za")
|
||||
}
|
||||
}
|
||||
|
||||
exports.path7za = getPath()
|
||||
exports.path7x = path.join(__dirname, "7x.sh")
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
BASEDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
rm -rf /tmp/7z-linux
|
||||
mkdir /tmp/7z-linux
|
||||
cp "$BASEDIR/do-build.sh" /tmp/7z-linux/do-build.sh
|
||||
docker run --rm -v /tmp/7z-linux:/project buildpack-deps:xenial /project/do-build.sh
|
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
apt-get update -qq
|
||||
apt-get upgrade -qq
|
||||
|
||||
echo "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-5.0 main" > /etc/apt/sources.list.d/llvm.list
|
||||
curl -L http://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
|
||||
apt-get update -qq
|
||||
apt-get install -qq bzip2 yasm clang-5.0 lldb-5.0 lld-5.0
|
||||
|
||||
ln -s /usr/bin/clang-5.0 /usr/bin/clang
|
||||
ln -s /usr/bin/clang++-5.0 /usr/bin/clang++
|
||||
|
||||
mkdir -p /tmp/7z
|
||||
cd /tmp/7z
|
||||
curl -L http://downloads.sourceforge.net/project/p7zip/p7zip/16.02/p7zip_16.02_src_all.tar.bz2 | tar -xj -C . --strip-components 1
|
||||
cp makefile.linux_clang_amd64_asm makefile.machine
|
||||
make -j4
|
||||
mv bin/7za /project/7za
|
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "7zip-bin",
|
||||
"description": "7-Zip precompiled binaries",
|
||||
"version": "5.1.1",
|
||||
"files": [
|
||||
"*.js",
|
||||
"7x.sh",
|
||||
"index.d.ts",
|
||||
"linux",
|
||||
"mac",
|
||||
"win"
|
||||
],
|
||||
"license": "MIT",
|
||||
"repository": "develar/7zip-bin",
|
||||
"keywords": [
|
||||
"7zip",
|
||||
"7z",
|
||||
"7za"
|
||||
]
|
||||
}
|
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"manifest_version": 1,
|
||||
"id": "io.github.jackgruber.backup",
|
||||
"app_min_version": "2.1.3",
|
||||
"version": "1.1.1",
|
||||
"name": "Simple Backup",
|
||||
"description": "Plugin to create manual and automatic backups.",
|
||||
"author": "JackGruber",
|
||||
"homepage_url": "https://github.com/JackGruber/joplin-plugin-backup/blob/master/README.md",
|
||||
"repository_url": "https://github.com/JackGruber/joplin-plugin-backup",
|
||||
"keywords": ["backup", "jex", "export", "zip", "7zip", "encrypted"]
|
||||
}
|
@@ -0,0 +1,15 @@
|
||||
#joplin-plugin-content {
|
||||
width: fit-content;
|
||||
background-color: var(--joplin-background-color);
|
||||
color: var(--joplin-color);
|
||||
}
|
||||
|
||||
#backuperror {
|
||||
width: fit-content;
|
||||
display: block;
|
||||
flex-direction: column;
|
||||
min-width: 300px;
|
||||
overflow-wrap: break-word;
|
||||
font-size: var(--joplin-font-size);
|
||||
font-family: var(--joplin-font-family);
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"manifest_version": 1,
|
||||
"id": "plugin.calebjohn.rich-markdown",
|
||||
"app_min_version": "2.4",
|
||||
"version": "0.8.3",
|
||||
"name": "Rich Markdown",
|
||||
"description": "Helping you ditch the markdown viewer for good.",
|
||||
"author": "Caleb John",
|
||||
"homepage_url": "https://github.com/CalebJohn/joplin-rich-markdown#readme",
|
||||
"repository_url": "https://github.com/CalebJohn/joplin-rich-markdown",
|
||||
"keywords": [
|
||||
"editor",
|
||||
"visual"
|
||||
],
|
||||
"_publish_hash": "sha256:7059ff05f3fcac2ead5b8f4cb04ec66830be55e02407408a39ab20e536055f5d",
|
||||
"_publish_commit": "main:9816b21068ce09014e8ef8adb0bd31bc20343247"
|
||||
}
|
Binary file not shown.
@@ -641,8 +641,8 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
|
||||
resourceInfos: props.resourceInfos,
|
||||
contentMaxWidth: props.contentMaxWidth,
|
||||
mapsToLine: true,
|
||||
// turning off custom pdf viewer; ref: https://github.com/laurent22/joplin/issues/8028
|
||||
useCustomPdfViewer: false,
|
||||
// Always using useCustomPdfViewer for now, we can add a new setting for it in future if we need to.
|
||||
useCustomPdfViewer: props.useCustomPdfViewer,
|
||||
noteId: props.noteId,
|
||||
vendorDir: bridge().vendorDir(),
|
||||
}));
|
||||
|
@@ -7,8 +7,6 @@ import { ContextMenuItemType, ContextMenuOptions } from './NoteEditor/utils/cont
|
||||
import CommandService from '@joplin/lib/services/CommandService';
|
||||
import styled from 'styled-components';
|
||||
import { themeStyle } from '@joplin/lib/theme';
|
||||
const Entities = require('html-entities').AllHtmlEntities;
|
||||
const htmlentities = new Entities().encode;
|
||||
|
||||
const Window = styled.div`
|
||||
height: 100%;
|
||||
@@ -21,6 +19,12 @@ const Window = styled.div`
|
||||
color: ${(props: any) => props.theme.color};
|
||||
`;
|
||||
|
||||
const IFrame = styled.iframe`
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border: none;
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
themeId: number;
|
||||
dispatch: Function;
|
||||
@@ -89,12 +93,13 @@ export default function PdfViewer(props: Props) {
|
||||
|
||||
const theme = themeStyle(props.themeId);
|
||||
|
||||
const escapedResourcePath = htmlentities(Resource.fullPath(props.resource));
|
||||
const escapedMime = htmlentities('application/pdf');
|
||||
|
||||
return (
|
||||
<Window theme={theme}>
|
||||
<object data={escapedResourcePath} className="media-player media-pdf" type={escapedMime}></object>;
|
||||
<IFrame src="./vendor/lib/@joplin/pdf-viewer/index.html" x-url={Resource.fullPath(props.resource)}
|
||||
x-appearance={theme.appearance} ref={iframeRef}
|
||||
x-title={props.resource.title}
|
||||
x-anchorpage={props.pageNo}
|
||||
x-type="full"></IFrame>
|
||||
</Window>
|
||||
);
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dist": "yarn run electronRebuild && npx electron-builder",
|
||||
"bundleDefaultPlugins": "cd ../tools && node bundleDefaultPlugins.js",
|
||||
"build": "gulp build",
|
||||
"postinstall": "yarn run build",
|
||||
"electronBuilder": "gulp electronBuilder",
|
||||
@@ -27,7 +28,6 @@
|
||||
},
|
||||
"build": {
|
||||
"appId": "net.cozic.joplin-desktop",
|
||||
"compression": "maximum",
|
||||
"productName": "Joplin",
|
||||
"npmRebuild": false,
|
||||
"afterSign": "./tools/notarizeMacApp.js",
|
||||
@@ -91,7 +91,11 @@
|
||||
"CFBundleURLName": "org.joplinapp.x-callback-url"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"binaries": [
|
||||
"Contents/Resources/build/defaultPlugins/io.github.jackgruber.backup/7zip-bin/mac/arm64/7za",
|
||||
"Contents/Resources/build/defaultPlugins/io.github.jackgruber.backup/7zip-bin/mac/x64/7za"
|
||||
]
|
||||
},
|
||||
"linux": {
|
||||
"icon": "../../Assets/LinuxIcons",
|
||||
@@ -108,6 +112,8 @@
|
||||
},
|
||||
"homepage": "https://github.com/laurent22/joplin#readme",
|
||||
"devDependencies": {
|
||||
"@electron/notarize": "1.2.3",
|
||||
"@electron/rebuild": "3.2.10",
|
||||
"@joplin/tools": "~2.11",
|
||||
"@testing-library/react-hooks": "8.0.1",
|
||||
"@types/jest": "29.2.6",
|
||||
@@ -116,9 +122,7 @@
|
||||
"@types/react-redux": "7.1.25",
|
||||
"@types/styled-components": "5.1.26",
|
||||
"electron": "19.1.4",
|
||||
"electron-builder": "23.6.0",
|
||||
"electron-notarize": "1.2.2",
|
||||
"electron-rebuild": "3.2.9",
|
||||
"electron-builder": "24.1.2",
|
||||
"glob": "8.1.0",
|
||||
"gulp": "4.0.2",
|
||||
"jest": "29.4.3",
|
||||
@@ -138,6 +142,7 @@
|
||||
"@fortawesome/fontawesome-free": "5.15.4",
|
||||
"@joeattardi/emoji-button": "4.6.4",
|
||||
"@joplin/lib": "~2.11",
|
||||
"@joplin/pdf-viewer": "~2.11",
|
||||
"@joplin/renderer": "~2.11",
|
||||
"async-mutex": "0.4.0",
|
||||
"codemirror": "5.65.9",
|
||||
@@ -149,7 +154,6 @@
|
||||
"formatcoords": "1.1.3",
|
||||
"fs-extra": "11.1.1",
|
||||
"highlight.js": "11.7.0",
|
||||
"html-entities": "1.4.0",
|
||||
"immer": "7.0.15",
|
||||
"keytar": "7.9.0",
|
||||
"mark.js": "8.11.1",
|
||||
@@ -177,4 +181,4 @@
|
||||
"taboverride": "4.0.3",
|
||||
"tinymce": "5.10.6"
|
||||
}
|
||||
}
|
||||
}
|
@@ -72,6 +72,10 @@ async function main() {
|
||||
src: langSourceDir,
|
||||
dest: `${buildLibDir}/tinymce/langs`,
|
||||
},
|
||||
{
|
||||
src: resolve(__dirname, '../../pdf-viewer/dist'),
|
||||
dest: `${buildLibDir}/@joplin/pdf-viewer`,
|
||||
},
|
||||
];
|
||||
|
||||
const files = [
|
||||
@@ -89,6 +93,10 @@ async function main() {
|
||||
src: resolve(__dirname, '../../lib/services/plugins/sandboxProxy.js'),
|
||||
dest: `${buildLibDir}/@joplin/lib/services/plugins/sandboxProxy.js`,
|
||||
},
|
||||
{
|
||||
src: resolve(__dirname, '../../pdf-viewer/index.html'),
|
||||
dest: `${buildLibDir}/@joplin/pdf-viewer/index.html`,
|
||||
},
|
||||
];
|
||||
|
||||
// First we delete all the destination directories, then we copy the files.
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const electron_notarize = require('electron-notarize');
|
||||
const electron_notarize = require('@electron/notarize');
|
||||
const execCommand = require('./execCommand');
|
||||
|
||||
function isDesktopAppTag(tagName) {
|
||||
|
@@ -1,32 +1,15 @@
|
||||
const React = require('react');
|
||||
|
||||
import { Component } from 'react';
|
||||
|
||||
import { connect } from 'react-redux';
|
||||
import { FlatList, Text, StyleSheet, Button, View } from 'react-native';
|
||||
import { FolderEntity, NoteEntity } from '@joplin/lib/services/database/types';
|
||||
import { AppState } from '../utils/types';
|
||||
|
||||
const Component = React.Component;
|
||||
const { connect } = require('react-redux');
|
||||
const { FlatList, Text, StyleSheet, Button, View } = require('react-native');
|
||||
const { _ } = require('@joplin/lib/locale');
|
||||
const { NoteItem } = require('./note-item.js');
|
||||
const time = require('@joplin/lib/time').default;
|
||||
const { themeStyle } = require('./global-style.js');
|
||||
|
||||
interface NoteListProps {
|
||||
themeId: string;
|
||||
dispatch: (action: any)=> void;
|
||||
notesSource: string;
|
||||
items: NoteEntity[];
|
||||
folders: FolderEntity[];
|
||||
noteSelectionEnabled?: boolean;
|
||||
selectedFolderId?: string;
|
||||
}
|
||||
|
||||
class NoteListComponent extends Component<NoteListProps> {
|
||||
private rootRef_: FlatList;
|
||||
private styles_: Record<string, StyleSheet.NamedStyles<any>>;
|
||||
|
||||
public constructor(props: NoteListProps) {
|
||||
super(props);
|
||||
class NoteListComponent extends Component {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.state = {
|
||||
items: [],
|
||||
@@ -38,7 +21,7 @@ class NoteListComponent extends Component<NoteListProps> {
|
||||
this.createNotebookButton_click = this.createNotebookButton_click.bind(this);
|
||||
}
|
||||
|
||||
private styles() {
|
||||
styles() {
|
||||
const themeId = this.props.themeId;
|
||||
const theme = themeStyle(themeId);
|
||||
|
||||
@@ -64,7 +47,7 @@ class NoteListComponent extends Component<NoteListProps> {
|
||||
return this.styles_[themeId];
|
||||
}
|
||||
|
||||
private createNotebookButton_click() {
|
||||
createNotebookButton_click() {
|
||||
this.props.dispatch({
|
||||
type: 'NAV_GO',
|
||||
routeName: 'Folder',
|
||||
@@ -72,14 +55,34 @@ class NoteListComponent extends Component<NoteListProps> {
|
||||
});
|
||||
}
|
||||
|
||||
public UNSAFE_componentWillReceiveProps(newProps: NoteListProps) {
|
||||
filterNotes(notes) {
|
||||
const todoFilter = 'all'; // Setting.value('todoFilter');
|
||||
if (todoFilter === 'all') return notes;
|
||||
|
||||
const now = time.unixMs();
|
||||
const maxInterval = 1000 * 60 * 60 * 24;
|
||||
const notRecentTime = now - maxInterval;
|
||||
|
||||
const output = [];
|
||||
for (let i = 0; i < notes.length; i++) {
|
||||
const note = notes[i];
|
||||
if (note.is_todo) {
|
||||
if (todoFilter === 'recent' && note.user_updated_time < notRecentTime && !!note.todo_completed) continue;
|
||||
if (todoFilter === 'nonCompleted' && !!note.todo_completed) continue;
|
||||
}
|
||||
output.push(note);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
UNSAFE_componentWillReceiveProps(newProps) {
|
||||
// Make sure scroll position is reset when switching from one folder to another or to a tag list.
|
||||
if (this.rootRef_ && newProps.notesSource !== this.props.notesSource) {
|
||||
this.rootRef_.scrollToOffset({ offset: 0, animated: false });
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
render() {
|
||||
// `enableEmptySections` is to fix this warning: https://github.com/FaridSafi/react-native-gifted-listview/issues/39
|
||||
|
||||
if (this.props.items.length) {
|
||||
@@ -106,7 +109,7 @@ class NoteListComponent extends Component<NoteListProps> {
|
||||
}
|
||||
}
|
||||
|
||||
const NoteList = connect((state: AppState) => {
|
||||
const NoteList = connect(state => {
|
||||
return {
|
||||
items: state.notes,
|
||||
folders: state.folders,
|
||||
@@ -116,4 +119,4 @@ const NoteList = connect((state: AppState) => {
|
||||
};
|
||||
})(NoteListComponent);
|
||||
|
||||
export default NoteList;
|
||||
module.exports = { NoteList };
|
@@ -2,7 +2,7 @@ const React = require('react');
|
||||
import { AppState as RNAppState, View, StyleSheet, NativeEventSubscription } from 'react-native';
|
||||
import { stateUtils } from '@joplin/lib/reducer';
|
||||
import { connect } from 'react-redux';
|
||||
import NoteList from '../NoteList';
|
||||
const { NoteList } = require('../note-list.js');
|
||||
import Folder from '@joplin/lib/models/Folder';
|
||||
import Tag from '@joplin/lib/models/Tag';
|
||||
import Note from '@joplin/lib/models/Note';
|
||||
@@ -254,7 +254,7 @@ class NotesScreenComponent extends BaseScreenComponent<any> {
|
||||
return (
|
||||
<View style={rootStyle}>
|
||||
<ScreenHeader title={iconString + title} showBackButton={false} parentComponent={thisComp} sortButton_press={this.sortButton_press} folderPickerOptions={this.folderPickerOptions()} showSearchButton={true} showSideMenuButton={true} />
|
||||
<NoteList />
|
||||
<NoteList style={this.styles().noteList} />
|
||||
{actionButtonComp}
|
||||
<DialogBox
|
||||
ref={(dialogbox: any) => {
|
||||
|
@@ -54,7 +54,7 @@
|
||||
"react-native-image-picker": "5.3.1",
|
||||
"react-native-image-resizer": "1.4.5",
|
||||
"react-native-modal-datetime-picker": "14.0.1",
|
||||
"react-native-paper": "5.5.2",
|
||||
"react-native-paper": "5.5.0",
|
||||
"react-native-popup-menu": "0.16.1",
|
||||
"react-native-quick-actions": "0.3.13",
|
||||
"react-native-rsa-native": "2.0.5",
|
||||
|
@@ -1395,7 +1395,7 @@ class Setting extends BaseModel {
|
||||
useCustomPdfViewer: {
|
||||
value: false,
|
||||
type: SettingItemType.Bool,
|
||||
public: false,
|
||||
public: true,
|
||||
advanced: true,
|
||||
appTypes: [AppType.Desktop],
|
||||
label: () => 'Use custom PDF viewer (Beta)',
|
||||
|
@@ -431,7 +431,6 @@ describe('services_SearchEngine', () => {
|
||||
['title:abcd efgh', { _: ['efgh'], title: ['abcd'] }],
|
||||
['title:abcd', { title: ['abcd'] }],
|
||||
['"abcd efgh"', { _: ['abcd efgh'] }],
|
||||
['"abcd efgh" ijkl', { _: ['abcd efgh', 'ijkl'] }],
|
||||
['title:abcd title:efgh', { title: ['abcd', 'efgh'] }],
|
||||
];
|
||||
|
||||
|
@@ -5,31 +5,20 @@ import Note from '../../models/Note';
|
||||
import BaseModel from '../../BaseModel';
|
||||
import ItemChangeUtils from '../ItemChangeUtils';
|
||||
import shim from '../../shim';
|
||||
import filterParser, { Term } from './filterParser';
|
||||
import filterParser from './filterParser';
|
||||
import queryBuilder from './queryBuilder';
|
||||
import { ItemChangeEntity, NoteEntity } from '../database/types';
|
||||
const { sprintf } = require('sprintf-js');
|
||||
const { pregQuote, scriptType, removeDiacritics } = require('../../string-utils.js');
|
||||
|
||||
enum SearchType {
|
||||
Auto = 'auto',
|
||||
Basic = 'basic',
|
||||
Nonlatin = 'nonlatin',
|
||||
Fts = 'fts',
|
||||
}
|
||||
|
||||
interface SearchOptions {
|
||||
searchType: SearchType;
|
||||
}
|
||||
|
||||
export default class SearchEngine {
|
||||
|
||||
public static instance_: SearchEngine = null;
|
||||
public static relevantFields = 'id, title, body, user_created_time, user_updated_time, is_todo, todo_completed, todo_due, parent_id, latitude, longitude, altitude, source_url';
|
||||
public static SEARCH_TYPE_AUTO = SearchType.Auto;
|
||||
public static SEARCH_TYPE_BASIC = SearchType.Basic;
|
||||
public static SEARCH_TYPE_NONLATIN_SCRIPT = SearchType.Nonlatin;
|
||||
public static SEARCH_TYPE_FTS = SearchType.Fts;
|
||||
public static SEARCH_TYPE_AUTO = 'auto';
|
||||
public static SEARCH_TYPE_BASIC = 'basic';
|
||||
public static SEARCH_TYPE_NONLATIN_SCRIPT = 'nonlatin';
|
||||
public static SEARCH_TYPE_FTS = 'fts';
|
||||
|
||||
public dispatch: Function = (_o: any) => {};
|
||||
private logger_ = new Logger();
|
||||
@@ -428,7 +417,7 @@ export default class SearchEngine {
|
||||
|
||||
const trimQuotes = (str: string) => str.startsWith('"') ? str.substr(1, str.length - 2) : str;
|
||||
|
||||
let allTerms: Term[] = [];
|
||||
let allTerms: any[] = [];
|
||||
|
||||
try {
|
||||
allTerms = filterParser(query);
|
||||
@@ -440,20 +429,7 @@ export default class SearchEngine {
|
||||
const titleTerms = allTerms.filter(x => x.name === 'title' && !x.negated).map(x => trimQuotes(x.value));
|
||||
const bodyTerms = allTerms.filter(x => x.name === 'body' && !x.negated).map(x => trimQuotes(x.value));
|
||||
|
||||
interface ComplexTerm {
|
||||
type: 'regex' | 'text';
|
||||
value: string;
|
||||
scriptType: any;
|
||||
valueRegex?: RegExp;
|
||||
}
|
||||
|
||||
interface Terms {
|
||||
_: (string | ComplexTerm)[];
|
||||
title: (string | ComplexTerm)[];
|
||||
body: (string | ComplexTerm)[];
|
||||
}
|
||||
|
||||
const terms: Terms = { _: textTerms, 'title': titleTerms, 'body': bodyTerms };
|
||||
const terms: any = { _: textTerms, 'title': titleTerms, 'body': bodyTerms };
|
||||
|
||||
// Filter terms:
|
||||
// - Convert wildcards to regex
|
||||
@@ -462,9 +438,7 @@ export default class SearchEngine {
|
||||
|
||||
let termCount = 0;
|
||||
const keys = [];
|
||||
for (const col2 in terms) {
|
||||
const col = col2 as '_' | 'title' | 'body';
|
||||
|
||||
for (const col in terms) {
|
||||
if (!terms.hasOwnProperty(col)) continue;
|
||||
|
||||
if (!terms[col].length) {
|
||||
@@ -473,7 +447,7 @@ export default class SearchEngine {
|
||||
}
|
||||
|
||||
for (let i = terms[col].length - 1; i >= 0; i--) {
|
||||
const term = terms[col][i] as string;
|
||||
const term = terms[col][i];
|
||||
|
||||
// SQlLite FTS doesn't allow "*" queries and neither shall we
|
||||
if (term === '*') {
|
||||
@@ -494,16 +468,12 @@ export default class SearchEngine {
|
||||
}
|
||||
|
||||
//
|
||||
// The object "allTerms" is used for query construction purposes (this
|
||||
// contains all the filter terms) Since this is used for the FTS match
|
||||
// query, we need to normalize text, title and body terms. Note, we're
|
||||
// not normalizing terms like tag because these are matched using SQL
|
||||
// LIKE operator and so we must preserve their diacritics.
|
||||
// The object "allTerms" is used for query construction purposes (this contains all the filter terms)
|
||||
// Since this is used for the FTS match query, we need to normalize text, title and body terms.
|
||||
// Note, we're not normalizing terms like tag because these are matched using SQL LIKE operator and so we must preserve their diacritics.
|
||||
//
|
||||
// The object "terms" only include text, title, body terms and is used
|
||||
// for highlighting. By not normalizing the text, title, body in
|
||||
// "terms", highlighting still works correctly for words with
|
||||
// diacritics.
|
||||
// The object "terms" only include text, title, body terms and is used for highlighting.
|
||||
// By not normalizing the text, title, body in "terms", highlighting still works correctly for words with diacritics.
|
||||
//
|
||||
|
||||
allTerms = allTerms.map(x => {
|
||||
@@ -551,9 +521,9 @@ export default class SearchEngine {
|
||||
const searchOptions: any = {};
|
||||
|
||||
for (const key of parsedQuery.keys) {
|
||||
if ((parsedQuery.terms as any)[key].length === 0) continue;
|
||||
if (parsedQuery.terms[key].length === 0) continue;
|
||||
|
||||
const term = (parsedQuery.terms as any)[key].map((x: Term) => x.value).join(' ');
|
||||
const term = parsedQuery.terms[key].map((x: any) => x.value).join(' ');
|
||||
if (key === '_') searchOptions.anywherePattern = `*${term}*`;
|
||||
if (key === 'title') searchOptions.titlePattern = `*${term}*`;
|
||||
if (key === 'body') searchOptions.bodyPattern = `*${term}*`;
|
||||
@@ -591,13 +561,12 @@ export default class SearchEngine {
|
||||
return SearchEngine.SEARCH_TYPE_FTS;
|
||||
}
|
||||
|
||||
public async search(searchString: string, options: SearchOptions = null) {
|
||||
public async search(searchString: string, options: any = null) {
|
||||
if (!searchString) return [];
|
||||
|
||||
options = {
|
||||
options = Object.assign({}, {
|
||||
searchType: SearchEngine.SEARCH_TYPE_AUTO,
|
||||
...options,
|
||||
};
|
||||
}, options);
|
||||
|
||||
const searchType = this.determineSearchType_(searchString, options.searchType);
|
||||
const parsedQuery = await this.parseQuery(searchString);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
|
||||
export interface Term {
|
||||
interface Term {
|
||||
name: string;
|
||||
value: string;
|
||||
negated: boolean;
|
||||
|
@@ -1,17 +0,0 @@
|
||||
import gotoAnythingStyleQuery from './gotoAnythingStyleQuery';
|
||||
|
||||
describe('searchengine/gotoAnythingStyleQuery', () => {
|
||||
|
||||
it('should prepare queries', () => {
|
||||
const testCases: [string, string][] = [
|
||||
['hello', 'hello*'],
|
||||
['hello welc', 'hello* welc*'],
|
||||
];
|
||||
|
||||
for (const [input, expected] of testCases) {
|
||||
const actual = gotoAnythingStyleQuery(input);
|
||||
expect(actual).toBe(expected);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
@@ -19,7 +19,7 @@ function resourceUrl(resourceFullPath: string): string {
|
||||
return `file://${toForwardSlashes(resourceFullPath)}`;
|
||||
}
|
||||
|
||||
export default function(link: Link, options: Options, _linkIndexes: LinkIndexes) {
|
||||
export default function(link: Link, options: Options, linkIndexes: LinkIndexes) {
|
||||
const resource = link.resource;
|
||||
|
||||
if (!link.resourceReady || !resource || !resource.mime) return '';
|
||||
@@ -47,6 +47,32 @@ export default function(link: Link, options: Options, _linkIndexes: LinkIndexes)
|
||||
}
|
||||
|
||||
if (options.pdfViewerEnabled && resource.mime === 'application/pdf') {
|
||||
|
||||
if (options.useCustomPdfViewer) {
|
||||
const resourceId = resource.id;
|
||||
let anchorPageNo = null;
|
||||
|
||||
let id = `${options.noteId}.${resourceId}`;
|
||||
if (linkIndexes && linkIndexes[resourceId]) {
|
||||
linkIndexes[resourceId]++;
|
||||
} else {
|
||||
linkIndexes[resourceId] = 1;
|
||||
}
|
||||
id += `.${linkIndexes[resourceId]}`;
|
||||
|
||||
if (link.href.indexOf('#') > 0) {
|
||||
anchorPageNo = Number(link.href.split('#').pop());
|
||||
if (anchorPageNo < 1) anchorPageNo = null;
|
||||
}
|
||||
|
||||
const src = `${options.vendorDir}/lib/@joplin/pdf-viewer/index.html`;
|
||||
|
||||
return `<iframe src="${src}" x-url="${escapedResourcePath}"
|
||||
x-appearance="${options.theme.appearance}" ${anchorPageNo ? `x-anchorPage="${anchorPageNo}"` : ''} id="${id}"
|
||||
x-type="mini" x-resourceid="${resourceId}"
|
||||
class="media-player media-pdf"></iframe>`;
|
||||
}
|
||||
|
||||
return `<object data="${escapedResourcePath}" class="media-player media-pdf" type="${escapedMime}"></object>`;
|
||||
}
|
||||
|
||||
|
@@ -41,7 +41,7 @@ async function downloadFile(url: string, outputPath: string) {
|
||||
|
||||
export async function extractPlugins(currentDir: string, defaultPluginDir: string, downloadedPluginsNames: PluginIdAndName): Promise<void> {
|
||||
for (const pluginId of Object.keys(downloadedPluginsNames)) {
|
||||
await execCommand(`tar xzf ${currentDir}/${downloadedPluginsNames[pluginId]}`, { quiet: true });
|
||||
await execCommand(`tar xzf ${currentDir}/${downloadedPluginsNames[pluginId]}`, { quiet: true, splitCommandOptions: { handleEscape: false } });
|
||||
await move(`package/publish/${pluginId}.jpl`, `${defaultPluginDir}/${pluginId}/plugin.jpl`, { overwrite: true });
|
||||
await move(`package/publish/${pluginId}.json`, `${defaultPluginDir}/${pluginId}/manifest.json`, { overwrite: true });
|
||||
await remove(`${downloadedPluginsNames[pluginId]}`);
|
||||
|
@@ -1,20 +1,19 @@
|
||||
import { readFileSync, readFile, mkdirpSync, writeFileSync, remove, copy, pathExistsSync, pathExists } from 'fs-extra';
|
||||
import { readFileSync, readFile, mkdirpSync, writeFileSync, remove, copy, pathExistsSync } from 'fs-extra';
|
||||
import { rootDir } from '../tool-utils';
|
||||
import { pressCarouselItems } from './utils/pressCarousel';
|
||||
import { getMarkdownIt, loadMustachePartials, markdownToPageHtml, renderMustache } from './utils/render';
|
||||
import { AssetUrls, Env, Locale, Partials, PlanPageParams, TemplateParams } from './utils/types';
|
||||
import { AssetUrls, Env, Partials, PlanPageParams, TemplateParams } from './utils/types';
|
||||
import { createFeatureTableMd, getPlans, loadStripeConfig } from '@joplin/lib/utils/joplinCloud';
|
||||
import { stripOffFrontMatter } from './utils/frontMatter';
|
||||
import { dirname, basename } from 'path';
|
||||
import { readmeFileTitle, replaceGitHubByWebsiteLinks } from './utils/parser';
|
||||
import { extractOpenGraphTags, OpenGraphTags } from './utils/openGraph';
|
||||
import { extractOpenGraphTags } from './utils/openGraph';
|
||||
import { readCredentialFileJson } from '@joplin/lib/utils/credentialFiles';
|
||||
import { getNewsDateString } from './utils/news';
|
||||
import { parsePoFile, parseTranslations, Translations } from '../utils/translation';
|
||||
import { setLocale } from '@joplin/lib/locale';
|
||||
import { countryCodeOnly, setLocale } from '@joplin/lib/locale';
|
||||
import applyTranslations from './utils/applyTranslations';
|
||||
import { loadSponsors } from '../utils/loadSponsors';
|
||||
import convertLinksToLocale from './utils/convertLinksToLocale';
|
||||
|
||||
interface BuildConfig {
|
||||
env: Env;
|
||||
@@ -24,12 +23,6 @@ const buildConfig = readCredentialFileJson<BuildConfig>('website-build.json', {
|
||||
env: Env.Prod,
|
||||
});
|
||||
|
||||
const enGbLocale: Locale = {
|
||||
htmlTranslations: {},
|
||||
lang: 'en-gb',
|
||||
pathPrefix: '',
|
||||
};
|
||||
|
||||
const glob = require('glob');
|
||||
const path = require('path');
|
||||
const md5File = require('md5-file');
|
||||
@@ -48,7 +41,7 @@ const partialDir = `${websiteAssetDir}/templates/partials`;
|
||||
const discussLink = 'https://discourse.joplinapp.org/c/news/9';
|
||||
|
||||
let tocMd_: string = null;
|
||||
const tocHtml_: Record<string, string> = {};
|
||||
let tocHtml_: string = null;
|
||||
const tocRegex_ = /<!-- TOC -->([^]*)<!-- TOC -->/;
|
||||
function tocMd() {
|
||||
if (tocMd_) return tocMd_;
|
||||
@@ -68,17 +61,15 @@ async function getDonateLinks() {
|
||||
return `<div class="donate-links">\n\n${matches[1].trim()}\n\n</div>`;
|
||||
}
|
||||
|
||||
function tocHtml(locale: Locale) {
|
||||
if (tocHtml_[locale.lang]) return tocHtml_[locale.lang];
|
||||
function tocHtml() {
|
||||
if (tocHtml_) return tocHtml_;
|
||||
const markdownIt = getMarkdownIt();
|
||||
let md = tocMd();
|
||||
md = md.replace(/# Table of contents/, '');
|
||||
md = replaceGitHubByWebsiteLinks(md);
|
||||
md = convertLinksToLocale(md, locale);
|
||||
let output = markdownIt.render(md);
|
||||
output = `<div>${output}</div>`;
|
||||
tocHtml_[locale.lang] = output;
|
||||
return output;
|
||||
tocHtml_ = markdownIt.render(md);
|
||||
tocHtml_ = `<div>${tocHtml_}</div>`;
|
||||
return tocHtml_;
|
||||
}
|
||||
|
||||
const baseUrl = '';
|
||||
@@ -99,16 +90,14 @@ async function getAssetUrls(): Promise<AssetUrls> {
|
||||
};
|
||||
}
|
||||
|
||||
function defaultTemplateParams(assetUrls: AssetUrls, locale: Locale = null): TemplateParams {
|
||||
if (!locale) locale = enGbLocale;
|
||||
|
||||
function defaultTemplateParams(assetUrls: AssetUrls): TemplateParams {
|
||||
return {
|
||||
env: buildConfig.env,
|
||||
baseUrl,
|
||||
imageBaseUrl: `${baseUrl}/images`,
|
||||
cssBaseUrl,
|
||||
jsBaseUrl,
|
||||
tocHtml: tocHtml(locale),
|
||||
tocHtml: tocHtml(),
|
||||
yyyy: (new Date()).getFullYear().toString(),
|
||||
templateHtml: mainTemplateHtml,
|
||||
forumUrl: 'https://discourse.joplinapp.org/',
|
||||
@@ -120,7 +109,6 @@ function defaultTemplateParams(assetUrls: AssetUrls, locale: Locale = null): Tem
|
||||
},
|
||||
assetUrls,
|
||||
openGraph: null,
|
||||
locale,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -129,7 +117,7 @@ function renderPageToHtml(md: string, targetPath: string, templateParams: Templa
|
||||
md = md.replace(/# Joplin\n/, '');
|
||||
|
||||
templateParams = {
|
||||
...defaultTemplateParams(templateParams.assetUrls, templateParams.locale),
|
||||
...defaultTemplateParams(templateParams.assetUrls),
|
||||
...templateParams,
|
||||
};
|
||||
|
||||
@@ -145,7 +133,6 @@ function renderPageToHtml(md: string, targetPath: string, templateParams: Templa
|
||||
}
|
||||
|
||||
md = replaceGitHubByWebsiteLinks(md);
|
||||
md = convertLinksToLocale(md, templateParams.locale);
|
||||
|
||||
if (templateParams.donateLinksMd) {
|
||||
md = `${templateParams.donateLinksMd}\n\n${md}`;
|
||||
@@ -174,8 +161,8 @@ function renderFileToHtml(sourcePath: string, targetPath: string, templateParams
|
||||
}
|
||||
}
|
||||
|
||||
function makeHomePageMd(readmePath: string) {
|
||||
let md = readFileSync(readmePath, 'utf8');
|
||||
function makeHomePageMd() {
|
||||
let md = readFileSync(`${rootDir}/README.md`, 'utf8');
|
||||
md = md.replace(tocRegex_, '');
|
||||
|
||||
// HACK: GitHub needs the \| or the inline code won't be displayed correctly inside the table,
|
||||
@@ -229,20 +216,15 @@ const updatePageLanguage = (html: string, lang: string): string => {
|
||||
return html.replace('<html lang="en-gb">', `<html lang="${lang}">`);
|
||||
};
|
||||
|
||||
// TODO: Add function that process links and add prefix.
|
||||
|
||||
async function main() {
|
||||
const supportedLocales: Record<string, Locale> = {
|
||||
'en_GB': enGbLocale,
|
||||
const supportedLocales = {
|
||||
'en_GB': {
|
||||
htmlTranslations: {},
|
||||
lang: 'en-gb',
|
||||
},
|
||||
'zh_CN': {
|
||||
htmlTranslations: parseTranslations(await parsePoFile(`${websiteAssetDir}/locales/zh_CN.po`)),
|
||||
lang: 'zh-cn',
|
||||
pathPrefix: 'cn',
|
||||
},
|
||||
'fr_FR': {
|
||||
htmlTranslations: {},
|
||||
lang: 'fr-fr',
|
||||
pathPrefix: 'fr',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -255,53 +237,34 @@ async function main() {
|
||||
const partials = await loadMustachePartials(partialDir);
|
||||
const assetUrls = await getAssetUrls();
|
||||
|
||||
const readmeMd = makeHomePageMd();
|
||||
const donateLinksMd = await getDonateLinks();
|
||||
|
||||
// =============================================================
|
||||
// HELP PAGE
|
||||
// =============================================================
|
||||
|
||||
renderPageToHtml(readmeMd, `${docDir}/help/index.html`, {
|
||||
sourceMarkdownFile: 'README.md',
|
||||
donateLinksMd,
|
||||
partials,
|
||||
sponsors,
|
||||
assetUrls,
|
||||
openGraph: {
|
||||
title: 'Joplin documentation',
|
||||
description: '',
|
||||
url: 'https://joplinapp.org/help/',
|
||||
},
|
||||
});
|
||||
|
||||
// =============================================================
|
||||
// FRONT PAGE
|
||||
// =============================================================
|
||||
|
||||
for (const [localeName, locale] of Object.entries(supportedLocales)) {
|
||||
setLocale(localeName);
|
||||
|
||||
const pathPrefix = localeName !== 'en_GB' ? `/${locale.pathPrefix}` : '';
|
||||
|
||||
// =============================================================
|
||||
// HELP PAGE
|
||||
// =============================================================
|
||||
|
||||
let readmePath = `${rootDir}/README.md`;
|
||||
|
||||
let sourceMarkdownFile = 'README.md';
|
||||
let targetDocDir = docDir;
|
||||
|
||||
if (localeName !== 'en_GB') {
|
||||
const possibleSource = `${rootDir}/readme/_i18n/${localeName}/README.md`;
|
||||
if (await pathExists(possibleSource)) {
|
||||
sourceMarkdownFile = possibleSource;
|
||||
readmePath = possibleSource;
|
||||
} else {
|
||||
console.warn(`Cannot find source file: ${possibleSource}`);
|
||||
}
|
||||
|
||||
targetDocDir = `${docDir}/${locale.pathPrefix}`;
|
||||
}
|
||||
|
||||
const readmeMd = makeHomePageMd(readmePath);
|
||||
|
||||
renderPageToHtml(readmeMd, `${targetDocDir}/help/index.html`, {
|
||||
sourceMarkdownFile,
|
||||
donateLinksMd,
|
||||
partials,
|
||||
sponsors,
|
||||
assetUrls,
|
||||
openGraph: {
|
||||
title: 'Joplin documentation',
|
||||
description: '',
|
||||
url: 'https://joplinapp.org/help/',
|
||||
},
|
||||
locale,
|
||||
});
|
||||
|
||||
// =============================================================
|
||||
// FRONT PAGE
|
||||
// =============================================================
|
||||
const pathPrefix = localeName !== 'en_GB' ? `/${countryCodeOnly(localeName).toLowerCase()}` : '';
|
||||
|
||||
let templateHtml = updatePageLanguage(applyTranslations(frontTemplateHtml, localeName, locale.htmlTranslations), locale.lang);
|
||||
if (localeName === 'zh_CN') templateHtml = templateHtml.replace(/\/plans/g, '/cn/plans');
|
||||
@@ -329,16 +292,22 @@ async function main() {
|
||||
url: 'https://joplinapp.org',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// =============================================================
|
||||
// PLANS PAGE
|
||||
// =============================================================
|
||||
setLocale('en_GB');
|
||||
|
||||
// =============================================================
|
||||
// PLANS PAGE
|
||||
// =============================================================
|
||||
|
||||
for (const [localeName, locale] of Object.entries(supportedLocales)) {
|
||||
setLocale(localeName);
|
||||
|
||||
const planPageFaqMd = await readFile(`${readmeDir}/faq_joplin_cloud.md`, 'utf8');
|
||||
const planPageFaqHtml = getMarkdownIt().render(planPageFaqMd, {});
|
||||
|
||||
const planPageParams: PlanPageParams = {
|
||||
...defaultTemplateParams(assetUrls, locale),
|
||||
...defaultTemplateParams(assetUrls),
|
||||
partials: translatePartials(partials, localeName, locale.htmlTranslations),
|
||||
templateHtml: applyTranslations(plansTemplateHtml, localeName, locale.htmlTranslations),
|
||||
plans: getPlans(stripeConfig),
|
||||
@@ -349,8 +318,10 @@ async function main() {
|
||||
|
||||
const planPageContentHtml = renderMustache('', planPageParams);
|
||||
|
||||
const pathPrefix = localeName !== 'en_GB' ? `/${countryCodeOnly(localeName).toLowerCase()}` : '';
|
||||
|
||||
const templateParams = {
|
||||
...defaultTemplateParams(assetUrls, locale),
|
||||
...defaultTemplateParams(assetUrls),
|
||||
pageName: 'plans',
|
||||
partials,
|
||||
showToc: false,
|
||||
@@ -371,20 +342,10 @@ async function main() {
|
||||
// Markdown files under /readme
|
||||
// =============================================================
|
||||
|
||||
interface SourceInfo {
|
||||
title: string;
|
||||
donateLinksMd: string;
|
||||
showToc: boolean;
|
||||
openGraph: OpenGraphTags;
|
||||
sourceMarkdownName?: string;
|
||||
sourceMarkdownFile?: string;
|
||||
locale: Locale;
|
||||
}
|
||||
const mdFiles = glob.sync(`${readmeDir}/**/*.md`).map((f: string) => f.substr(rootDir.length + 1));
|
||||
const sources = [];
|
||||
|
||||
const mdFiles: string[] = glob.sync(`${readmeDir}/**/*.md`).map((f: string) => f.substr(rootDir.length + 1));
|
||||
const sources: [string, string, SourceInfo][] = [];
|
||||
|
||||
const makeTargetBasename = (input: string, pathPrefix: string): string => {
|
||||
const makeTargetBasename = (input: string): string => {
|
||||
if (isNewsFile(input)) {
|
||||
const filenameNoExt = basename(input, '.md');
|
||||
return `news/${filenameNoExt}/index.html`;
|
||||
@@ -403,49 +364,34 @@ async function main() {
|
||||
|
||||
s = s.replace(/readme\//, '');
|
||||
|
||||
if (pathPrefix) s = `${pathPrefix}/${s}`;
|
||||
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
const makeTargetFilePath = (input: string, pathPrefix: string): string => {
|
||||
return `${docDir}/${makeTargetBasename(input, pathPrefix)}`;
|
||||
const makeTargetFilePath = (input: string): string => {
|
||||
return `${docDir}/${makeTargetBasename(input)}`;
|
||||
};
|
||||
|
||||
const makeTargetUrl = (input: string, pathPrefix: string) => {
|
||||
return `https://joplinapp.org/${makeTargetBasename(input, pathPrefix)}`;
|
||||
const makeTargetUrl = (input: string) => {
|
||||
return `https://joplinapp.org/${makeTargetBasename(input)}`;
|
||||
};
|
||||
|
||||
const newsFilePaths: string[] = [];
|
||||
|
||||
for (const mdFile of mdFiles) {
|
||||
if (mdFile.startsWith('readme/_i18n')) continue;
|
||||
const title = await readmeFileTitle(`${rootDir}/${mdFile}`);
|
||||
const targetFilePath = makeTargetFilePath(mdFile);
|
||||
const openGraph = await extractOpenGraphTags(mdFile, makeTargetUrl(mdFile));
|
||||
|
||||
for (const [localeName, locale] of Object.entries(supportedLocales)) {
|
||||
const title = await readmeFileTitle(`${rootDir}/${mdFile}`);
|
||||
const targetFilePath = makeTargetFilePath(mdFile, locale.pathPrefix);
|
||||
const openGraph = await extractOpenGraphTags(mdFile, makeTargetUrl(mdFile, locale.pathPrefix));
|
||||
const isNews = isNewsFile(mdFile);
|
||||
if (isNews) newsFilePaths.push(mdFile);
|
||||
|
||||
const isNews = isNewsFile(mdFile);
|
||||
if (isNews) newsFilePaths.push(mdFile);
|
||||
|
||||
let sourceFile = mdFile;
|
||||
|
||||
if (localeName !== 'en_GB') {
|
||||
let temp = mdFile.replace(/readme\//, '');
|
||||
temp = `readme/_i18n/${localeName}/${temp}`;
|
||||
if (await pathExists(temp)) sourceFile = temp;
|
||||
}
|
||||
|
||||
sources.push([sourceFile, targetFilePath, {
|
||||
title: title,
|
||||
donateLinksMd: mdFile === 'readme/donate.md' ? '' : donateLinksMd,
|
||||
showToc: mdFile !== 'readme/download.md' && !isNews,
|
||||
openGraph,
|
||||
locale,
|
||||
}]);
|
||||
}
|
||||
sources.push([mdFile, targetFilePath, {
|
||||
title: title,
|
||||
donateLinksMd: mdFile === 'readme/donate.md' ? '' : donateLinksMd,
|
||||
showToc: mdFile !== 'readme/download.md' && !isNews,
|
||||
openGraph,
|
||||
}]);
|
||||
}
|
||||
|
||||
for (const source of sources) {
|
||||
@@ -472,7 +418,7 @@ async function main() {
|
||||
});
|
||||
|
||||
await makeNewsFrontPage(newsFilePaths, `${docDir}/news/index.html`, {
|
||||
...defaultTemplateParams(assetUrls, null),
|
||||
...defaultTemplateParams(assetUrls),
|
||||
title: 'What\'s new',
|
||||
pageName: 'news',
|
||||
partials,
|
||||
|
@@ -1,25 +0,0 @@
|
||||
import convertLinksToLocale from './convertLinksToLocale';
|
||||
|
||||
describe('convertLinksToLocale', () => {
|
||||
|
||||
it('should convert links', async () => {
|
||||
const tests: [string, any, string][] = [
|
||||
[
|
||||
'test [link](/help/link)',
|
||||
{ pathPrefix: 'fr' },
|
||||
'test [link](/fr/help/link)',
|
||||
],
|
||||
[
|
||||
'test [link](/help/link) [link2](/link2)',
|
||||
{ pathPrefix: 'fr' },
|
||||
'test [link](/fr/help/link) [link2](/fr/link2)',
|
||||
],
|
||||
];
|
||||
|
||||
for (const [input, locale, expected] of tests) {
|
||||
const actual = convertLinksToLocale(input, locale);
|
||||
expect(actual).toBe(expected);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
@@ -1,9 +0,0 @@
|
||||
import { Locale } from './types';
|
||||
|
||||
export default (md: string, locale: Locale) => {
|
||||
if (locale.lang === 'en-gb') return md;
|
||||
|
||||
md = md.replace(/\(\//g, `(/${locale.pathPrefix}/`);
|
||||
|
||||
return md;
|
||||
};
|
@@ -7,12 +7,6 @@ export enum Env {
|
||||
Prod = 'prod',
|
||||
}
|
||||
|
||||
export interface Locale {
|
||||
htmlTranslations: Record<string, string>;
|
||||
lang: string;
|
||||
pathPrefix: string;
|
||||
}
|
||||
|
||||
export interface GithubUser {
|
||||
id: string;
|
||||
}
|
||||
@@ -68,7 +62,6 @@ export interface TemplateParams {
|
||||
showBottomLinks?: boolean;
|
||||
openGraph: OpenGraphTags;
|
||||
isNews?: boolean;
|
||||
locale?: Locale;
|
||||
}
|
||||
|
||||
export interface PlanPageParams extends TemplateParams {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import * as execa from 'execa';
|
||||
import commandToString from './commandToString';
|
||||
import splitCommandString from './splitCommandString';
|
||||
import splitCommandString, { SplitCommandOptions } from './splitCommandString';
|
||||
import { stdout } from 'process';
|
||||
|
||||
interface ExecCommandOptions {
|
||||
@@ -8,6 +8,7 @@ interface ExecCommandOptions {
|
||||
showStdout?: boolean;
|
||||
showStderr?: boolean;
|
||||
quiet?: boolean;
|
||||
splitCommandOptions?: SplitCommandOptions | null;
|
||||
}
|
||||
|
||||
export default async (command: string | string[], options: ExecCommandOptions | null = null): Promise<string> => {
|
||||
@@ -33,7 +34,7 @@ export default async (command: string | string[], options: ExecCommandOptions |
|
||||
}
|
||||
}
|
||||
|
||||
const args: string[] = typeof command === 'string' ? splitCommandString(command) : command as string[];
|
||||
const args: string[] = typeof command === 'string' ? splitCommandString(command, options.splitCommandOptions || null) : command as string[];
|
||||
const executableName = args[0];
|
||||
args.splice(0, 1);
|
||||
const promise = execa(executableName, args);
|
||||
|
@@ -1,4 +1,8 @@
|
||||
export default (command: string, options: any = null) => {
|
||||
export interface SplitCommandOptions {
|
||||
handleEscape?: boolean;
|
||||
}
|
||||
|
||||
export default (command: string, options: SplitCommandOptions | null = null) => {
|
||||
options = options || {};
|
||||
if (!('handleEscape' in options)) {
|
||||
options.handleEscape = true;
|
||||
|
@@ -1,74 +0,0 @@
|
||||
<!-- DONATELINKS -->
|
||||
[! [Faire un don via PayPal] (https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/badges/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=E8JMYD2LQ8MMA&lc=GB&item_name=Joplin+Development¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted) [! [Sponsor sur GitHub] (https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/badges/GitHub-Badge.svg)](https://github.com/sponsors/laurent22/) [! [Devenez mécène] (https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/badges/Patreon-Badge.svg)](https://www.patreon.com/joplin) [! [Faire un don en utilisant un IBAN] (https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/badges/Donate-IBAN.svg)](https://joplinapp.org/donate/#donations)
|
||||
<!-- DONATELINKS -->
|
||||
|
||||
* * *
|
||||
**TEST ONLY**
|
||||
* * *
|
||||
|
||||
[test link](/spec/e2ee)
|
||||
|
||||
<img width="64" src="https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/LinuxIcons/256x256.png" align="left" />**Joplin** est une application gratuite et open source de prise de notes et de tâches, qui peut gérer un grand nombre de notes organisées dans des carnets de notes. Les notes sont consultables, peuvent être copiées, balisées et modifiées directement depuis les applications ou depuis votre propre éditeur de texte. Les notes sont au format [Markdown] (#markdown).
|
||||
|
||||
Les notes exportées depuis Evernote [peuvent être importées] (#importing) dans Joplin, y compris le contenu formaté (qui est converti en Markdown), les ressources (images, pièces jointes, etc.) et les métadonnées complètes (géolocalisation, heure de mise à jour, heure de création, etc.). Les fichiers Markdown simples peuvent également être importés.
|
||||
|
||||
Les notes peuvent être [synchronisées] (#synchronisation) en toute sécurité à l'aide du [chiffrement de bout en bout] (#encryption) avec divers services cloud, notamment Nextcloud, Dropbox, OneDrive et [Joplin Cloud] (https://joplinapp.org/plans/).
|
||||
|
||||
La recherche en texte intégral est disponible sur toutes les plateformes pour trouver rapidement les informations dont vous avez besoin. L'application peut être personnalisée à l'aide de plugins et de thèmes, et vous pouvez également créer facilement le vôtre.
|
||||
|
||||
L'application est disponible pour Windows, Linux, macOS, Android et iOS. Un [Web Clipper] (https://github.com/laurent22/joplin/blob/dev/readme/clipper.md), qui permet d'enregistrer des pages Web et des captures d'écran depuis votre navigateur, est également disponible pour [Firefox] (https://addons.mozilla.org/firefox/addon/joplin-web-clipper/) et [Chrome] (https://chrome.google.com/webstore/detail/joplin-web-clipper/alofnhikmmkdbbbgpnglcpdollgjjfek?hl=en-GB).
|
||||
|
||||
<div class="top-screenshot"></div><img src="https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/home-top-img.png" style="max-width: 100%; max-height: 35em;">
|
||||
|
||||
# Installation
|
||||
|
||||
Trois types d'applications sont disponibles : pour **bureau** (Windows, macOS et Linux), pour **mobile** (Android et iOS) et pour **terminal** (Windows, macOS, Linux et FreeBSD). Toutes les applications disposent d'interfaces utilisateur similaires et peuvent se synchroniser entre elles.
|
||||
|
||||
## Applications de bureau
|
||||
|
||||
Système d'exploitation | Télécharger
|
||||
---|---
|
||||
Windows (32 et 64 bits) | <a href='https://github.com/laurent22/joplin/releases/download/v2.9.17/Joplin-Setup-2.9.17.exe'><img alt='Get it on Windows' width="134px" src='https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/BadgeWindows.png'/></a>
|
||||
MacOS | <a href='https://github.com/laurent22/joplin/releases/download/v2.9.17/Joplin-2.9.17.dmg'><img alt='Get it on macOS' width="134px" src='https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/BadgeMacOS.png'/></a>
|
||||
Linux | <a href='https://github.com/laurent22/joplin/releases/download/v2.9.17/Joplin-2.9.17.AppImage'><img alt='Get it on Linux' width="134px" src='https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/BadgeLinux.png'/></a>
|
||||
|
||||
<a href='https://github.com/laurent22/joplin/releases/download/v2.9.17/JoplinPortable.exe'>**Sous Windows**, vous pouvez également utiliser la version portable.</a> L' [application portable] (https://en.wikipedia.org/wiki/Portable_application) permet d'installer le logiciel sur un appareil portable tel qu'une clé USB. Copiez simplement le fichier JoplinPortable.exe dans n'importe quel répertoire de cette clé USB ; l'application créera alors un répertoire appelé « JoplinProfile » à côté du fichier exécutable.
|
||||
|
||||
**Sous Linux**, la méthode recommandée est d'utiliser le script d'installation suivant car il gérera également l'icône du bureau :
|
||||
|
||||
<pre><code style="word-break: break-all">wget -O - https://raw.githubusercontent.com/laurent22/joplin/dev/Joplin_install_and_update.sh | bash</code></pre>
|
||||
|
||||
## Applications mobiles
|
||||
|
||||
Système d'exploitation | Télécharger | Alt. Télécharger
|
||||
---|---|---
|
||||
Android | <a href='https://play.google.com/store/apps/details?id=net.cozic.joplin&utm_source=GitHub&utm_campaign=README&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'><img alt='Get it on Google Play' height="40px" src='https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/BadgeAndroid.png'/></a>| ou téléchargez le fichier APK : [64 bits] (https://github.com/laurent22/joplin-android/releases/download/android-v2.9.8/joplin-v2.9.8.apk) [32 bits] ( https://github.com/laurent22/joplin-android/releases/download/android-v2.9.8/joplin-v2.9.8-32bit.apk)
|
||||
iOS | <a href='https://itunes.apple.com/us/app/joplin/id1315599797'><img alt='Get it on the App Store' height="40px" src='https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/BadgeIOS.png'/></a>| -
|
||||
|
||||
## Application du terminal
|
||||
|
||||
Système d'exploitation | Méthode
|
||||
-----------------|----------------
|
||||
macOS, Linux ou Windows (via [WSL] (https://msdn.microsoft.com/en-us/commandline/wsl/faq?f=255&MSPPError=-2147217396)) | **Important :** Tout d'abord, [installez Node 12+] (https://nodejs.org/en/download/package-manager/). <br/><br/><br><br>`NPM_CONFIG_PREFIX=~/.joplin-bin npm install -g joplin` `sudo ln -s ~/.joplin-bin/bin/joplin /usr/bin/joplin `Par défaut, le binaire de l'application sera installé sous <br/> `~/.joplin-bin`. Vous pouvez modifier ce répertoire si nécessaire. Sinon, si vos autorisations npm sont configurées comme décrit [ici] (https://docs.npmjs.com/getting-started/fixing-npm-permissions#option-2-change-npms-default-directory-to-another-directory) (Option 2), il suffit d'exécuter `npm -g install joplin`.
|
||||
|
||||
Pour le démarrer, tapez `joplin`.
|
||||
|
||||
Pour des informations d'utilisation, veuillez consulter la [Documentation complète de l'application Joplin Terminal] (https://joplinapp.org/terminal/).
|
||||
|
||||
## Web Clipper
|
||||
|
||||
Le Web Clipper est une extension de navigateur qui vous permet d'enregistrer des pages Web et des captures d'écran à partir de votre navigateur. Pour plus d'informations sur son installation et son utilisation, consultez la [Page d'aide de Web Clipper] (https://github.com/laurent22/joplin/blob/dev/readme/clipper.md).
|
||||
|
||||
## Distributions alternatives non officielles
|
||||
|
||||
Il existe un certain nombre de distributions alternatives non officielles de Joplin. Si vous ne voulez pas ou ne pouvez pas utiliser appimages ou l'une des autres versions officiellement prises en charge, vous pouvez envisager de les utiliser.
|
||||
|
||||
Cependant, ils sont assortis d'une mise en garde dans la mesure où ils ne sont pas officiellement pris en charge, de sorte que certains problèmes peuvent ne pas être pris en charge par le projet principal. Les demandes d'assistance, les rapports de bogues et les conseils généraux devraient plutôt être adressés aux responsables de ces distributions.
|
||||
|
||||
Une liste de ces distributions gérée par la communauté est disponible ici : [Distributions Joplin non officielles] (https://discourse.joplinapp.org/t/unofficial-alternative-joplin-distributions/23703)
|
||||
|
||||
# Sponsors
|
||||
|
||||
<!-- SPONSORS-ORG -->
|
||||
</a><a href="https://seirei.ne.jp"><img title="Serei Network" width="256" src="https://joplinapp.org/images/sponsors/SeireiNetwork.png"/><a href="https://www.hosting.de/nextcloud/?mtm_campaign=managed-nextcloud&mtm_kwd=joplinapp&mtm_source=joplinapp-webseite&mtm_medium=banner"><img title="Hosting.de" width="256" src="https://joplinapp.org/images/sponsors/HostingDe.png"/></a><a href="https://residence-greece.com/"><img title="Greece Golden Visa" width="256" src="https://joplinapp.org/images/sponsors/ResidenceGreece.jpg"/></a> <a href="https://grundstueckspreise.info/"><img title="SP Software GmbH" width="256" src="https://joplinapp.org/images/sponsors/Grundstueckspreise.png"/></a>
|
||||
<!-- SPONSORS-ORG -->
|
@@ -1,5 +0,0 @@
|
||||
# Application de bureau
|
||||
|
||||
<img src="https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/DemoDesktop.png" style="width: 100%">
|
||||
|
||||
Pour des informations générales relatives à toutes les applications, voir aussi [la page de garde](https://joplinapp.org).
|
@@ -439,30 +439,6 @@
|
||||
"created_at": "2023-04-10T02:33:42Z",
|
||||
"repoId": 79162682,
|
||||
"pullRequestNo": 8036
|
||||
},
|
||||
{
|
||||
"name": "simonla",
|
||||
"id": 14934570,
|
||||
"comment_id": 1503950257,
|
||||
"created_at": "2023-04-11T19:02:23Z",
|
||||
"repoId": 79162682,
|
||||
"pullRequestNo": 8042
|
||||
},
|
||||
{
|
||||
"name": "Wladefant",
|
||||
"id": 79611093,
|
||||
"comment_id": 1514649134,
|
||||
"created_at": "2023-04-19T12:28:22Z",
|
||||
"repoId": 79162682,
|
||||
"pullRequestNo": 8069
|
||||
},
|
||||
{
|
||||
"name": "DeeJayLSP",
|
||||
"id": 60024671,
|
||||
"comment_id": 1519381301,
|
||||
"created_at": "2023-04-24T04:56:51Z",
|
||||
"repoId": 79162682,
|
||||
"pullRequestNo": 8077
|
||||
}
|
||||
]
|
||||
}
|
@@ -741,7 +741,7 @@ The following commands are available in [command-line mode](#command-line-mode):
|
||||
|
||||
# License
|
||||
|
||||
Copyright (c) 2016-2023 Laurent Cozic
|
||||
Copyright (c) 2016-2021 Laurent Cozic
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
Reference in New Issue
Block a user