Add support DarkMode, function list & auto-completion for TypeScript

Close #10381
This commit is contained in:
0xlay 2021-08-13 23:31:19 +03:00 committed by Don HO
parent 141fef9a45
commit f50061981a
6 changed files with 490 additions and 2 deletions

View File

@ -0,0 +1,364 @@
var crypto = require('crypto'),
Friends,
User,
Post,
WallPost,
Comment,
LoginToken;
function extractKeywords(text) {
if (!text) return [];
return text.
split(/\s+/).
filter(function(v) { return v.length > 2; }).
filter(function(v, i, a) { return a.lastIndexOf(v) === i; });
}
function convertBasicMarkup(input, allowHtml) {
var strongRe = /[*]{2}([^*]+)[*]{2}/gm;
var emRe = /[*]{1}([^*]+)[*]{1}/gm;
var linkRe = /\[([^\]]*)\]\(([^\)]*?)\)/gm;
var nlRe = /\r\n/gm;
var crRe = /\r/gm;
// special re's to revert linebreaks from <br />
var codeRe = /(<code\b[^>]*>(.*?)<\/code>)/gm;
// cleanup newlines
input = input.replace(nlRe, "\n");
input = input.replace(crRe, "\n");
// strip existing html before inserting breaks/markup
if (!allowHtml) {
// strip html
input = input
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
}
// convert newlines to breaks
input = input.replace(/\n/gm, '<br />');
// replace basic markup
input = input.replace(strongRe, function(whole, m1, m2, m3) {
return '<strong>' + m1 + '</strong>';
});
input = input.replace(emRe, function(whole, m1, m2, m3) {
return '<em>' + m1 + '</em>';
});
input = input.replace(linkRe, function(whole, m1, m2) {
// fix up protocol
if (!m2.match(/(http(s?)|ftp(s?)):\/\//gm))
// prepend http as default
m2 = 'http://' + m2;
return '<a href=\"' + m2 + '\" target=\"_blank\">' + m1 + '</a>';
});
// revert code blocks
input = input.replace(codeRe, function(whole, m1) {
return m1.replace(/<br \/>/gm, '\n');
});
return input;
}
function defineModels(mongoose, fn) {
var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
/**
* Comment model
*
* Used for persisting user comments
*/
var Comment = new Schema({
user_id: ObjectId,
//photo:String,
date: Date,
body: String,
post_id:ObjectId,
});
// register virtual members
Comment.virtual('readableday')
.get(function() {
var day = this.date.getDate();
return (day < 10 ? '0' + day : day);
});
Comment.virtual('readablemonth')
.get(function() {
return monthNamesShort[this.date.getMonth()];
});
Comment.virtual('readabletime')
.get(function() {
var hour = this.date.getHours();
var minute = this.date.getMinutes();
return (hour < 10 ? '0' + hour : hour) + ':' + (minute < 10 ? '0' + minute : minute);
});
Comment.virtual('bodyParsed')
.get(function() {
return convertBasicMarkup(this.body, false);
});
// register validators
/*Comment.path('author').validate(function(val) {
return val.length > 0;
}, 'AUTHOR_MISSING');*/
Comment.path('body').validate(function(val) {
return val.length > 0;
}, 'BODY_MISSING');
/**
* Model: WallPost
*/
var WallPost = new Schema({
friend_id: String,
preview: String,
body: String,
//rsstext: String,
slug: String,
created: Date,
modified: Date,
//tags: [String],
user_id:ObjectId,
posted_on_user_id : ObjectId,
//comments: [Comment]
});
var monthNames = [ 'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli',
'August', 'September', 'Oktober', 'November', 'Dezember' ];
var monthNamesShort = [ 'Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul',
'Aug', 'Sep', 'Okt', 'Nov', 'Dez' ];
// define virtual getter method for id (readable string)
WallPost.virtual('id')
.get(function() {
return this._id.toHexString();
});
WallPost.virtual('url')
.get(function() {
// build url for current post
var year = this.created.getFullYear();
var month = this.created.getMonth() + 1;
var day = this.created.getDate();
return '/' + year + '/' + (month < 10 ? '0' + month : month) + '/' + (day < 10 ? '0' + day : day) + '/' + this.slug + '/';
});
WallPost.virtual('rfc822created')
.get(function() {
return this.created.toGMTString();
});
WallPost.virtual('readabledate')
.get(function() {
var year = this.created.getFullYear();
var month = monthNames[this.created.getMonth()];
var day = this.created.getDate();
return (day < 10 ? '0' + day : day) + '. ' + month + ' ' + year;
});
WallPost.virtual('readableday')
.get(function() {
var day = this.created.getDate();
return (day < 10 ? '0' + day : day);
});
WallPost.virtual('readablemonth')
.get(function() {
return monthNamesShort[this.created.getMonth()];
});
WallPost.virtual('previewParsed')
.get(function() {
return convertBasicMarkup(this.preview, true);
});
WallPost.virtual('bodyParsed')
.get(function() {
return convertBasicMarkup(this.body, true);
});
// register validators
/*WallPost.path('title').validate(function(val) {
return val.length > 0;
}, 'TITLE_MISSING');
WallPost.path('preview').validate(function(val) {
return val.length > 0;
}, 'PREVIEW_MISSING');
WallPost.path('rsstext').validate(function(val) {
return val.length > 0;
}, 'RSSTEXT_MISSING');*/
WallPost.path('body').validate(function(val) {
return val.length > 0;
}, 'BODY_MISSING');
// generate a proper slug value for Wallpost
function slugGenerator (options){
options = options || {};
var key = options.key || 'body';
return function slugGenerator(schema){
schema.path(key).set(function(v){
this.slug = v.toLowerCase().replace(/[^a-z0-9]/g, '-').replace(/\++/g, '');
return v;
});
};
};
// attach slugGenerator plugin to Wallpost schema
WallPost.plugin(slugGenerator());
/**
* Model: User
*/
function validatePresenceOf(value) {
return value && value.length;
}
var User = new Schema({
'first_name': { type: String, validate: /[a-z]/ },
'last_name':{ type: String, validate: /[a-z]/ },
'age':Number,
'sex':{ type: String},
'photo':String,
'location':{ type: String, validate: /[a-z]/ },
'latitude' : String,
'longitude' : String,
'keywords': [String],
'username':String,
'email': { type: String, validate: [validatePresenceOf, 'an email is required'], index: { unique: true }, required:true },
'hashed_password': { type: String},
'salt': String,
});
User.virtual('id')
.get(function() {
return this._id.toHexString();
});
User.virtual('password')
.set(function(password) {
this._password = password;
this.salt = this.makeSalt();
this.hashed_password = this.encryptPassword(password);
})
.get(function() { return this._password; });
User.method('authenticate', function(plainText) {
return this.encryptPassword(plainText) === this.hashed_password;
});
User.method('makeSalt', function() {
return Math.round((new Date().valueOf() * Math.random())) + '';
});
User.method('encryptPassword', function(password) {
return crypto.createHmac('sha1', this.salt).update(password).digest('hex');
});
User.pre('save', function(next) {
this.keywords = extractKeywords(this.first_name);
next();
if (!validatePresenceOf(this.password)) {
next(new Error('Invalid password'));
} else {
next();
}
});
var Friends = new Schema({
requestor : String
, acceptor : String
, date_requested : Date
, status:Number
});
Friends.virtual('id')
.get(function() {
return this._id.toHexString();
});
var Post = new Schema({
filename : { type: String, index: true }
, file : String
, created_at : Date
, user_id: ObjectId
});
Post.virtual('id')
.get(function() {
return this._id.toHexString();
});
/**
* Model: LoginToken
*
* Used for session persistence.
*/
var LoginToken = new Schema({
email: { type: String, index: true },
series: { type: String, index: true },
token: { type: String, index: true }
});
LoginToken.method('randomToken', function() {
return Math.round((new Date().valueOf() * Math.random())) + '';
});
LoginToken.pre('save', function(next) {
// Automatically create the tokens
this.token = this.randomToken();
if (this.isNew)
this.series = this.randomToken();
next();
});
LoginToken.virtual('id')
.get(function() {
return this._id.toHexString();
});
LoginToken.virtual('cookieValue')
.get(function() {
return JSON.stringify({ email: this.email, token: this.token, series: this.series });
});
mongoose.model('User', User);
mongoose.model('Post', Post);
mongoose.model('Friends', Friends);
mongoose.model('LoginToken', LoginToken);
mongoose.model('WallPost', WallPost);
mongoose.model('Comment', Comment);
fn();
}
exports.defineModels = defineModels;

View File

@ -0,0 +1 @@
{"leaves":["extractKeywords","convertBasicMarkup","function","function","function","function","defineModels","slugGenerator","slugGenerator","validatePresenceOf","function","function","function","function","function","function"],"root":"unitTest"}

View File

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8" ?>
<NotepadPlus>
<AutoComplete>
<KeyWord name="abstract" />
<KeyWord name="any" />
<KeyWord name="as" />
<KeyWord name="async" />
<KeyWord name="await" />
<KeyWord name="bigint" />
<KeyWord name="boolean" />
<KeyWord name="break" />
<KeyWord name="case" />
<KeyWord name="catch" />
<KeyWord name="class" />
<KeyWord name="const" />
<KeyWord name="continue" />
<KeyWord name="debugger" />
<KeyWord name="declare" />
<KeyWord name="default" />
<KeyWord name="delete" />
<KeyWord name="do" />
<KeyWord name="else" />
<KeyWord name="enum" />
<KeyWord name="export" />
<KeyWord name="extends" />
<KeyWord name="false" />
<KeyWord name="finally" />
<KeyWord name="for" />
<KeyWord name="from" />
<KeyWord name="function" />
<KeyWord name="get" />
<KeyWord name="if" />
<KeyWord name="implements" />
<KeyWord name="import" />
<KeyWord name="in" />
<KeyWord name="instanceof" />
<KeyWord name="interface" />
<KeyWord name="let" />
<KeyWord name="module" />
<KeyWord name="NaN" />
<KeyWord name="new" />
<KeyWord name="null" />
<KeyWord name="number" />
<KeyWord name="of" />
<KeyWord name="package" />
<KeyWord name="private" />
<KeyWord name="protected" />
<KeyWord name="prototype" />
<KeyWord name="public" />
<KeyWord name="require" />
<KeyWord name="return" />
<KeyWord name="set" />
<KeyWord name="static" />
<KeyWord name="string" />
<KeyWord name="super" />
<KeyWord name="switch" />
<KeyWord name="symbol" />
<KeyWord name="synchronized" />
<KeyWord name="this" />
<KeyWord name="throw" />
<KeyWord name="true" />
<KeyWord name="try" />
<KeyWord name="type" />
<KeyWord name="typeof" />
<KeyWord name="undefined" />
<KeyWord name="var" />
<KeyWord name="void" />
<KeyWord name="while" />
<KeyWord name="with" />
<KeyWord name="yield" />
</AutoComplete>
</NotepadPlus>

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!-- ==========================================================================\
|
| To learn how to make your own language parser, please check the following
| link:
| https://npp-user-manual.org/docs/function-list/
|
\=========================================================================== -->
<NotepadPlus>
<functionList>
<!-- ================================================ [ TypeScript ] -->
<parser
displayName="TypeScript"
id ="typescript_function"
commentExpr="(?s:/\*.*?\*/)|(?m-s://.*?$)"
>
<function
mainExpr="((^|\s+|[;\}\.])([A-Za-z_$][\w$]*\.)*[A-Za-z_$][\w$]*\s*[=:]|^|[\s;\}]+)\s*function(\s+[A-Za-z_$][\w$]*)?\s*\([^\)\(]*\)[\n\s]*\{"
>
<functionName>
<nameExpr expr="[A-Za-z_$][\w$]*\s*[=:]|[A-Za-z_$][\w$]*\s*\(" />
<nameExpr expr="[A-Za-z_$][\w$]*" />
</functionName>
<className>
<nameExpr expr="([A-Za-z_$][\w$]*\.)*[A-Za-z_$][\w$]*\." />
<nameExpr expr="([A-Za-z_$][\w$]*\.)*[A-Za-z_$][\w$]*" />
</className>
</function>
</parser>
</functionList>
</NotepadPlus>

View File

@ -1244,6 +1244,25 @@ License: GPL2
<WordsStyle name="PREPROC" styleID="24" fgColor="FFCFAF" bgColor="3F3F3F" fontName="" fontStyle="0" fontSize="" /> <WordsStyle name="PREPROC" styleID="24" fgColor="FFCFAF" bgColor="3F3F3F" fontName="" fontStyle="0" fontSize="" />
<WordsStyle name="POSTPROC" styleID="25" fgColor="FFCFAF" bgColor="3F3F3F" fontName="" fontStyle="0" fontSize="" /> <WordsStyle name="POSTPROC" styleID="25" fgColor="FFCFAF" bgColor="3F3F3F" fontName="" fontStyle="0" fontSize="" />
</LexerType> </LexerType>
<LexerType name="typescript" desc="TypeScript" ext="">
<WordsStyle name="DEFAULT" styleID="11" fgColor="DCDCCC" bgColor="3F3F3F" fontName="" fontStyle="0" fontSize="" />
<WordsStyle name="INSTRUCTION WORD" styleID="5" fgColor="DFC47D" bgColor="3F3F3F" fontName="" fontStyle="1" fontSize="" keywordClass="instre1" />
<WordsStyle name="TYPE WORD" styleID="16" fgColor="CEDF99" bgColor="3F3F3F" fontName="" fontStyle="0" fontSize="" keywordClass="type1" />
<WordsStyle name="WINDOW INSTRUCTION" styleID="19" fgColor="FFCFAF" bgColor="3F3F3F" fontName="" fontStyle="1" fontSize="" keywordClass="" />
<WordsStyle name="NUMBER" styleID="4" fgColor="8CD0D3" bgColor="3F3F3F" fontName="" fontStyle="0" fontSize="" />
<WordsStyle name="STRING" styleID="6" fgColor="CC9393" bgColor="3F3F3F" fontName="" fontStyle="0" fontSize="" />
<WordsStyle name="STRINGRAW" styleID="20" fgColor="CC9393" bgColor="3F3F3F" fontName="" fontStyle="3" fontSize="" />
<WordsStyle name="CHARACTER" styleID="7" fgColor="DCA3A3" bgColor="3F3F3F" fontName="" fontStyle="0" fontSize="" />
<WordsStyle name="OPERATOR" styleID="10" fgColor="9F9D6D" bgColor="3F3F3F" fontName="" fontStyle="1" fontSize="" />
<WordsStyle name="VERBATIM" styleID="13" fgColor="CC9393" bgColor="3F3F3F" fontName="" fontStyle="0" fontSize="" />
<WordsStyle name="REGEX" styleID="14" fgColor="CC9393" bgColor="3F3F3F" fontName="" fontStyle="1" fontSize="" />
<WordsStyle name="COMMENT" styleID="1" fgColor="7F9F7F" bgColor="3F3F3F" fontName="" fontStyle="0" fontSize="" />
<WordsStyle name="COMMENT LINE" styleID="2" fgColor="7F9F7F" bgColor="3F3F3F" fontName="" fontStyle="0" fontSize="" />
<WordsStyle name="COMMENT DOC" styleID="3" fgColor="7F9F7F" bgColor="3F3F3F" fontName="" fontStyle="0" fontSize="" />
<WordsStyle name="COMMENT LINE DOC" styleID="15" fgColor="7F9F7F" bgColor="3F3F3F" fontName="" fontStyle="0" fontSize="" />
<WordsStyle name="COMMENT DOC KEYWORD" styleID="17" fgColor="7F9F7F" bgColor="3F3F3F" fontName="" fontStyle="1" fontSize="" />
<WordsStyle name="COMMENT DOC KEYWORD ERROR" styleID="18" fgColor="7F9F7F" bgColor="3F3F3F" fontName="" fontStyle="0" fontSize="" />
</LexerType>
<LexerType name="vb" desc="VB / VBS" ext=""> <LexerType name="vb" desc="VB / VBS" ext="">
<WordsStyle name="DEFAULT" styleID="7" fgColor="DCDCCC" bgColor="3F3F3F" fontName="" fontStyle="0" fontSize="" /> <WordsStyle name="DEFAULT" styleID="7" fgColor="DCDCCC" bgColor="3F3F3F" fontName="" fontStyle="0" fontSize="" />
<WordsStyle name="COMMENT" styleID="1" fgColor="7F9F7F" bgColor="3F3F3F" fontName="" fontStyle="2" fontSize="" /> <WordsStyle name="COMMENT" styleID="1" fgColor="7F9F7F" bgColor="3F3F3F" fontName="" fontStyle="2" fontSize="" />

View File

@ -372,8 +372,8 @@
</Language> </Language>
<Language name="txt2tags" ext="t2t" commentLine="" commentStart="" commentEnd=""/> <Language name="txt2tags" ext="t2t" commentLine="" commentStart="" commentEnd=""/>
<Language name="typescript" ext="ts tsx" commentLine="//" commentStart="/*" commentEnd="*/"> <Language name="typescript" ext="ts tsx" commentLine="//" commentStart="/*" commentEnd="*/">
<Keywords name="instre1">abstract package symbol get module require set as declare type null NaN undefined from async await break case catch class const continue debugger default delete do else enum export extends finally for function goto if implements import in instanceof int interface let new of private protected public return static super switch synchronized this throw throws transient try typeof var volatile while with true false prototype yield</Keywords> <Keywords name="instre1">abstract package symbol get module require set as declare type null NaN undefined from async await break case catch class const continue debugger default delete do else enum export extends finally for function if implements import in instanceof interface let new of private protected public return static super switch synchronized this throw try typeof var while with true false prototype yield</Keywords>
<Keywords name="type1">Array String number string boolean void any bigint Date</Keywords> <Keywords name="type1">number string boolean void any bigint</Keywords>
</Language> </Language>
<Language name="verilog" ext="v sv vh svh" commentLine="//" commentStart="/*" commentEnd="*/"> <Language name="verilog" ext="v sv vh svh" commentLine="//" commentStart="/*" commentEnd="*/">
<Keywords name="instre1">accept_on alias always always_comb always_ff always_latch and assert assign assume attribute automatic before begin bind bins binsof bit break buf bufif0 bufif1 byte case casex casez cell chandle checker class clocking cmos config const constraint context continue cover covergroup coverpoint cross deassign default defparam design disable dist do edge else end endattribute endcase endchecker endclass endclocking endconfig endfunction endgenerate endgroup endinterface endmodule endpackage endprimitive endprogram endproperty endsequence endspecify endtable endtask enum event eventually expect export extends extern final first_match for force foreach forever fork forkjoin function generate genvar global highz0 highz1 if iff ifnone ignore_bins illegal_bins implements implies import incdir include initial inout input inside instance int integer interconnect interface intersect join join_any join_none large let liblist library local localparam logic longint macromodule matches medium modport module nand negedge nettype new nexttime nmos nor noshowcancelled not notif0 notif1 null or output package packed parameter pmos posedge primitive priority program property protected pull0 pull1 pulldown pullup pulsestyle_ondetect pulsestyle_onevent pure rand randc randcase randsequence rcmos real realtime ref reg reject_on release repeat restrict return rnmos rpmos rtran rtranif0 rtranif1 scalared sequence shortint shortreal showcancelled signed small soft solve specify specparam static string strong strong0 strong1 struct super supply0 supply1 sync_accept_on sync_reject_on s_always s_eventually s_nexttime s_until s_until_with table tagged task this throughout time timeprecision timeunit tran tranif0 tranif1 tri tri0 tri1 triand trior trireg type typedef union unique unique0 unsigned until until_with untyped use var vectored virtual void wait wait_order wand weak weak0 weak1 while wildcard wire with within wor xnor xor</Keywords> <Keywords name="instre1">accept_on alias always always_comb always_ff always_latch and assert assign assume attribute automatic before begin bind bins binsof bit break buf bufif0 bufif1 byte case casex casez cell chandle checker class clocking cmos config const constraint context continue cover covergroup coverpoint cross deassign default defparam design disable dist do edge else end endattribute endcase endchecker endclass endclocking endconfig endfunction endgenerate endgroup endinterface endmodule endpackage endprimitive endprogram endproperty endsequence endspecify endtable endtask enum event eventually expect export extends extern final first_match for force foreach forever fork forkjoin function generate genvar global highz0 highz1 if iff ifnone ignore_bins illegal_bins implements implies import incdir include initial inout input inside instance int integer interconnect interface intersect join join_any join_none large let liblist library local localparam logic longint macromodule matches medium modport module nand negedge nettype new nexttime nmos nor noshowcancelled not notif0 notif1 null or output package packed parameter pmos posedge primitive priority program property protected pull0 pull1 pulldown pullup pulsestyle_ondetect pulsestyle_onevent pure rand randc randcase randsequence rcmos real realtime ref reg reject_on release repeat restrict return rnmos rpmos rtran rtranif0 rtranif1 scalared sequence shortint shortreal showcancelled signed small soft solve specify specparam static string strong strong0 strong1 struct super supply0 supply1 sync_accept_on sync_reject_on s_always s_eventually s_nexttime s_until s_until_with table tagged task this throughout time timeprecision timeunit tran tranif0 tranif1 tri tri0 tri1 triand trior trireg type typedef union unique unique0 unsigned until until_with untyped use var vectored virtual void wait wait_order wand weak weak0 weak1 while wildcard wire with within wor xnor xor</Keywords>