public abstract class APrototype : ICloneable { public string Name { get; set; } public string Health { get; set; } } public class Prototype : APrototype { public override string ToString() { return string.Format("Player name: {0}, Health statuse: {1}", Name, Health); } }
Prototype p1 = new Prototype { Name = "Vahid", Health = "OK" }; Console.WriteLine(p1.ToString());
public abstract class APrototype : ICloneable { public string Name { get; set; } public string Health { get; set; } public abstract object Clone(); } public class Prototype : APrototype { public override object Clone() { return this.MemberwiseClone() as APrototype; } public override string ToString() { return string.Format("Player name: {0}, Health statuse: {1}", Name, Health); } }
Prototype p1 = new Prototype { Name = "Vahid", Health = "OK" }; Prototype p2 = p1.Clone() as Prototype; Console.WriteLine(p1.ToString()); Console.WriteLine(p2.ToString());
public abstract class APrototype : ICloneable { public string Name { get; set; } public string Health { get; set; } public AdditionalDetails Detail { get; set; } public abstract object Clone(); } public class AdditionalDetails { public string Height { get; set; } } public class Prototype : APrototype { public override object Clone() { return this.MemberwiseClone() as APrototype; } public override string ToString() { return string.Format("Player name: {0}, Health statuse: {1}, Height: {2}", Name, Health, Detail.Height); } }
Prototype p1 = new Prototype { Name = "Vahid", Health = "OK", Detail = new AdditionalDetails { Height = "100" } }; Prototype p2 = p1.Clone() as Prototype; p2.Detail.Height = "200"; Console.WriteLine(p1.ToString()); Console.WriteLine(p2.ToString());
public abstract class APrototype : ICloneable { public string Name { get; set; } public string Health { get; set; } //This is a ref type public AdditionalDetails Detail { get; set; } public abstract APrototype ShallowClone(); public abstract object Clone(); } public class AdditionalDetails { public string Height { get; set; } } public class Prototype : APrototype { public override object Clone() { Prototype cloned = MemberwiseClone() as Prototype; //We need to deep copy each ref types in order to prevent shallow copy cloned.Detail = new AdditionalDetails { Height = this.Detail.Height }; return cloned; } //Shallow copy will copy ref type's address instead of their value, so any changes in cloned object or source object will take effect on both objects public override APrototype ShallowClone() { return this.MemberwiseClone() as APrototype; } public override string ToString() { return string.Format("Player name: {0}, Health statuse: {1}, Height: {2}", Name, Health, Detail.Height); } }
Prototype p1 = new Prototype { Name = "Vahid", Health = "OK", Detail = new AdditionalDetails { Height = "100" } }; Prototype p2 = p1.Clone() as Prototype; p2.Detail.Height = "200"; Console.WriteLine("<This is Deep Copy>"); Console.WriteLine(p1.ToString()); Console.WriteLine(p2.ToString()); Prototype p3 = new Prototype { Name = "Vahid", Health = "OK", Detail = new AdditionalDetails { Height = "100" } }; Prototype p4 = p3.ShallowClone() as Prototype; p4.Detail.Height = "200"; Console.WriteLine("\n<This is Shallow Copy>"); Console.WriteLine(p3.ToString()); Console.WriteLine(p4.ToString());
ERROR in ./node_modules/angular2-permission/index.ts Module build failed: Error: C:\Front\node_modules\angular2-permission\index.ts is missing from the TypeScript compilation. Please make sure it is in your tsconfig via the 'files' or 'include' property. The missing file seems to be part of a third party library. TS files in published libraries are often a sign of a badly packaged library. Please open an issue in the library repository to alert its author and ask them to package the library using the Angular Package Format (https://goo.gl/jB3GVv). at AngularCompilerPlugin.getCompiledFile (C:\Front\node_modules\@ngtools\webpack\src\angular_compiler_plugin.js:674:23) at plugin.done.then (C:\Front\node_modules\@ngtools\webpack\src\loader.js:467:39) at process._tickCallback (internal/process/next_tick.js:68:7)
نصب پیشنیازهای کار با Gulp و TypeScript
فایل package.json در قسمت اول این سری معرفی شد. دراینجا قسمت devDependencies آنرا به نحو ذیل تکمیل کنید:
"devDependencies": { "typescript": "^1.8.10", "gulp": "^3.9.1", "path": "^0.12.7", "gulp-clean": "^0.3.2", "fs": "^0.0.2", "gulp-concat": "^2.6.0", "gulp-typescript": "^2.13.1", "gulp-tsc": "^1.1.5", "del": "^2.2.0", "gulp-autoprefixer": "^3.1.0", "gulp-cssnano": "^2.0.0", "gulp-html-replace": "^1.5.4", "gulp-htmlmin": "^1.0.5", "gulp-uglify": "^1.5.3", "merge-stream": "^1.0.0", "systemjs-builder": "^0.15.16", "typings": "^0.8.1" },
نکتهی مهم آن systemjs-builder است. این کتابخانه کار کامپایل systemjs.config.js را به یک تک اسکریپت انجام میدهد. به این ترتیب مشکل صدها بار رفت و برگشت به سرور، برای دریافت وابستگیهای AngularJS 2.0، به طور کامل برطرف میشود.
افزودن فایل gulpfile.js به پروژه
یا یک فایل جدید جاوا اسکریپتی را به نام gulpfile.js به ریشهی پروژه اضافه کنید و یا از منوی project -> add new item نیز میتوانید گزینهی gulp configuration file را در VS 2015 انتخاب نمائید. محتوای این فایل را به نحو ذیل تغییر دهید:
var gulp = require("gulp"), concat = require("gulp-concat"), tsc = require("gulp-typescript"), jsMinify = require("gulp-uglify"), cssPrefixer = require("gulp-autoprefixer"), cssMinify = require("gulp-cssnano"), del = require("del"), merge = require("merge-stream"), minifyHTML = require('gulp-htmlmin'), SystemBuilder = require("systemjs-builder"); var appFolder = "./app"; var outFolder = "wwwroot"; gulp.task("clean", () => { return del(outFolder); }); gulp.task("shims", () => { return gulp.src([ "node_modules/es6-shim/es6-shim.js", "node_modules/zone.js/dist/zone.js", "node_modules/reflect-metadata/Reflect.js" ]) .pipe(concat("shims.js")) .pipe(jsMinify()) .pipe(gulp.dest(outFolder + "/js/")); }); gulp.task("tsc", () => { var tsProject = tsc.createProject("./tsconfig.json"); var tsResult = gulp.src([ appFolder + "/**/*.ts" ]) .pipe(tsc(tsProject), undefined, tsc.reporter.fullReporter()); return tsResult.js.pipe(gulp.dest("build/")); }); gulp.task("system-build", ["tsc"], () => { var builder = new SystemBuilder(); return builder.loadConfig("systemjs.config.js") .then(() => builder.buildStatic(appFolder, outFolder + "/js/bundle.js")) .then(() => del("build")); }); gulp.task("buildAndMinify", ["system-build"], () => { var bundle = gulp.src(outFolder + "/js/bundle.js") .pipe(jsMinify()) .pipe(gulp.dest(outFolder + "/js/")); var css = gulp.src(outFolder + "/css/styles.css") .pipe(cssMinify()) .pipe(gulp.dest(outFolder + "/css/")); return merge(bundle, css); }); gulp.task("favicon", function () { return gulp.src("./app/favicon.ico") .pipe(gulp.dest(outFolder)); }); gulp.task("css", function () { return gulp.src(appFolder + "/**/*.css") .pipe(cssPrefixer()) .pipe(cssMinify()) .pipe(gulp.dest(outFolder)); }); gulp.task("templates", function () { return gulp.src(appFolder + "/**/*.html") .pipe(minifyHTML()) .pipe(gulp.dest(outFolder)); }); gulp.task("assets", ["templates", "css", "favicon"], function () { return gulp.src(appFolder + "/**/*.png") .pipe(gulp.dest(outFolder)); }); gulp.task("otherScriptsAndStyles", () => { gulp.src([ "jquery/dist/jquery.*js", "bootstrap/dist/js/bootstrap*.js" ], { cwd: "node_modules/**" }) .pipe(gulp.dest(outFolder + "/js/")); gulp.src([ "node_modules/bootstrap/dist/css/bootstrap.css" ]).pipe(cssMinify()).pipe(gulp.dest(outFolder + "/css/")); gulp.src([ "node_modules/bootstrap/fonts/*.*" ]).pipe(gulp.dest(outFolder + "/fonts/")); }); //gulp.task("watch.tsc", ["tsc"], function () { // return gulp.watch(appFolder + "/**/*.ts", ["tsc"]); //}); //gulp.task("watch", ["watch.tsc"]); gulp.task("default", [ "shims", "buildAndMinify", "assets", "otherScriptsAndStyles" //,"watch" ]);
در این فایل فرض شدهاست که خروجی نهایی برنامه قرار است در پوشهای به نام wwwroot کپی شود و پوشهی اصلی برنامه، همان پوشهای به نام app، در ریشهی پروژه است.
var appFolder = "./app"; var outFolder = "wwwroot";
1) وظیفهی clean، کار تمیز کردن پوشهی نهایی خروجی برنامه را انجام میدهد (حذف تمام فایلهای آن).
2) وظیفهی shims، کار بسته بندی، یکی کردن و فشرده کردن سه اسکریپت es6-shim.js، zone.js و Reflect.js را انجام میدهد. سپس تک فایل حاصل را به نام shims.js، در پوشهی wwwroot/js کپی میکند.
3) وظیفهی tsc، یکبار دیگر کامپایلر TypeScript را اجرا میکند تا مطمئن شویم با آخرین نگارش فایلهای js برنامه کار میکنیم.
4) وظیفهی system-build، کار پردازش خودکار مداخل فایل systemjs.config.js را انجام میدهد. در آخرین نگارش ارائه شدهی AngularJS 2.0، بجای ذکر مداخل مورد نیاز آن، این تک فایل systemjs.config.js را به صفحه پیوست میکنیم تا اسکریپتهای لازم را (چند صد عدد)، به صورت خودکار بارگذاری کند. برای یکی کردن این چند صد عدد اسکریپت، از کتابخانهی SystemBuilder آن کمک گرفته و کار کامپایل نهایی را انجام میدهیم. خروجی تمام این فایلها، به همراه کلیه فایلهای js حاصل از کامپایل فایلهای TypeScript برنامه، در فایلی به نام bundle.js کپی شدهی در پوشهی wwwroot/js نوشته میشود. بنابراین دیگر نیازی نیست تا فایلهای js پوشهی app و همچنین فایلهای js وابستگیهای AngularJS 2.0 را توزیع کنیم. تک فایل bundle.js، حاوی تمام اینها است.
5) وظیفهی buildAndMinify کار اجرای وظیفهی system-bulder را به همراه فشرده سازی تک فایل bundle.js، به عهده دارد. به علاوه اگر در پوشهی css آن نیز فایل styles.css موجود باشد، آن را فشرده میکند.
6) در ادامه یک سری وظیفهی کپی کردن منابع برنامه را مشاهده میکنید. مانند favicon که کار کپی کردن این آیکن را به پوشهی wwwroot انجام میدهد. وظیفهی css، فایلهای css موجود در پوشههای برنامه را به wwwroot و زیر پوشههای آن کپی میکند. وظیفهی templates، کار کپی کردن فایلهای html قالبهای کامپوننتها را بر عهده دارد. وظیفهی assets، کار کپی کردن فایلهای png را انجام میدهد.
7) وظیفهی otherScriptsAndStyles یک سری css و js ثالث را به پوشهی wwwroot کپی میکند؛ مانند فایلهای بوت استرپ و جیکوئری.
8) وظیفهی default، کار اجرای تمام این وظایف را با هم به عهده دارد.
اکنون اگر بر روی gulpfile.js کلیک راست کنید، گزینهی task runner explorer ظاهر خواهد شد. آنرا انتخاب کنید:
بر روی وظیفهی default کلیک راست کرده و آنرا اجرا کنید. پس از مدتی پوشهی جدید wwwroot ساخته شده و فایلهای نهایی برنامه به آن کپی میشوند.
اصلاح فایل index.html و یا Views\Shared\_Layout.cshtml
اکنون که تمام فایلهای مورد نیاز پروژه در پوشهی wwwroot کپی شدهاند، نیاز است فایل index.html را به نحو ذیل تغییر داد:
<!DOCTYPE html> <html> <head> <base href="/"> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>@ViewBag.Title - My ASP.NET Application</title> <link href="~/wwwroot/css/bootstrap.css" rel="stylesheet" /> <link href="~/wwwroot/app.component.css" rel="stylesheet" /> <link href="~/Content/Site.css" rel="stylesheet" type="text/css" /> <script src="~/wwwroot/js/shims.js"></script> </head> <body> <div> @RenderBody() <pm-app>Loading App...</pm-app> </div> <script src="~/wwwroot/js/jquery/dist/jquery.min.js"></script> <script src="~/wwwroot/js/bootstrap/dist/js/bootstrap.min.js"></script> <script src="~/wwwroot/js/bundle.js"></script> @RenderSection("Scripts", required: false) </body> </html>
اسکریپتهای shims که برای مرورگرهای قدیمیتر درنظر گرفته شدهاند، به تک فایل wwwroot/js/shims.js منتقل شدهاند.
تمام اسکریپتهای AngularJS 2.0 و وابستگیهای آن به همراه تمام اسکریپتهای برنامهی خودمان، به تک فایل wwwroot/js/bundle.js منتقل شدهاند.
اکنون اگر برنامه را اجرا کنید، سرعت آن با قبل قابل مقایسه نیست! اینبار دیگر نه نیازی به بارگذاری تمام وابستگیهای AngularJS 2.0 به صورت مجزا توسط systemjs.config.js وجود دارد و نه به ازای مشاهدهی هر صفحهای، یکبار قرار است فایل js کامپوننت آن بارگذاری شود. تمام اینها داخل فایل wwwroot/js/bundle.js قرار گرفتهاند و تنها یکبار بارگذاری میشوند.
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید: MVC5Angular2.part12.zip
خلاصهی بحث
با نوشتن یک Gulp Task جدید میتوان بر اساس فایل systemjs.config.js، تمام اسکریپتهای دخیل در اجرای برنامه را به صورت خودکار یافته و به صورت یک تک فایل نهایی، بسته بندی و توزیع کرد.
آزمون اطلاعات عمومی JavaScript
JS Is Weird
JavaScript is a great programming language, but thanks to the fact that its initial release was built in only ten days back in 1995, coupled with the fact that JS is backward-compatible, it's also a bit weird. It doesn't always behave the way you might think. In this quiz, you'll be shown 25 quirky expressions and will have to guess the output. Even if you're a JS developer, most of this syntax is probably, and hopefully, not something you use in your daily life.
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
"dependencies": { "@angular/animations": "^6.0.9", "@angular/cdk": "^6.4.0", "@angular/common": "^2.3.1", "@angular/compiler": "^2.3.1", "@angular/core": "^2.3.1", "@angular/forms": "^2.3.1", "@angular/http": "^2.3.1", "@angular/material": "^6.4.0", "@angular/platform-browser": "^2.3.1", "@angular/platform-browser-dynamic": "^2.3.1", "@angular/router": "^3.3.1", "core-js": "^2.4.1", "hammerjs": "^2.0.8", "rxjs": "^5.0.1", "ts-helpers": "^1.1.1", "zone.js": "^0.7.2" }, "devDependencies": { "@angular/compiler-cli": "^2.3.1", "@types/jasmine": "2.5.38", "@types/node": "^6.0.42", "angular-cli": "1.0.0-beta.28.3", "codelyzer": "~2.0.0-beta.1", "jasmine-core": "2.5.2", "jasmine-spec-reporter": "2.5.0", "karma": "1.2.0", "karma-chrome-launcher": "^2.0.0", "karma-cli": "^1.0.1", "karma-jasmine": "^1.0.2", "karma-remap-istanbul": "^0.2.1", "protractor": "~4.0.13", "ts-node": "1.2.1", "tslint": "^4.3.0", "typescript": "~2.0.3"
جهت افزودن قابلیتهای meta-programming به زبانهای جاوا اسکریپت و TypeScript و همچنین تعریف annotations بر روی کلاسها و اعضای کلاس، میتوان از Decorators استفاده کرد. یک decorator، تعریف ویژهای است که میتواند به تعریف یک کلاس، متد، خاصیت و یا پارامتر «متصل» شود و به صورت expression@ تعریف میگردد. این expression باید قابلیت فراخوانی به صورت یک متد را داشته باشد که در زمان اجرا فراخوانی خواهد شد. از Decorators در طراحی AngularJS 2 زیاد استفاده شدهاست.
نحوهی فعال سازی Decorators با ES 5
این قابلیت فعلا در مرحلهی آزمایش به سر میبرد؛ بنابراین برای فعال سازی آن نیاز است پارامترهای experimentalDecorators و emitDecoratorMetadata را به کامپایلر خط فرمان tsc و یا به خواص کامپایلر در فایل tsconfig.json اضافه کنید:
Command Line: tsc --target ES5 --experimentalDecorators --emitDecoratorMetadata tsconfig.json: { "compilerOptions": { "target": "ES5", "experimentalDecorators": true, "emitDecoratorMetadata": true } }
بررسی انواع Decorators
در اینجا یک مثال ساده از decoratorها را مشاهده میکنید:
// A simple decorator @decoratorExpression class MyClass { }
function decoratorExpression(target) { // Add a property on target target.annotated = true; }
در ادامه انواع و اقسام decoratorهای ممکن را با مثالهایی بررسی خواهیم کرد.
Class Decorator
یک class Decorator، پیش از تعریف یک کلاس اضافه میشود و هدف آن، اعمال تعاریفی به سازندهی کلاس است و از آن میتوان جهت تحت نظر قرار دادن تعاریف کلاس و یا تغییر یا حتی تعویض کلی تعاریف آن استفاده کرد. یک class Decorator را نمیتوان در سایر فایلهای تعاریف، مانند d.ts. قرار داد.
تنها آرگومانی که به یک class Decorator ارسال میشود، سازندهی کلاسی است که به آن اعمال شدهاست. اگر متد class Decorator مقداری را برگرداند، سبب تعویض و جایگزینی تعاریف کلاس با مقدار باگشت داده شده، میشود.
در ادامه دو مثال را از class Decoratorها مشاهده میکنید:
مثال بدون پارامتر
function ClassDecorator( target: Function // The class the decorator is declared on ) { console.log("ClassDecorator called on: ", target); } @ClassDecorator class ClassDecoratorExample { }
اگر به تصویر فوق و خروجی نهایی آن دقت کنید، مشاهده میکنید که یک decorator برای اجرا، نیازی به وهله سازی از آن کلاس ندارد و اجرای آن دقیقا در زمان تعریف کلاس انجام میشود. این اجرا به معنای تزریق کدهای تزئین کننده، به تعاریف سازندهی کلاس تعریف شده، پیش از وهله سازی از آن است.
مثال با پارامتر
function ClassDecoratorParams(param1: number, param2: string) { return function( target: Function // The class the decorator is declared on ) { console.log("ClassDecoratorParams(" + param1 + ", '" + param2 + "') called on: ", target); } } @ClassDecoratorParams(1, "a") @ClassDecoratorParams(2, "b") class ClassDecoratorParamsExample { }
ClassDecoratorParams(2, 'b') called on: function ClassDecoratorParamsExample() { } ClassDecoratorParams(1, 'a') called on: function ClassDecoratorParamsExample() { }
Property Decorator
یک Property Decorator دقیقا پیش از تعریف یک خاصیت اضافه میشود و نباید در سایر فایلهای تعاریف جانبی قرار گیرد. زمانیکه متد expression آن در runtime فراخوانی میشود، دو پارامتر را دریافت خواهد کرد:
الف) برای static member ها، متد سازندهی کلاس و برای instance memberها، prototype کلاس را دریافت میکند.
ب) نام عضو.
اگر متد expression تعریف شده، مقداری را برگرداند، به عنوان Property Descriptor آن عضو بکارگرفته میشود.
در مثال ذیل که متد PropertyDecorator به خاصیت name اعمال شدهاست، دو پارامتر ارسالی به آنرا بهتر میتوان مشاهده کرد:
function PropertyDecorator( target: Object, // The prototype of the class propertyKey: string | symbol // The name of the property ) { console.log("PropertyDecorator called on: ", target, propertyKey); } class PropertyDecoratorExample { @PropertyDecorator name: string; }
PropertyDecorator called on: PropertyDecoratorExample {} name
Method Decorator
یک Method Decorator باید درست پیش از تعریف یک متد، قرارگیرد و نباید در سایر کلاسها تعاریف نوعهای جانبی افزوده شود. هدف از آن میتواند بررسی، مشاهده و تغییر رفتار یک متد باشد. به متد expression آن، سه پارامتر ارسال میشوند:
الف) برای static member ها، متد سازندهی کلاس و برای instance memberها، prototype کلاس را دریافت میکند.
ب) نام عضو
ج) Property Descriptor عضو
اگر متد تعریف شده، خروجی را برگرداند به عنوان Property Descriptor آن متد استفاده خواهد شد.
در مثال ذیل، متد تزئین کنندهای به نام MethodDecorator تعریف شدهاست که سه پارامتر یاد شده را در زمان اجرا دریافت میکند:
function MethodDecorator( target: Object, // The prototype of the class propertyKey: string, // The name of the method descriptor: TypedPropertyDescriptor<any> ) { console.log("MethodDecorator called on: ", target, propertyKey, descriptor); } class MethodDecoratorExample { @MethodDecorator method() { } }
MethodDecorator called on: MethodDecoratorExample { method: [Function] } method { value: [Function], writable: true, enumerable: true, configurable: true }
و مثالی جهت محدود ساختن آن به یک سری متد خاص که یک پارامتر عددی را دریافت میکنند و یک خروجی عددی نیز دارند:
function TypeRestrictedMethodDecorator( target: Object, // The prototype of the class propertyKey: string, // The name of the method descriptor: TypedPropertyDescriptor<(num: number) => number> ) { console.log("TypeRestrictedMethodDecorator called on: ", target, propertyKey, descriptor); } class TypeRestrictedMethodDecoratorExample { @TypeRestrictedMethodDecorator method(num: number): number { return 0; } }
TypeRestrictedMethodDecorator called on: TypeRestrictedMethodDecoratorExample { method: [Function] } method { value: [Function], writable: true, enumerable: true, configurable: true }
و مثالی از تزئین کنندههای متدهای استاتیک یک کلاس که در این حالت، پارامتر target از نوع متد سازندهی کلاس خواهد بود و نه prototype آن:
function StaticMethodDecorator( target: Function, // the function itself and not the prototype propertyKey: string | symbol, // The name of the static method descriptor: TypedPropertyDescriptor<any> ) { console.log("StaticMethodDecorator called on: ", target, propertyKey, descriptor); } class StaticMethodDecoratorExample { @StaticMethodDecorator static staticMethod() { } }
StaticMethodDecorator called on: function StaticMethodDecoratorExample() { } staticMethod { value: [Function], writable: true, enumerable: true, configurable: true }
Parameter Decorator
یک Parameter Decorator باید درست پیش از تعریف یک آرگومان متد، قرارگیرد و نباید در سایر کلاسها تعاریف نوعهای جانبی افزوده شود. به متد expression آن سه پارامتر ارسال میشوند:
الف) برای static member ها، متد سازندهی کلاس و برای instance memberها، prototype کلاس را دریافت میکند.
ب) نام عضو
ج) شماره ایندکس پارامتر مدنظر در متد
از خروجی متد تزئین کننده در اینجا صرفنظر میشود.
در ادامه مثالی را از نحوهی تعریف یک تزئین کنندهی پارامترها را با سه آرگومان ویژهی آن، مشاهده میکنید:
function ParameterDecorator( target: Function, // The prototype of the class propertyKey: string | symbol, // The name of the method parameterIndex: number // The index of parameter in the list of the function's parameters ) { console.log("ParameterDecorator called on: ", target, propertyKey, parameterIndex); } class ParameterDecoratorExample { method(@ParameterDecorator param1: string, @ParameterDecorator param2: number) { } }
ParameterDecorator called on: ParameterDecoratorExample { method: [Function] } method 1 ParameterDecorator called on: ParameterDecoratorExample { method: [Function] } method 0
یک سری مثال تکمیلی
npm install darkreader
// فعال کردن DarkReader.enable({ brightness: 100, contrast: 90, sepia: 10 }); // غیر فعال کردن DarkReader.disable();
import { enable as enableDarkMode, disable as disableDarkMode, } from 'darkreader'; // فعال کردن enableDarkMode({ brightness: 100, contrast: 90, sepia: 10, }); // غیر فعال کردن disableDarkMode();
var defaultTheme = { mode: 1, // (0 1) for enabling or disabling dark mode brightness: 100, contrast: 100, grayscale: 0, sepia: 0, useFont: false, fontFamily: '', // add custom font textStroke: 0, engine: ThemeEngines.dynamicTheme, stylesheet: '', // add custom css styles };
Microsoft plugged as many as 89 security flaws as part of its monthly Patch Tuesday updates released today, including fixes for an actively exploited zero-day in Internet Explorer that could permit an attacker to run arbitrary code on target machines.