1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-24 10:27:10 +02:00

All: Added script to build welcome assets and to import them on startup

This commit is contained in:
Laurent Cozic 2019-02-03 18:58:44 +00:00
parent fc416de348
commit 9c00dc4cab
8 changed files with 262 additions and 10 deletions

View File

@ -38,6 +38,7 @@ const SearchEngineUtils = require('lib/services/SearchEngineUtils');
const DecryptionWorker = require('lib/services/DecryptionWorker'); const DecryptionWorker = require('lib/services/DecryptionWorker');
const BaseService = require('lib/services/BaseService'); const BaseService = require('lib/services/BaseService');
const SearchEngine = require('lib/services/SearchEngine'); const SearchEngine = require('lib/services/SearchEngine');
const WelcomeUtils = require('lib/WelcomeUtils');
SyncTargetRegistry.addClass(SyncTargetFilesystem); SyncTargetRegistry.addClass(SyncTargetFilesystem);
SyncTargetRegistry.addClass(SyncTargetOneDrive); SyncTargetRegistry.addClass(SyncTargetOneDrive);
@ -564,6 +565,8 @@ class BaseApplication {
if (!currentFolder) currentFolder = await Folder.defaultFolder(); if (!currentFolder) currentFolder = await Folder.defaultFolder();
Setting.setValue('activeFolderId', currentFolder ? currentFolder.id : ''); Setting.setValue('activeFolderId', currentFolder ? currentFolder.id : '');
await WelcomeUtils.createWelcomeItems();
// await this.testing();process.exit(); // await this.testing();process.exit();
return argv; return argv;

View File

@ -0,0 +1,98 @@
const welcomeAssets = require('./welcomeAssets');
const Note = require('lib/models/Note');
const Setting = require('lib/models/Setting');
const Folder = require('lib/models/Folder');
const Resource = require('lib/models/Resource');
const { shim } = require('lib/shim');
const { uuid } = require('lib/uuid');
const { fileExtension, basename} = require('lib/path-utils');
const { pregQuote } = require('lib/string-utils');
class WelcomeUtils {
static async createWelcomeItems() {
const overwriteExisting = Setting.value('env') === 'dev';
const noteAssets = welcomeAssets.notes;
const folderAssets = welcomeAssets.folders;
const tempDir = Setting.value('resourceDir');
// TODO: Check if asset exist before creating
// TODO: Update createResourceFromPath for mobile
// TODO: Update BaseApplication
// TODO: Update mobile root.js
for (let i = 0; i < folderAssets.length; i++) {
const folderAsset = folderAssets[i];
const folderId = folderAsset.id;
let existingFolder = await Folder.load(folderId);
if (existingFolder && overwriteExisting) {
await Folder.delete(existingFolder.id);
existingFolder = null;
}
if (existingFolder) continue;
await Folder.save({
id: folderId,
title: folderAsset.title,
}, { isNew: true });
}
for (let i = noteAssets.length - 1; i >= 0; i--) {
const noteAsset = noteAssets[i];
const noteId = noteAsset.id;
let existingNote = await Note.load(noteId);
if (existingNote && overwriteExisting) {
await Note.delete(existingNote.id);
existingNote = null;
}
if (existingNote) continue;
let noteBody = noteAsset.body;
for (let resourceUrl in noteAsset.resources) {
if (!noteAsset.resources.hasOwnProperty(resourceUrl)) continue;
const resourceAsset = noteAsset.resources[resourceUrl];
const resourceId = resourceAsset.id;
let existingResource = await Resource.load(resourceId);
if (existingResource && overwriteExisting) {
await Resource.delete(resourceId);
existingResource = null;
}
if (!existingResource) {
const ext = fileExtension(resourceUrl);
const tempFilePath = tempDir + '/' + uuid.create() + '.tmp.' + ext;
await shim.fsDriver().writeFile(tempFilePath, resourceAsset.body, 'base64');
await shim.createResourceFromPath(tempFilePath, {
id: resourceId,
title: basename(resourceUrl),
});
await shim.fsDriver().remove(tempFilePath);
}
const regex = new RegExp(pregQuote('(' + resourceUrl + ')'), 'g');
noteBody = noteBody.replace(regex, '(:/' + resourceId + ')');
}
await Note.save({
id: noteId,
parent_id: noteAsset.parent_id,
title: noteAsset.title,
body: noteBody,
}, { isNew: true });
}
}
}
module.exports = WelcomeUtils;

View File

@ -101,7 +101,7 @@ function shimInit() {
} }
} }
shim.createResourceFromPath = async function(filePath) { shim.createResourceFromPath = async function(filePath, defaultProps = null) {
const readChunk = require('read-chunk'); const readChunk = require('read-chunk');
const imageType = require('image-type'); const imageType = require('image-type');
@ -111,8 +111,12 @@ function shimInit() {
if (!(await fs.pathExists(filePath))) throw new Error(_('Cannot access %s', filePath)); if (!(await fs.pathExists(filePath))) throw new Error(_('Cannot access %s', filePath));
defaultProps = defaultProps ? defaultProps : {};
const resourceId = defaultProps.id ? defaultProps.id : uuid.create();
let resource = Resource.new(); let resource = Resource.new();
resource.id = uuid.create(); resource.id = resourceId;
resource.mime = mime.getType(filePath); resource.mime = mime.getType(filePath);
resource.title = basename(filePath); resource.title = basename(filePath);
@ -143,6 +147,10 @@ function shimInit() {
await fs.copy(filePath, targetPath, { overwrite: true }); await fs.copy(filePath, targetPath, { overwrite: true });
} }
if (defaultProps) {
resource = Object.assign({}, resource, defaultProps);
}
return await Resource.save(resource, { isNew: true }); return await Resource.save(resource, { isNew: true });
} }

