1
0
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:
Laurent Cozic
2020-10-15 18:40:13 +01:00
parent efa346fea4
commit eec32cf70a
18 changed files with 172 additions and 40 deletions

View 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];
}
}
}

View File

@ -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}

View File

@ -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 {

View File

@ -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_ = {

View File

@ -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);
}
};

View File

@ -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",

View File

@ -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"
}

View File

@ -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",

View File

@ -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",