You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-07-16 00:14:34 +02:00
Removed cache package dependency and implemented one more suitable for React Native
This commit is contained in:
84
ReactNativeClient/lib/InMemoryCache.ts
Normal file
84
ReactNativeClient/lib/InMemoryCache.ts
Normal file
@ -0,0 +1,84 @@
|
||||
// There are plenty of packages for in-memory caching but each have their
|
||||
// own gotchas and often have extra complexity which makes it work in one
|
||||
// platform but not in another (for example, the use of long timeouts would
|
||||
// be fine in Node but not in React Native).
|
||||
//
|
||||
// So this class implements a simple in-memory cache with support for TTL.
|
||||
// Checking for expired keys is a bit inefficient since it doesn't rely on
|
||||
// timers, so it's checking every time a value is set or retrieved. But it
|
||||
// should be fine in most cases, as long as the class is not used at a massive
|
||||
// scale.
|
||||
|
||||
interface Record {
|
||||
value: any,
|
||||
expiredTime: number,
|
||||
}
|
||||
|
||||
interface Records {
|
||||
[key:string]: Record;
|
||||
}
|
||||
|
||||
interface ExpirableKeys {
|
||||
[key:string]: boolean,
|
||||
}
|
||||
|
||||
export default class Cache {
|
||||
|
||||
private maxRecords_:number;
|
||||
private records_:Records = {};
|
||||
private expirableKeys_:ExpirableKeys = {};
|
||||
private recordKeyHistory_:string[] = [];
|
||||
|
||||
constructor(maxRecords:number = 50) {
|
||||
this.maxRecords_ = maxRecords;
|
||||
}
|
||||
|
||||
private checkExpiredRecords() {
|
||||
const now = Date.now();
|
||||
|
||||
for (let key in this.expirableKeys_) {
|
||||
if (!this.records_[key]) {
|
||||
delete this.expirableKeys_[key];
|
||||
} else {
|
||||
if (this.records_[key].expiredTime <= now) {
|
||||
delete this.records_[key];
|
||||
delete this.expirableKeys_[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (this.recordKeyHistory_.length > this.maxRecords_) {
|
||||
const key = this.recordKeyHistory_[0];
|
||||
delete this.records_[key];
|
||||
delete this.expirableKeys_[key];
|
||||
this.recordKeyHistory_.splice(0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public value(key:string, defaultValue:any = undefined):any {
|
||||
this.checkExpiredRecords();
|
||||
if (key in this.records_) return this.records_[key].value;
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public setValue(key:string, value:any, ttl:number = 0) {
|
||||
this.checkExpiredRecords();
|
||||
|
||||
this.records_[key] = {
|
||||
value: value,
|
||||
expiredTime: ttl ? Date.now() + ttl : 0,
|
||||
}
|
||||
|
||||
const idx = this.recordKeyHistory_.indexOf(key);
|
||||
if (idx >= 0) this.recordKeyHistory_.splice(idx, 1);
|
||||
this.recordKeyHistory_.push(key);
|
||||
|
||||
if (ttl) {
|
||||
this.expirableKeys_[key] = true;
|
||||
} else {
|
||||
delete this.expirableKeys_[key];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import { RNCamera } from 'react-native-camera';
|
||||
const { RNCamera } = require('react-native-camera');
|
||||
const React = require('react');
|
||||
const Component = React.Component;
|
||||
const { connect } = require('react-redux');
|
||||
@ -178,7 +178,7 @@ class CameraView extends Component {
|
||||
<View style={{ position: 'absolute', backgroundColor: '#000000', width: '100%', height: '100%' }}/>
|
||||
<RNCamera
|
||||
style={Object.assign({ position: 'absolute' }, cameraRect)}
|
||||
ref={ref => {
|
||||
ref={(ref:any) => {
|
||||
this.camera = ref;
|
||||
}}
|
||||
type={this.props.cameraType}
|
||||
|
@ -3,15 +3,20 @@ const utils = require('./utils');
|
||||
const noteStyle = require('./noteStyle');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const { themeStyle } = require('lib/theme');
|
||||
const memoryCache = require('memory-cache');
|
||||
const InMemoryCache = require('lib/InMemoryCache').default;
|
||||
const md5 = require('md5');
|
||||
|
||||
// Renderered notes can potentially be quite large (for example
|
||||
// when they come from the clipper) so keep the cache size
|
||||
// relatively small.
|
||||
const inMemoryCache = new InMemoryCache(10);
|
||||
|
||||
class HtmlToHtml {
|
||||
constructor(options) {
|
||||
if (!options) options = {};
|
||||
this.resourceBaseUrl_ = 'resourceBaseUrl' in options ? options.resourceBaseUrl : null;
|
||||
this.ResourceModel_ = options.ResourceModel;
|
||||
this.cache_ = new memoryCache.Cache();
|
||||
this.cache_ = inMemoryCache;
|
||||
this.fsDriver_ = {
|
||||
writeFile: (/* path, content, encoding = 'base64'*/) => { throw new Error('writeFile not set'); },
|
||||
exists: (/* path*/) => { throw new Error('exists not set'); },
|
||||
@ -55,7 +60,7 @@ class HtmlToHtml {
|
||||
}, options);
|
||||
|
||||
const cacheKey = md5(escape(markup));
|
||||
let html = this.cache_.get(cacheKey);
|
||||
let html = this.cache_.value(cacheKey);
|
||||
|
||||
if (!html) {
|
||||
html = htmlUtils.sanitizeHtml(markup);
|
||||
@ -80,7 +85,7 @@ class HtmlToHtml {
|
||||
});
|
||||
}
|
||||
|
||||
this.cache_.put(cacheKey, html, 1000 * 60 * 10);
|
||||
this.cache_.setValue(cacheKey, html, 1000 * 60 * 10);
|
||||
|
||||
if (options.bodyOnly) {
|
||||
return {
|
||||
|
@ -2,7 +2,7 @@ const MarkdownIt = require('markdown-it');
|
||||
const md5 = require('md5');
|
||||
const noteStyle = require('./noteStyle');
|
||||
const { fileExtension } = require('./pathUtils');
|
||||
const memoryCache = require('memory-cache');
|
||||
const InMemoryCache = require('lib/InMemoryCache').default;
|
||||
|
||||
// /!\/!\ Note: the order of rules is important!! /!\/!\
|
||||
const rules = {
|
||||
@ -44,6 +44,9 @@ function slugify(s) {
|
||||
return nodeSlug(s);
|
||||
}
|
||||
|
||||
// Share across all instances of MdToHtml
|
||||
const inMemoryCache = new InMemoryCache(20);
|
||||
|
||||
class MdToHtml {
|
||||
constructor(options = null) {
|
||||
if (!options) options = {};
|
||||
@ -57,7 +60,7 @@ class MdToHtml {
|
||||
this.cachedHighlightedCode_ = {};
|
||||
this.ResourceModel_ = options.ResourceModel;
|
||||
this.pluginOptions_ = options.pluginOptions ? options.pluginOptions : {};
|
||||
this.contextCache_ = new memoryCache.Cache();
|
||||
this.contextCache_ = inMemoryCache;
|
||||
|
||||
this.tempDir_ = options.tempDir;
|
||||
this.fsDriver_ = {
|
||||
|
@ -16,7 +16,7 @@ function installRule(markdownIt:any, mdOptions:any, ruleOptions:any, context:any
|
||||
}
|
||||
|
||||
const cacheKey = md5(escape(token.content));
|
||||
let sanitizedContent = context.cache.get(cacheKey);
|
||||
let sanitizedContent = context.cache.value(cacheKey);
|
||||
|
||||
// For html_inline, the content is only a fragment of HTML, as it will be rendered, but
|
||||
// it's not necessarily valid HTML. For example this HTML:
|
||||
@ -37,7 +37,7 @@ function installRule(markdownIt:any, mdOptions:any, ruleOptions:any, context:any
|
||||
|
||||
token.content = sanitizedContent;
|
||||
|
||||
context.cache.put(cacheKey, sanitizedContent, 1000 * 60 * 60);
|
||||
context.cache.setValue(cacheKey, sanitizedContent, 1000 * 60 * 60);
|
||||
walkHtmlTokens(token.children);
|
||||
}
|
||||
};
|
||||
|
@ -855,11 +855,6 @@
|
||||
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
|
||||
"integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4="
|
||||
},
|
||||
"memory-cache": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/memory-cache/-/memory-cache-0.2.0.tgz",
|
||||
"integrity": "sha1-eJCwHVLADI68nVM+H46xfjA0hxo="
|
||||
},
|
||||
"mermaid": {
|
||||
"version": "8.8.1",
|
||||
"resolved": "https://registry.npmjs.org/mermaid/-/mermaid-8.8.1.tgz",
|
||||
@ -972,9 +967,9 @@
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"slug": {
|
||||
"version": "3.3.5",
|
||||
"resolved": "https://registry.npmjs.org/slug/-/slug-3.3.5.tgz",
|
||||
"integrity": "sha512-d/9yTbJDtSIhJThaNRP/U5uxwCl0mWIlV42JmKSfvg8t7DiVt69G8rAWTc0FWhaQOier0fiNAWVs7ctvVhK1RA=="
|
||||
"version": "3.5.1",
|
||||
"resolved": "https://registry.npmjs.org/slug/-/slug-3.5.1.tgz",
|
||||
"integrity": "sha512-ei0JnJzg8HKhLunZy+vpNlILRRradfaAQ+p2YEI4b4r8yX/5TlFi1JSwcYQCg7INZxdTC43BT68rHMkRxzn7Xg=="
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.5.7",
|
||||
|
@ -36,7 +36,6 @@
|
||||
"markdown-it-sup": "^1.0.0",
|
||||
"markdown-it-toc-done-right": "^4.1.0",
|
||||
"md5": "^2.2.1",
|
||||
"memory-cache": "^0.2.0",
|
||||
"mermaid": "^8.8.1",
|
||||
"slug": "^3.5.0"
|
||||
}
|
||||
|
5
ReactNativeClient/package-lock.json
generated
5
ReactNativeClient/package-lock.json
generated
@ -7930,11 +7930,6 @@
|
||||
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
|
||||
"integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4="
|
||||
},
|
||||
"memory-cache": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/memory-cache/-/memory-cache-0.2.0.tgz",
|
||||
"integrity": "sha1-eJCwHVLADI68nVM+H46xfjA0hxo="
|
||||
},
|
||||
"merge-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
||||
|
@ -46,7 +46,6 @@
|
||||
"markdown-it-sup": "^1.0.0",
|
||||
"markdown-it-toc-done-right": "^4.1.0",
|
||||
"md5": "^2.2.1",
|
||||
"memory-cache": "^0.2.0",
|
||||
"mermaid": "^8.8.1",
|
||||
"moment": "^2.24.0",
|
||||
"nanoid": "^3.1.12",
|
||||
|
Reference in New Issue
Block a user