File diff suppressed because one or more lines are too long

91
Tools/build-welcome.js Normal file
View File

@ -0,0 +1,91 @@
require('app-module-path').addPath(__dirname + '/../ReactNativeClient');
const fs = require('fs-extra');
const dirname = require('path').dirname;
const { fileExtension, basename } = require('lib/path-utils.js');
const markdownUtils = require('lib/markdownUtils.js');
const rootDir = dirname(__dirname);
const welcomeDir = rootDir + '/readme/welcome';
function itemIdFromPath(path) {
const ids = {
'1_welcome_to_joplin.md': '8a1556e382704160808e9a7bef7135d3',
'2_importing_and_exporting_notes.md': 'b863cbc514cb4cafbae8dd6a4fcad919',
'3_synchronising_your_notes.md': '25b656aac0564d1a91ab98295aa3cc58',
'4_tips.md': '2ee48f80889447429a3cccb04a466072',
'AllClients.png': '5c05172554194f95b60971f6d577cc1a',
'folder_Welcome': '9bb5d498aba74cc6a047cfdc841e82a1',
};
const f = basename(path);
const id = ids[f];
if (!id) throw new Error('No ID for filename: ' + f);
return id;
}
function fileToBase64(filePath) {
const content = fs.readFileSync(filePath);
return Buffer.from(content).toString('base64');
}
async function parseNoteFile(filePath) {
const n = basename(filePath);
const number = n.split('_')[0];
const body = fs.readFileSync(filePath, 'utf8');
const title = number + '. ' + body.split('\n')[0].substr(2);
const resources = {};
const imagePaths = markdownUtils.extractImageUrls(body);
for (let i = 0; i < imagePaths.length; i++) {
const imagePath = imagePaths[i];
const fullImagePath = welcomeDir + '/' + imagePath;
const base64 = fileToBase64(fullImagePath);
resources[imagePath] = {
id: itemIdFromPath(fullImagePath),
body: base64,
}
}
return {
id: itemIdFromPath(filePath),
title: title,
body: body,
resources: resources,
};
}
async function main() {
const notes = [];
const filenames = fs.readdirSync(welcomeDir);
const rootFolder = {
id: itemIdFromPath('folder_Welcome'),
title: 'Welcome',
};
for (let i = 0; i < filenames.length; i++) {
const f = filenames[i];
const ext = fileExtension(f);
if (ext === 'md') {
const note = await parseNoteFile(welcomeDir + '/' + f);
note.parent_id = rootFolder.id;
notes.push(note);
}
}
const folders = [];
folders.push(rootFolder);
const content = { notes: notes, folders: folders }
const jsonContent = JSON.stringify(content, null, 4);
const jsContent = 'module.exports = ' + jsonContent;
fs.writeFileSync(rootDir + '/ReactNativeClient/lib/welcomeAssets.js', jsContent, { encoding: 'utf8' });
}
main().catch((error) => {
console.error(error);
});

