typescript 标记的Sum Typescript

tagged_sum.ts
import AsyncData from './AsyncData';

export default class RefreshableData<T extends AsyncData<any, any>> {
  constructor(
    /**
     * Current-most AsyncData value.
     */
    public current: T = AsyncData.NotAsked() as T,
    /**
     * Most recent settled AsyncData value,
     * where "settled" here means "AsyncData.Error or AsyncData.Data".
     */
    public lastSettled: T = current
  ) {}

  /**
   * Create a new RefreshableData instance with the next value,
   * only updating the lastSettled value if the next value
   * is a settled case.
   * @param next Next AsyncData instance.
   */
  public next(next: T): RefreshableData<T> {
    return new RefreshableData(
      next,
      next.cata({
        NotAsked: () => this.lastSettled,
        Waiting: () => (
          this.lastSettled.tag === 'NotAsked'
            ? next
            : this.lastSettled
        ),
        Error: () => next,
        Data: () => next,
      })
    );
  }
}

typescript 打字稿可刷新数据

refreshable_data.ts
import AsyncData from './AsyncData';

export default class RefreshableData<T extends AsyncData<any, any>> {
  constructor(
    /**
     * Current-most AsyncData value.
     */
    public current: T = AsyncData.NotAsked() as T,
    /**
     * Most recent settled AsyncData value,
     * where "settled" here means "AsyncData.Error or AsyncData.Data".
     */
    public lastSettled: T = current
  ) {}

  /**
   * Create a new RefreshableData instance with the next value,
   * only updating the lastSettled value if the next value
   * is a settled case.
   * @param next Next AsyncData instance.
   */
  public next(next: T): RefreshableData<T> {
    return new RefreshableData(
      next,
      next.cata({
        NotAsked: () => this.lastSettled,
        Waiting: () => (
          this.lastSettled.tag === 'NotAsked'
            ? next
            : this.lastSettled
        ),
        Error: () => next,
        Data: () => next,
      })
    );
  }
}

typescript Typescript AsyncData

typescript_async_data
import TaggedSum, { TaggedSumTagNames, TaggedSumSpecializedTo } from './TaggedSum';

/**
 * A TaggedSum type that represents the possible states of data that is
 * obtained through some asynchronous process, most frequently a fetch
 * of some sort, but not necessarily.
 *
 * Does not encode any notion of Progress, as that is usually considered
 * a separate concern, not necessarily directly related to the data itself,
 * although this could be optionally added to the Waiting state.
 */
export default class AsyncData<D, E> extends TaggedSum<'AsyncData',
  | ['NotAsked']
  | ['Waiting']
  | ['Error', E]
  | ['Data', D]
> {
  /**
   * Create a new AsyncData instance of the NotAsked tag.
   */
  public static NotAsked = <D, E>() => new AsyncData<D, E>('NotAsked');
  /**
   * Create a new AsyncData instance of the Waiting tag.
   */
  public static Waiting = <D, E>() => new AsyncData<D, E>('Waiting');
  /**
   * Create a new AsyncData instance of the Error tag.
   */
  public static Error = <D, E>(error: E) => new AsyncData<D, E>('Error', error);
  /**
   * Create a new AsyncData instance of the Data tag.
   */
  public static Data = <D, E>(data: D) => new AsyncData<D, E>('Data', data);

  /**
   * Check if a value is an instance of a TaggedSum without regard for any Tag.
   * Note that since the value may be anything, we cannot derive type parametrization
   * from it because that information was lost.  We can only determine the Sum and Tag.
   * @param inst The value that may or may not be an instance of a given tagged sum.
   */
  public static is(inst: unknown): inst is AsyncData<any, any> {
    return inst != null && inst instanceof AsyncData;
  }

  /**
   * Checks if a value is an instance of a TaggedSum with a particular Tag.
   * Note that since the value may be anything, we cannot derive type parametrization
   * from it because that information was lost.  We can only determine the Sum and Tag.
   * @param tagName The tag name you want to check against.
   * @param inst The item that may or may not be an instance of a given tagged sum.
   */
  public static isTag<
    TTagName extends TaggedSumTagNames<AsyncData<any, any>>
  >(tagName: TTagName, inst: unknown): inst is TaggedSumSpecializedTo<AsyncData<any, any>, TTagName> {
    return AsyncData.is(inst) && inst.type[0] === tagName;
  }

  /**
   * Coalesces a tuple of AsyncData instances down to a single AsyncData instance
   * whose Data type param is a tuple of all the inputs' Data type params, and whose
   * Error type param is a Union of all the inputs' Error type params.
   *
   * NOTE: Unlike with `Promise.all`, you do NOT pass an array to this function.
   *
   * Example:
   *
   *     let foo: AsyncData<number, Error>;
   *     let bar: AsyncData<string, Error>;
   *     let baz: AsyncData<{ baz: string }, { error: Error }>;
   *
   *     // Type: AsyncData<[number, string, { baz: string; }], Error | { error: Error; }>
   *     const allThemData = AsyncData.all(foo, bar, baz);
   *
   * Literally just reduces over the tuple using the coalesce method.
   * @param allInsts A tuple of AsyncData instances
   */
  public static all<TAllInsts extends Array<AsyncData<any, any>>>(...allInsts: TAllInsts): AsyncDataAllReturnType<TAllInsts> {
    return allInsts.reduce(
      (acc, next) => acc.coalesce(next, (accData: any[], nextData: any) => {
        accData.push(nextData);
        return accData;
      }),
      AsyncData.Data([])
    );
  }

  protected sum = 'AsyncData' as 'AsyncData';

  public map<DB>(fn: (data: D) => DB): AsyncData<DB, E> {
    return this.cata({
      // In these cases, we know that "this" is compatible with AsyncData<DB, E>,
      // but TS has no way of knowing that in any given handler.
      // So, coerce, coerce, coerce.  Woo.
      NotAsked: () => this as unknown as AsyncData<DB, E>,
      Waiting: () => this as unknown as AsyncData<DB, E>,
      Error: () => this as unknown as AsyncData<DB, E>,
      // TS auto-infers AsyncData<DB, DB> for some reason, so being explicit.
      Data: (data: D) => AsyncData.Data<DB, E>(fn(data)),
    });
  }

  public mapError<EB>(fn: (error: E) => EB): AsyncData<D, EB> {
    return this.cata({
      NotAsked: () => this as unknown as AsyncData<D, EB>,
      Waiting: () => this as unknown as AsyncData<D, EB>,
      Error: (error: E) => AsyncData.Error<D, EB>(fn(error)),
      Data: () => this as unknown as AsyncData<D, EB>,
    });
  }

  public flatten<DI, EI>(this: AsyncData<AsyncData<DI, EI>, E>): AsyncData<DI, E | EI> {
    return this.cata({
      NotAsked: () => this as unknown as AsyncData<DI, E>,
      Waiting: () => this as unknown as AsyncData<DI, E>,
      Error: () => this as unknown as AsyncData<DI, E>,
      Data: (data: AsyncData<DI, EI>) => data,
    });
  }

  public flatMap<DB, EB>(fn: (a: D) => AsyncData<DB, EB>): AsyncData<DB, E | EB> {
    return this.map(fn).flatten();
  }

  /**
   * Performs an opinionated merge of two AsyncData values with a bias towards
   * what would make the most sense in most cases for rendering to the UI:
   * - That Errors take precedence over everything (like Promise.all()).
   * - That Waiting takes precedence next.
   * - That NotAsked takes precedence next.
   * - And that Result is only the case if both inputs are Result.
   * @param other Another AsyncData instance.
   * @param merge How to merge the data values of the two AsyncData instances, if they're both AsyncData.Data.
   */
  public coalesce<Do, Eo, Dm>(other: AsyncData<Do, Eo>, merge: (thisData: D, otherData: Do) => Dm): AsyncData<Dm, E | Eo> {
    if (AsyncData.isTag('Error', this)) {
      return this as unknown as AsyncData<Dm, E>;
    }
    if (AsyncData.isTag('Error', other)) {
      return other as unknown as AsyncData<Dm, Eo>;
    }
    if (AsyncData.isTag('Waiting', this)) {
      return this as unknown as AsyncData<Dm, E>;
    }
    if (AsyncData.isTag('Waiting', other)) {
      return other as unknown as AsyncData<Dm, Eo>;
    }
    if (AsyncData.isTag('NotAsked', this)) {
      return this as unknown as AsyncData<Dm, E>;
    }
    if (AsyncData.isTag('NotAsked', other)) {
      return other as unknown as AsyncData<Dm, Eo>;
    }

    // now both should be 'Data'.
    return this.flatMap(thisData => other.map(otherData => merge(thisData, otherData)))
  }
}

/**
 * Return type of `AsyncData.all()`.
 */
type AsyncDataAllReturnType<TAllInsts extends Array<AsyncData<any, any>>> =
  AsyncData<
    { [I in keyof TAllInsts]: TAllInsts[I] extends AsyncData<infer R, any> ? R : never; },
    TAllInsts extends Array<AsyncData<any, infer TError>> ? TError : never
  >;

typescript 将datepicker KendoUI更改为希伯来语

ts
ואז משנים את הקוד:

import { LOCALE_ID, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { DateInputsModule } from '@progress/kendo-angular-dateinputs';
import { AppComponent } from './app.component';
import { IntlModule } from '@progress/kendo-angular-intl';

import '@progress/kendo-angular-intl/locales/de/all';
import '@progress/kendo-angular-intl/locales/es/all';
import '@progress/kendo-angular-intl/locales/he/all';

@NgModule({
    imports: [ BrowserModule, BrowserAnimationsModule, IntlModule, DateInputsModule ],
    providers: [
        { provide: LOCALE_ID, useValue: 'he-IL' }
    ],
    declarations: [ AppComponent ],
    bootstrap: [ AppComponent ]
  })

export class AppModule { }

typescript 查找替换从当前位置往后查找

untitled
// TeXworksScript
// Title: Search and Replace
// Description: search and replace like word (support wildcase)
// Author: KR
// Version: 0.1
// Date: 2019-1-17
// Script-Type: standalone
// Context: TeXDocument
// Shortcut: Ctrl+shift+H




function isEmptyObject(e) {  
    var t;  
    for (t in e)  
        return !1;
    return !0;
} 


var myFirstForm = null; // main form
var myThirdForm = null;
var myForms = [];

// any time later or straight a way

myFirstForm = TW.createUI("../Lib/searchRepDialog.ui");
myForms.push(myFirstForm);
//   TW.information(null,"s",my)
//eval("var " + pushButton + " = TW.findChildWidget(myDialogue,\"" + pushButton + "\")");
var pushButton = TW.findChildWidget(myFirstForm,"pushButton")
var replaceButton = TW.findChildWidget(myFirstForm,"pushButton_3")
var checkBox = TW.findChildWidget(myFirstForm,"checkBox")
var textEdit = TW.findChildWidget(myFirstForm,"plainTextEdit")
var textReplace = TW.findChildWidget(myFirstForm,"plainTextEdit_2")
var findText = "";
var findCount= 0
var  preIndex  = 0;
var oriStart = TW.target.selectionStart;  
function getSubMatchesIndex(index){

    if (checkBox.checked == true ) {
        findText = textEdit.plainText;
       
        // TW.information(null,"s",findText)
        findText = findText.replace("@","+?");        
        findText = findText.replace("{1,}","+");
        findText = findText.replace(".","\.");
        
    }else{
        findText = textEdit.plainText
        findText = findText.replace(/(\W)/g,"\\$1")
    }
    //TW.information(null,"s",textEdit.modificationChanged())
    var reg = new RegExp(findText,"g"); 

    TW.target.selectAll();
    var selAll = TW.target.selection;   
    TW.target.selectRange(oriStart,selAll.length-oriStart);
    //TW.information(null,"s","s")
    var dStart = TW.target.selectionStart;    
    var SELECTION = TW.target.selection; 
    var matches = SELECTION.match(reg)
    if (!isEmptyObject(matches)){
        if (index === matches.length){
            TW.information(null,"find and replace","We have finished searching the document")  
            
            findCount= -1

        }
        while (index> matches.length){
            index = index - matches.length 
        }
            //TW.information(null,"find and replace","Cannot finds")            
        
        for (var i=0; i<matches.length; i++){
            
            reg.test(SELECTION)
            
             if (i==index){
                
                
                TW.target.selectRange(oriStart + reg.lastIndex-matches[i].length, matches[i].length) 
                if (TW.target.selectionStart ==preIndex){
                    reg.test(SELECTION)
                    TW.target.selectRange(oriStart +reg.lastIndex-matches[i+1].length, matches[i+1].length) 
                }
                preIndex  = TW.target.selectionStart;
                //TW.information(null,"find and replace",preIndex);
                //TW.information(null,"find and replace",i)    
                                    
            }
            
        }
        
    }else{
        TW.information(null,"find and replace","Cannot find")
    }
    
}


var preText = textEdit.plainText;


function searchReplace(){
    if (textEdit.plainText.length< 1) {
        TW.information(null,"Search and Replace","please insert find text");
        
    }else{
        if (textEdit.plainText != preText && findCount!=0 ){
            findCount= 0;
        }
        getSubMatchesIndex(findCount);
        //TW.information(null,"s",index);

        //TW.target.selectRange(index-4,textEdit.plainText.length)
        
        //TW.target.selectRange(dStart+firstIndex ,myArray[1].length);

        findCount = findCount +1;
        //TW.information(null,"s",findCount);
        preText = textEdit.plainText;
    }
}

function replaceText(){

    if (checkBox.checked == true ) {    
        findText = textEdit.plainText;
        findText = findText.replace("@","+?");        
        findText = findText.replace("{1,}","+");  
        findText = findText.replace(".","\.");
        newRep = textReplace.plainText.replace("\\","$");
        newText = TW.target.selection.replace(new RegExp(findText,"g"),newRep);
        TW.target.insertText(newText);
    }else{
        TW.target.insertText(textReplace.plainText);
    }    
    findCount -=1
    searchReplace()
    
}

pushButton.clicked.connect(searchReplace)
replaceButton.clicked.connect(replaceText)

myFirstForm.exec();
TW.target.selectRange(oriStart);
myFirstForm.deleteLater();
//myFirstForm.show();
//myFirstForm.hide();

//myForms.setVisible(true); // there will be a momentary flicker

//   var  answer = myForm.exec();





typescript ClientStorage.js

ClientStorage.js
const DEFAULT_VERSION = 0;

export class ClientStorage {
  constructor(key, {
    isSessionOnly = false,
    version = DEFAULT_VERSION,
  } = {}) {
    this.key = key;
    this.version = version;
    this.storage = isSessionOnly ? sessionStorage : localStorage;
  }

  save(json) {
    const data = Object.assign({}, json, { version: this.version });
    this.storage.setItem(this.key, JSON.stringify(data));
  }

  load() {
    const json = this.storage.getItem(this.key);
    if (!json) return null;

    const data = JSON.parse(json);

    if (data.version !== this.version) {
      this.reset();
      return null;
    }

    delete data.version;
    return data;
  }

  reset() {
    this.storage.removeItem(this.key);
  }
}
ClientStorage.ts
const DEFAULT_VERSION = 0;

interface IStorageOptions {
  version?: number;
  isSessionOnly?: boolean;
}

export class ClientStorage<T = any> {
  readonly version: number;
  private readonly storage: Storage;

  constructor(
    private readonly key: string,
    { isSessionOnly = false, version = DEFAULT_VERSION }: IStorageOptions = {},
  ) {
    this.version = version;
    this.storage = isSessionOnly ? sessionStorage : localStorage;
  }

  save(json: T) {
    const data = { ...json, version: this.version };
    this.storage.setItem(this.key, JSON.stringify(data));
  }

  load(): T {
    const json = this.storage.getItem(this.key);
    if (!json) return null;

    const data = JSON.parse(json);

    if (data.version !== this.version) {
      this.reset();
      return null;
    }

    delete data.version;
    return data;
  }

  reset() {
    this.storage.removeItem(this.key);
  }
}

typescript 将http拦截器添加到模块

将http拦截器添加到模块

app.module.ts
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {HTTP_INTERCEPTORS, HttpClientModule} from '@angular/common/http';

import {AppComponent} from './app.component';
import {BaseURLInterceptor} from './services/base-url.interceptor';
import {HttpErrorInterceptor} from './services/http-error.interceptor';

@NgModule({
  declarations: [ AppComponent ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: BaseURLInterceptor, multi: true },
    { provide: HTTP_INTERCEPTORS, useClass: HttpErrorInterceptor, multi: true }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

typescript 用于以单一方式管理所有HTTP错误的错误拦截器

用于以单一方式管理所有HTTP错误的错误拦截器

http-error.interceptor.ts
import {Injectable} from '@angular/core';
import {HttpHandler, HttpRequest, HttpInterceptor} from '@angular/common/http';
import {throwError} from 'rxjs';
import {catchError} from 'rxjs/internal/operators';
import {ErrorService} from '../my-services/error.service';

@Injectable({
  providedIn: 'root'
})
export class HttpErrorInterceptor implements HttpInterceptor {
  construct(private errorService: ErrorService) {}
  
  intercept(req: HttpRequest<any>, next: HttpHandler) {
    return next.handle(req).pipe(
      catchError(error => {
        let errorMessage = '';
        if (error instanceof ErrorEvent) {
          // client-side error
          errorMessage = `Client-side error: ${error.error.message}`;
        } else {
          // backend error
          errorMessage = `Server-side error: ${error.status} ${error.message}`;
        }
        
        // aquí podrías agregar código que muestre el error en alguna parte fija de la pantalla.
        this.errorService.show(errorMessage);
        return throwError(errorMessage);
      })
    );
  }
}

typescript 简单的HttpInterceptor,它为请求添加标头

简单的HttpInterceptor,它为请求添加标头

base-url.interceptor.ts
import { Injectable } from '@angular/core';
import {HttpHandler, HttpRequest, HttpInterceptor} from '@angular/common/http';
import {environment} from '../../environments/environment';

@Injectable({
  providedIn: 'root'
})
export class BaseURLInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler) {
    if (!req.url.match(/^http(s)?:\/\/(.*)$/)) {
      const url = `${environment.baseURL}${req.url}`.replace(/([^:]\/)\/+/g, '$1');
      req = req.clone({ url });
    }
    return next.handle(req);
  }
}

typescript .NET核心基础知识

.NET Core Basics

// .NET core is built from scratch
// Main method is the entry point to the application
// Startup class is the enhanced way to configure your pipeline as well as dependency injection
// The project file is now "csproj" file (project.json/xproj is replaced with csproj file in .NET core 2, project.json was not compatible with MS build (DevOps platform))
// wwwroot folder for static files
// ConfigureServices method in Startup class configures any dependency injection (like providers in Angular)

// NuGet is used for managing packages.
// NPM can also be used for client side packages .. 

// MVC had a dependency on System.Web (which is tied to IIS and Windows)
// Microsoft didn't want to tie Web API with System.Web
// in .NET Core, the combined functinality of MVC and Web API is now called .NET Core MVC which is independent of System.Web

// Tag helpers - angular like directives to add logic in html
// View components - partial views with mini controllers (partials alone don't have controllers)