View File

@ -26,7 +26,8 @@
"*.min.js", "*.min.js",
"*.bundle.js", "*.bundle.js",
"yarn.lock", "yarn.lock",
"*.icns" "*.icns",
"*.base64",
], ],
"folder_exclude_patterns": "folder_exclude_patterns":
[ [

View File

@ -1,11 +1,11 @@
# Welcome to Joplin # Welcome to Joplin
Joplin is a free, open source note taking and to-do application, which helps you write and organise your notes, and synchronise them between your devices. The notes are searchable, can be copied, tagged and modified either from the applications directly or from your own text editor. The notes are in [Markdown format](https://joplin.cozic.net/#markdown). Joplin is a free, open source note taking and to-do application, which helps you write and organise your notes, and synchronise them between your devices. The notes are searchable, can be copied, tagged and modified either from the applications directly or from your own text editor. The notes are in [Markdown format](https://joplin.cozic.net/#markdown). Joplin is available as **💻 desktop**, **📱 mobile** and **🔡 terminal** applications.
![](./AllClients.png)
## Joplin is divided into three parts ## Joplin is divided into three parts
**TODO: ADD SCREENSHOT**
Joplin has three main columns: Joplin has three main columns:
- **Sidebar**: It contains the list of your notebooks and tags, as well as the synchronisation status. - **Sidebar**: It contains the list of your notebooks and tags, as well as the synchronisation status.
@ -18,7 +18,7 @@ Joplin has three main columns:
Markdown is a lightweight markup language with plain text formatting syntax. Joplin supports a [Github-flavoured Markdown syntax](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) with a few variations and additions. Markdown is a lightweight markup language with plain text formatting syntax. Joplin supports a [Github-flavoured Markdown syntax](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) with a few variations and additions.
In general, while Markdown is a markup language, it is readable as-is, even without being rendered. This is a simple example (you can see how it looks in the viewer panel): In general, while Markdown is a markup language, it is meant to be human readable, even without being rendered. This is a simple example (you can see how it looks in the viewer panel):
* * * * * *
@ -48,10 +48,18 @@ A lot more is possible including adding code samples, math formulas or checkbox
## Organising your notes ## Organising your notes
Joplin notes are organised into a tree of notebooks and sub-notebooks. You can create a notebook by clicking on New Notebook, then you can drag and drop them into other notebooks to organise them as you wish. Joplin notes are organised into a tree of notebooks and sub-notebooks.
IMAGE - On **💻 desktop**, you can create a notebook by clicking on New Notebook, then you can drag and drop them into other notebooks to organise them as you wish.
- On **📱 mobile**, press the "+" icon and select "New notebook".
- On **🔡 terminal**, press `:mn`!
The second way to organise your notes is using tags. To do so, right-click on any note in the Note List, and select "Edit tags". You can then add the tags, separating each one by a comma. **TODO: ADD SUB-NOTEBOOK IMAGE**
The second way to organise your notes is using tags:
- On **💻 desktop**, right-click on any note in the Note List, and select "Edit tags". You can then add the tags, separating each one by a comma.
- On **📱 mobile**, open the note and press the "⋮" button and select "Tags".
- On **🔡 terminal**, type `:help tag` for the available commands.
**TODO: ADD TAGS TO EACH OF THESE NOTES (eg. "welcome", "markdown", "notebook" tag)** **TODO: ADD TAGS TO EACH OF THESE NOTES (eg. "welcome", "markdown", "notebook" tag)**

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB