fix: 错误的忽略了单行的 a 标签
This commit is contained in:
		
							parent
							
								
									151d8824ee
								
							
						
					
					
						commit
						16bd6edca0
					
				| @ -35,10 +35,8 @@ Angular offers two ways to compile your application: | |||||||
| JIT compilation is the default when you run the _build-only_ or the _build-and-serve-locally_ CLI commands: | JIT compilation is the default when you run the _build-only_ or the _build-and-serve-locally_ CLI commands: | ||||||
| 
 | 
 | ||||||
| <code-example language="sh" class="code-shell"> | <code-example language="sh" class="code-shell"> | ||||||
| 
 |  | ||||||
|   ng build |   ng build | ||||||
|   ng serve |   ng serve | ||||||
| 
 |  | ||||||
| </code-example> | </code-example> | ||||||
| 
 | 
 | ||||||
| {@a compile} | {@a compile} | ||||||
| @ -46,10 +44,8 @@ JIT compilation is the default when you run the _build-only_ or the _build-and-s | |||||||
| For AOT compilation, append the `--aot` flags to the _build-only_ or the _build-and-serve-locally_ CLI commands: | For AOT compilation, append the `--aot` flags to the _build-only_ or the _build-and-serve-locally_ CLI commands: | ||||||
| 
 | 
 | ||||||
| <code-example language="sh" class="code-shell"> | <code-example language="sh" class="code-shell"> | ||||||
| 
 |  | ||||||
|   ng build --aot |   ng build --aot | ||||||
|   ng serve --aot |   ng serve --aot | ||||||
| 
 |  | ||||||
| </code-example> | </code-example> | ||||||
| 
 | 
 | ||||||
| <div class="l-sub-section"> | <div class="l-sub-section"> | ||||||
| @ -126,6 +122,7 @@ You can control your app compilation by providing template compiler options in t | |||||||
| `"angularCompilerOptions"` object as shown below: | `"angularCompilerOptions"` object as shown below: | ||||||
| 
 | 
 | ||||||
| ```json | ```json | ||||||
|  | 
 | ||||||
| { | { | ||||||
|   "compilerOptions": { |   "compilerOptions": { | ||||||
|     "experimentalDecorators": true, |     "experimentalDecorators": true, | ||||||
| @ -137,6 +134,7 @@ You can control your app compilation by providing template compiler options in t | |||||||
|     ... |     ... | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| ### *skipMetadataEmit* | ### *skipMetadataEmit* | ||||||
| @ -316,6 +314,7 @@ In the following example, the `@Component()` metadata object and the class const | |||||||
| 在下列范例中,`@Component()` 元数据对象和类的构造函数会告诉 Angular 如何创建和显示 `TypicalComponent` 的实例。 | 在下列范例中,`@Component()` 元数据对象和类的构造函数会告诉 Angular 如何创建和显示 `TypicalComponent` 的实例。 | ||||||
| 
 | 
 | ||||||
| ```typescript | ```typescript | ||||||
|  | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-typical', |   selector: 'app-typical', | ||||||
|   template: '<div>A typical component for {{data.name}}</div>' |   template: '<div>A typical component for {{data.name}}</div>' | ||||||
| @ -324,6 +323,7 @@ export class TypicalComponent { | |||||||
|   @Input() data: TypicalData; |   @Input() data: TypicalData; | ||||||
|   constructor(private someService: SomeService) { ... } |   constructor(private someService: SomeService) { ... } | ||||||
| } | } | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| The Angular compiler extracts the metadata _once_ and generates a _factory_ for `TypicalComponent`. | The Angular compiler extracts the metadata _once_ and generates a _factory_ for `TypicalComponent`. | ||||||
| @ -435,10 +435,12 @@ piece of metadata to generate the application code. | |||||||
|  如果你希望`ngc`立即汇报这些语法错误,而不要生成带有错误信息的`.metadata.json`文件,可以到`tsconfig`中设置 `strictMetadataEmit` 选项。 |  如果你希望`ngc`立即汇报这些语法错误,而不要生成带有错误信息的`.metadata.json`文件,可以到`tsconfig`中设置 `strictMetadataEmit` 选项。 | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
|  | 
 | ||||||
|   "angularCompilerOptions": { |   "angularCompilerOptions": { | ||||||
|    ... |    ... | ||||||
|    "strictMetadataEmit" : true |    "strictMetadataEmit" : true | ||||||
|  } |  } | ||||||
|  | 
 | ||||||
|  ``` |  ``` | ||||||
| 
 | 
 | ||||||
| Angular libraries have this option to ensure that all Angular `.metadata.json` files are clean and it is a best practice to do the same when building your own libraries. | Angular libraries have this option to ensure that all Angular `.metadata.json` files are clean and it is a best practice to do the same when building your own libraries. | ||||||
| @ -448,6 +450,7 @@ Angular 库通过这个选项来确保所有的 `.metadata.json` 文件都是干 | |||||||
| </div> | </div> | ||||||
| 
 | 
 | ||||||
| {@a function-expression} | {@a function-expression} | ||||||
|  | 
 | ||||||
| {@a arrow-functions} | {@a arrow-functions} | ||||||
| 
 | 
 | ||||||
| ### No arrow functions | ### No arrow functions | ||||||
| @ -458,10 +461,12 @@ and [arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Re | |||||||
| Consider the following component decorator: | Consider the following component decorator: | ||||||
| 
 | 
 | ||||||
| ```typescript | ```typescript | ||||||
|  | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   ... |   ... | ||||||
|   providers: [{provide: server, useFactory: () => new Server()}] |   providers: [{provide: server, useFactory: () => new Server()}] | ||||||
| }) | }) | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| The AOT _collector_ does not support the arrow function, `() => new Server()`, in a metadata expression. | The AOT _collector_ does not support the arrow function, `() => new Server()`, in a metadata expression. | ||||||
| @ -472,6 +477,7 @@ When the compiler later interprets this node, it reports an error that invites y | |||||||
| You can fix the error by converting to this: | You can fix the error by converting to this: | ||||||
| 
 | 
 | ||||||
| ```typescript | ```typescript | ||||||
|  | 
 | ||||||
| export function serverFactory() { | export function serverFactory() { | ||||||
|   return new Server(); |   return new Server(); | ||||||
| } | } | ||||||
| @ -480,6 +486,7 @@ export function serverFactory() { | |||||||
|   ... |   ... | ||||||
|   providers: [{provide: server, useFactory: serverFactory}] |   providers: [{provide: server, useFactory: serverFactory}] | ||||||
| }) | }) | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| Beginning in version 5, the compiler automatically performs this rewritting while emitting the `.js` file. | Beginning in version 5, the compiler automatically performs this rewritting while emitting the `.js` file. | ||||||
| @ -496,6 +503,7 @@ The compiler only supports calls to a small set of functions and will use `new` | |||||||
| ### Folding | ### Folding | ||||||
| 
 | 
 | ||||||
| {@a exported-symbols} | {@a exported-symbols} | ||||||
|  | 
 | ||||||
| The compiler can only resolve references to **_exported_** symbols. | The compiler can only resolve references to **_exported_** symbols. | ||||||
| Fortunately, the _collector_ enables limited use of non-exported symbols through _folding_. | Fortunately, the _collector_ enables limited use of non-exported symbols through _folding_. | ||||||
| 
 | 
 | ||||||
| @ -506,12 +514,14 @@ For example, the _collector_ can evaluate the expression `1 + 2 + 3 + 4` and rep | |||||||
| This process is called _folding_. An expression that can be reduced in this manner is _foldable_. | This process is called _folding_. An expression that can be reduced in this manner is _foldable_. | ||||||
| 
 | 
 | ||||||
| {@a var-declaration} | {@a var-declaration} | ||||||
|  | 
 | ||||||
| The collector can evaluate references to | The collector can evaluate references to | ||||||
| module-local `const` declarations and initialized `var` and `let` declarations, effectively removing them from the `.metadata.json` file. | module-local `const` declarations and initialized `var` and `let` declarations, effectively removing them from the `.metadata.json` file. | ||||||
| 
 | 
 | ||||||
| Consider the following component definition: | Consider the following component definition: | ||||||
| 
 | 
 | ||||||
| ```typescript | ```typescript | ||||||
|  | 
 | ||||||
| const template = '<div>{{hero.name}}</div>'; | const template = '<div>{{hero.name}}</div>'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
| @ -521,6 +531,7 @@ const template = '<div>{{hero.name}}</div>'; | |||||||
| export class HeroComponent { | export class HeroComponent { | ||||||
|   @Input() hero: Hero; |   @Input() hero: Hero; | ||||||
| } | } | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| The compiler could not refer to the `template` constant because it isn't exported. | The compiler could not refer to the `template` constant because it isn't exported. | ||||||
| @ -529,6 +540,7 @@ But the _collector_ can _fold_ the `template` constant into the metadata definit | |||||||
| The effect is the same as if you had written: | The effect is the same as if you had written: | ||||||
| 
 | 
 | ||||||
| ```typescript | ```typescript | ||||||
|  | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-hero', |   selector: 'app-hero', | ||||||
|   template: '<div>{{hero.name}}</div>' |   template: '<div>{{hero.name}}</div>' | ||||||
| @ -536,6 +548,7 @@ The effect is the same as if you had written: | |||||||
| export class HeroComponent { | export class HeroComponent { | ||||||
|   @Input() hero: Hero; |   @Input() hero: Hero; | ||||||
| } | } | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| There is no longer a reference to `template` and, therefore, nothing to trouble the compiler when it later interprets the _collector's_ output in `.metadata.json`. | There is no longer a reference to `template` and, therefore, nothing to trouble the compiler when it later interprets the _collector's_ output in `.metadata.json`. | ||||||
| @ -543,6 +556,7 @@ There is no longer a reference to `template` and, therefore, nothing to trouble | |||||||
| You can take this example a step further by including the `template` constant in another expression: | You can take this example a step further by including the `template` constant in another expression: | ||||||
| 
 | 
 | ||||||
| ```typescript | ```typescript | ||||||
|  | 
 | ||||||
| const template = '<div>{{hero.name}}</div>'; | const template = '<div>{{hero.name}}</div>'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
| @ -552,6 +566,7 @@ const template = '<div>{{hero.name}}</div>'; | |||||||
| export class HeroComponent { | export class HeroComponent { | ||||||
|   @Input() hero: Hero; |   @Input() hero: Hero; | ||||||
| } | } | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| The _collector_ reduces this expression to its equivalent _folded_ string: | The _collector_ reduces this expression to its equivalent _folded_ string: | ||||||
| @ -600,6 +615,7 @@ Decorated component class members must be public. You cannot make an `@Input()` | |||||||
| Data bound properties must also be public. | Data bound properties must also be public. | ||||||
| 
 | 
 | ||||||
| ```typescript | ```typescript | ||||||
|  | 
 | ||||||
| // BAD CODE - title is private | // BAD CODE - title is private | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-root', |   selector: 'app-root', | ||||||
| @ -608,9 +624,11 @@ Data bound properties must also be public. | |||||||
| export class AppComponent { | export class AppComponent { | ||||||
|   private title = 'My App'; // Bad |   private title = 'My App'; // Bad | ||||||
| } | } | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| {@a supported-functions} | {@a supported-functions} | ||||||
|  | 
 | ||||||
| Most importantly, the compiler only generates code to create instances of certain classes, support certain decorators, and call certain functions from the following lists. | Most importantly, the compiler only generates code to create instances of certain classes, support certain decorators, and call certain functions from the following lists. | ||||||
| 
 | 
 | ||||||
| ### New instances | ### New instances | ||||||
| @ -650,9 +668,11 @@ methods that return an expression. | |||||||
| For example, consider the following function: | For example, consider the following function: | ||||||
| 
 | 
 | ||||||
| ```typescript | ```typescript | ||||||
|  | 
 | ||||||
| export function wrapInArray<T>(value: T): T[] { | export function wrapInArray<T>(value: T): T[] { | ||||||
|   return [value]; |   return [value]; | ||||||
| } | } | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| You can call the `wrapInArray` in a metadata definition because it returns the value of an expression that conforms to the compiler's restrictive JavaScript subset. | You can call the `wrapInArray` in a metadata definition because it returns the value of an expression that conforms to the compiler's restrictive JavaScript subset. | ||||||
| @ -660,19 +680,23 @@ You can call the `wrapInArray` in a metadata definition because it returns the v | |||||||
| You might use  `wrapInArray()` like this: | You might use  `wrapInArray()` like this: | ||||||
| 
 | 
 | ||||||
| ```typescript | ```typescript | ||||||
|  | 
 | ||||||
| @NgModule({ | @NgModule({ | ||||||
|   declarations: wrapInArray(TypicalComponent) |   declarations: wrapInArray(TypicalComponent) | ||||||
| }) | }) | ||||||
| export class TypicalModule {} | export class TypicalModule {} | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| The compiler treats this usage as if you had written: | The compiler treats this usage as if you had written: | ||||||
| 
 | 
 | ||||||
| ```typescript | ```typescript | ||||||
|  | 
 | ||||||
| @NgModule({ | @NgModule({ | ||||||
|   declarations: [TypicalComponent] |   declarations: [TypicalComponent] | ||||||
| }) | }) | ||||||
| export class TypicalModule {} | export class TypicalModule {} | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| The collector is simplistic in its determination of what qualifies as a macro | The collector is simplistic in its determination of what qualifies as a macro | ||||||
| @ -692,6 +716,7 @@ the compiler doesn't need to know the expression's value—it just needs to | |||||||
| You might write something like: | You might write something like: | ||||||
| 
 | 
 | ||||||
| ```typescript | ```typescript | ||||||
|  | 
 | ||||||
| class TypicalServer { | class TypicalServer { | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
| @ -700,6 +725,7 @@ class TypicalServer { | |||||||
|   providers: [{provide: SERVER, useFactory: () => TypicalServer}] |   providers: [{provide: SERVER, useFactory: () => TypicalServer}] | ||||||
| }) | }) | ||||||
| export class TypicalModule {} | export class TypicalModule {} | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| Without rewriting, this would be invalid because lambdas are not supported and `TypicalServer` is not exported. | Without rewriting, this would be invalid because lambdas are not supported and `TypicalServer` is not exported. | ||||||
| @ -707,6 +733,7 @@ Without rewriting, this would be invalid because lambdas are not supported and ` | |||||||
| To allow this, the compiler automatically rewrites this to something like: | To allow this, the compiler automatically rewrites this to something like: | ||||||
| 
 | 
 | ||||||
| ```typescript | ```typescript | ||||||
|  | 
 | ||||||
| class TypicalServer { | class TypicalServer { | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
| @ -717,6 +744,7 @@ export const ɵ0 = () => new TypicalServer(); | |||||||
|   providers: [{provide: SERVER, useFactory: ɵ0}] |   providers: [{provide: SERVER, useFactory: ɵ0}] | ||||||
| }) | }) | ||||||
| export class TypicalModule {} | export class TypicalModule {} | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| This allows the compiler to generate a reference to `ɵ0` in the | This allows the compiler to generate a reference to `ɵ0` in the | ||||||
| @ -751,6 +779,7 @@ Language features outside of the compiler's [restricted expression syntax](#expr | |||||||
| can produce this error, as seen in the following example: | can produce this error, as seen in the following example: | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
|  | 
 | ||||||
| // ERROR | // ERROR | ||||||
| export class Fooish { ... } | export class Fooish { ... } | ||||||
| ... | ... | ||||||
| @ -759,6 +788,7 @@ const prop = typeof Fooish; // typeof is not valid in metadata | |||||||
|   // bracket notation is not valid in metadata |   // bracket notation is not valid in metadata | ||||||
|   { provide: 'token', useValue: { [prop]: 'value' } }; |   { provide: 'token', useValue: { [prop]: 'value' } }; | ||||||
|   ... |   ... | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| You can use `typeof` and bracket notation in normal application code. | You can use `typeof` and bracket notation in normal application code. | ||||||
| @ -785,6 +815,7 @@ The compiler encountered a referenced to a locally defined symbol that either wa | |||||||
| Here's a `provider` example of the problem. | Here's a `provider` example of the problem. | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
|  | 
 | ||||||
| // ERROR | // ERROR | ||||||
| let foo: number; // neither exported nor initialized | let foo: number; // neither exported nor initialized | ||||||
| 
 | 
 | ||||||
| @ -796,26 +827,33 @@ let foo: number; // neither exported nor initialized | |||||||
|   ] |   ] | ||||||
| }) | }) | ||||||
| export class MyComponent {} | export class MyComponent {} | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
|  | 
 | ||||||
| The compiler generates the component factory, which includes the `useValue` provider code, in a separate module. _That_ factory module can't reach back to _this_ source module to access the local (non-exported) `foo` variable. | The compiler generates the component factory, which includes the `useValue` provider code, in a separate module. _That_ factory module can't reach back to _this_ source module to access the local (non-exported) `foo` variable. | ||||||
| 
 | 
 | ||||||
| You could fix the problem by initializing `foo`. | You could fix the problem by initializing `foo`. | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
|  | 
 | ||||||
| let foo = 42; // initialized | let foo = 42; // initialized | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| The compiler will [fold](#folding) the expression into the provider as if you had written this. | The compiler will [fold](#folding) the expression into the provider as if you had written this. | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
|  | 
 | ||||||
|   providers: [ |   providers: [ | ||||||
|     { provide: Foo, useValue: 42 } |     { provide: Foo, useValue: 42 } | ||||||
|   ] |   ] | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| Alternatively, you can fix it by exporting `foo` with the expectation that `foo` will be assigned at runtime when you actually know its value. | Alternatively, you can fix it by exporting `foo` with the expectation that `foo` will be assigned at runtime when you actually know its value. | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
|  | 
 | ||||||
| // CORRECTED | // CORRECTED | ||||||
| export let foo: number; // exported | export let foo: number; // exported | ||||||
| 
 | 
 | ||||||
| @ -827,6 +865,7 @@ export let foo: number; // exported | |||||||
|   ] |   ] | ||||||
| }) | }) | ||||||
| export class MyComponent {} | export class MyComponent {} | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| Adding `export` often works for variables referenced in metadata such as `providers` and `animations` because the compiler can generate _references_ to the exported variables in these expressions. It doesn't need the _values_ of those variables. | Adding `export` often works for variables referenced in metadata such as `providers` and `animations` because the compiler can generate _references_ to the exported variables in these expressions. It doesn't need the _values_ of those variables. | ||||||
| @ -836,6 +875,7 @@ in order to generate code. | |||||||
| For example, it doesn't work for the `template` property. | For example, it doesn't work for the `template` property. | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
|  | 
 | ||||||
| // ERROR | // ERROR | ||||||
| export let someTemplate: string; // exported but not initialized | export let someTemplate: string; // exported but not initialized | ||||||
| 
 | 
 | ||||||
| @ -844,6 +884,7 @@ export let someTemplate: string; // exported but not initialized | |||||||
|   template: someTemplate |   template: someTemplate | ||||||
| }) | }) | ||||||
| export class MyComponent {} | export class MyComponent {} | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| The compiler needs the value of the `template` property _right now_ to generate the component factory. | The compiler needs the value of the `template` property _right now_ to generate the component factory. | ||||||
| @ -869,6 +910,7 @@ The following example tries to set the component's `template` property to the va | |||||||
| the exported `someTemplate` variable which is declared but _unassigned_. | the exported `someTemplate` variable which is declared but _unassigned_. | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
|  | 
 | ||||||
| // ERROR | // ERROR | ||||||
| export let someTemplate: string; | export let someTemplate: string; | ||||||
| 
 | 
 | ||||||
| @ -877,11 +919,13 @@ export let someTemplate: string; | |||||||
|   template: someTemplate |   template: someTemplate | ||||||
| }) | }) | ||||||
| export class MyComponent {} | export class MyComponent {} | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| You'd also get this error if you imported `someTemplate` from some other module and neglected to initialize it there. | You'd also get this error if you imported `someTemplate` from some other module and neglected to initialize it there. | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
|  | 
 | ||||||
| // ERROR - not initialized there either | // ERROR - not initialized there either | ||||||
| import { someTemplate } from './config'; | import { someTemplate } from './config'; | ||||||
| 
 | 
 | ||||||
| @ -890,6 +934,7 @@ import { someTemplate } from './config'; | |||||||
|   template: someTemplate |   template: someTemplate | ||||||
| }) | }) | ||||||
| export class MyComponent {} | export class MyComponent {} | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| The compiler cannot wait until runtime to get the template information. | The compiler cannot wait until runtime to get the template information. | ||||||
| @ -900,6 +945,7 @@ instructions for building the element based on the template. | |||||||
| To correct this error, provide the initial value of the variable in an initializer clause _on the same line_. | To correct this error, provide the initial value of the variable in an initializer clause _on the same line_. | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
|  | 
 | ||||||
| // CORRECTED | // CORRECTED | ||||||
| export let someTemplate = '<h1>Greetings from Angular</h1>'; | export let someTemplate = '<h1>Greetings from Angular</h1>'; | ||||||
| 
 | 
 | ||||||
| @ -908,6 +954,7 @@ export let someTemplate = '<h1>Greetings from Angular</h1>'; | |||||||
|   template: someTemplate |   template: someTemplate | ||||||
| }) | }) | ||||||
| export class MyComponent {} | export class MyComponent {} | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| <hr> | <hr> | ||||||
| @ -926,6 +973,7 @@ For example, you may have defined a class and used it as an injection token in a | |||||||
| but neglected to export that class. | but neglected to export that class. | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
|  | 
 | ||||||
| // ERROR | // ERROR | ||||||
| abstract class MyStrategy { } | abstract class MyStrategy { } | ||||||
| 
 | 
 | ||||||
| @ -934,6 +982,7 @@ abstract class MyStrategy { } | |||||||
|     { provide: MyStrategy, useValue: ... } |     { provide: MyStrategy, useValue: ... } | ||||||
|   ] |   ] | ||||||
|   ... |   ... | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| Angular generates a class factory in a separate module and that | Angular generates a class factory in a separate module and that | ||||||
| @ -941,6 +990,7 @@ factory [can only access exported classes](#exported-symbols). | |||||||
| To correct this error, export the referenced class. | To correct this error, export the referenced class. | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
|  | 
 | ||||||
| // CORRECTED | // CORRECTED | ||||||
| export abstract class MyStrategy { } | export abstract class MyStrategy { } | ||||||
| 
 | 
 | ||||||
| @ -949,6 +999,7 @@ export abstract class MyStrategy { } | |||||||
|     { provide: MyStrategy, useValue: ... } |     { provide: MyStrategy, useValue: ... } | ||||||
|   ] |   ] | ||||||
|   ... |   ... | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| <hr> | <hr> | ||||||
| @ -960,6 +1011,7 @@ Metadata referenced a function that wasn't exported. | |||||||
| For example, you may have set a providers `useFactory` property to a locally defined function that you neglected to export. | For example, you may have set a providers `useFactory` property to a locally defined function that you neglected to export. | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
|  | 
 | ||||||
| // ERROR | // ERROR | ||||||
| function myStrategy() { ... } | function myStrategy() { ... } | ||||||
| 
 | 
 | ||||||
| @ -968,6 +1020,7 @@ function myStrategy() { ... } | |||||||
|     { provide: MyStrategy, useFactory: myStrategy } |     { provide: MyStrategy, useFactory: myStrategy } | ||||||
|   ] |   ] | ||||||
|   ... |   ... | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| Angular generates a class factory in a separate module and that | Angular generates a class factory in a separate module and that | ||||||
| @ -975,6 +1028,7 @@ factory [can only access exported functions](#exported-symbols). | |||||||
| To correct this error, export the function. | To correct this error, export the function. | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
|  | 
 | ||||||
| // CORRECTED | // CORRECTED | ||||||
| export function myStrategy() { ... } | export function myStrategy() { ... } | ||||||
| 
 | 
 | ||||||
| @ -983,6 +1037,7 @@ export function myStrategy() { ... } | |||||||
|     { provide: MyStrategy, useFactory: myStrategy } |     { provide: MyStrategy, useFactory: myStrategy } | ||||||
|   ] |   ] | ||||||
|   ... |   ... | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| <hr> | <hr> | ||||||
| @ -1001,6 +1056,7 @@ The compiler does not currently support [function expressions or lambda function | |||||||
| For example, you cannot set a provider's `useFactory` to an anonymous function or arrow function like this. | For example, you cannot set a provider's `useFactory` to an anonymous function or arrow function like this. | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
|  | 
 | ||||||
| // ERROR | // ERROR | ||||||
|   ... |   ... | ||||||
|   providers: [ |   providers: [ | ||||||
| @ -1008,9 +1064,13 @@ For example, you cannot set a provider's `useFactory` to an anonymous function o | |||||||
|     { provide: OtherStrategy, useFactory: () => { ... } } |     { provide: OtherStrategy, useFactory: () => { ... } } | ||||||
|   ] |   ] | ||||||
|   ... |   ... | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
|  | 
 | ||||||
| You also get this error if you call a function or method in a provider's `useValue`. | You also get this error if you call a function or method in a provider's `useValue`. | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
|  | 
 | ||||||
| // ERROR | // ERROR | ||||||
| import { calculateValue } from './utilities'; | import { calculateValue } from './utilities'; | ||||||
| 
 | 
 | ||||||
| @ -1019,12 +1079,12 @@ import { calculateValue } from './utilities'; | |||||||
|     { provide: SomeValue, useValue: calculateValue() } |     { provide: SomeValue, useValue: calculateValue() } | ||||||
|   ] |   ] | ||||||
|   ... |   ... | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| To correct this error, export a function from the module and refer to the function in a `useFactory` provider instead. | To correct this error, export a function from the module and refer to the function in a `useFactory` provider instead. | ||||||
| 
 | 
 | ||||||
| <code-example linenums="false"> | <code-example linenums="false"> | ||||||
| 
 |  | ||||||
| // CORRECTED | // CORRECTED | ||||||
| import { calculateValue } from './utilities'; | import { calculateValue } from './utilities'; | ||||||
| 
 | 
 | ||||||
| @ -1040,7 +1100,6 @@ export function someValueFactory() { | |||||||
|     { provide: SomeValue, useFactory: someValueFactory } |     { provide: SomeValue, useFactory: someValueFactory } | ||||||
|   ] |   ] | ||||||
|   ... |   ... | ||||||
| 
 |  | ||||||
| </code-example> | </code-example> | ||||||
| 
 | 
 | ||||||
| <hr> | <hr> | ||||||
| @ -1060,7 +1119,6 @@ The compiler does not support references to variables assigned by [destructuring | |||||||
| For example, you cannot write something like this: | For example, you cannot write something like this: | ||||||
| 
 | 
 | ||||||
| <code-example linenums="false"> | <code-example linenums="false"> | ||||||
| 
 |  | ||||||
| // ERROR | // ERROR | ||||||
| import { configuration } from './configuration'; | import { configuration } from './configuration'; | ||||||
| 
 | 
 | ||||||
| @ -1072,13 +1130,11 @@ const {foo, bar} = configuration; | |||||||
|     {provide: Bar, useValue: bar}, |     {provide: Bar, useValue: bar}, | ||||||
|   ] |   ] | ||||||
|   ... |   ... | ||||||
| 
 |  | ||||||
| </code-example> | </code-example> | ||||||
| 
 | 
 | ||||||
| To correct this error, refer to non-destructured values. | To correct this error, refer to non-destructured values. | ||||||
| 
 | 
 | ||||||
| <code-example linenums="false"> | <code-example linenums="false"> | ||||||
| 
 |  | ||||||
| // CORRECTED | // CORRECTED | ||||||
| import { configuration } from './configuration'; | import { configuration } from './configuration'; | ||||||
|   ... |   ... | ||||||
| @ -1087,7 +1143,6 @@ import { configuration } from './configuration'; | |||||||
|     {provide: Bar, useValue: configuration.bar}, |     {provide: Bar, useValue: configuration.bar}, | ||||||
|   ] |   ] | ||||||
|   ... |   ... | ||||||
| 
 |  | ||||||
| </code-example> | </code-example> | ||||||
| 
 | 
 | ||||||
| <hr> | <hr> | ||||||
| @ -1103,12 +1158,15 @@ You'll get an error if you reference it in the component constructor, | |||||||
| which the compiler must statically analyze. | which the compiler must statically analyze. | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
|  | 
 | ||||||
| // ERROR | // ERROR | ||||||
| @Component({ }) | @Component({ }) | ||||||
| export class MyComponent { | export class MyComponent { | ||||||
|   constructor (private win: Window) { ... } |   constructor (private win: Window) { ... } | ||||||
| } | } | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
|  | 
 | ||||||
| TypeScript understands ambiant types so you don't import them. | TypeScript understands ambiant types so you don't import them. | ||||||
| The Angular compiler does not understand a type that you neglect to export or import. | The Angular compiler does not understand a type that you neglect to export or import. | ||||||
| 
 | 
 | ||||||
| @ -1130,7 +1188,6 @@ you can finesse the problem in four steps: | |||||||
| Here's an illustrative example. | Here's an illustrative example. | ||||||
| 
 | 
 | ||||||
| <code-example linenums="false"> | <code-example linenums="false"> | ||||||
| 
 |  | ||||||
| // CORRECTED | // CORRECTED | ||||||
| import { Inject } from '@angular/core'; | import { Inject } from '@angular/core'; | ||||||
| 
 | 
 | ||||||
| @ -1146,7 +1203,6 @@ export function _window() { return window; } | |||||||
| export class MyComponent { | export class MyComponent { | ||||||
|   constructor (@Inject(WINDOW) private win: Window) { ... } |   constructor (@Inject(WINDOW) private win: Window) { ... } | ||||||
| } | } | ||||||
| 
 |  | ||||||
| </code-example> | </code-example> | ||||||
| 
 | 
 | ||||||
| The `Window` type in the constructor is no longer a problem for the compiler because it | The `Window` type in the constructor is no longer a problem for the compiler because it | ||||||
| @ -1155,7 +1211,6 @@ uses the `@Inject(WINDOW)` to generate the injection code. | |||||||
| Angular does something similar with the `DOCUMENT` token so you can inject the browser's `document` object (or an abstraction of it, depending upon the platform in which the application runs). | Angular does something similar with the `DOCUMENT` token so you can inject the browser's `document` object (or an abstraction of it, depending upon the platform in which the application runs). | ||||||
| 
 | 
 | ||||||
| <code-example linenums="false"> | <code-example linenums="false"> | ||||||
| 
 |  | ||||||
| import { Inject }   from '@angular/core'; | import { Inject }   from '@angular/core'; | ||||||
| import { DOCUMENT } from '@angular/platform-browser'; | import { DOCUMENT } from '@angular/platform-browser'; | ||||||
| 
 | 
 | ||||||
| @ -1163,7 +1218,6 @@ import { DOCUMENT } from '@angular/platform-browser'; | |||||||
| export class MyComponent { | export class MyComponent { | ||||||
|   constructor (@Inject(DOCUMENT) private doc: Document) { ... } |   constructor (@Inject(DOCUMENT) private doc: Document) { ... } | ||||||
| } | } | ||||||
| 
 |  | ||||||
| </code-example> | </code-example> | ||||||
| 
 | 
 | ||||||
| <hr> | <hr> | ||||||
| @ -1174,15 +1228,19 @@ The compiler expected a name in an expression it was evaluating. | |||||||
| This can happen if you use a number as a property name as in the following example. | This can happen if you use a number as a property name as in the following example. | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
|  | 
 | ||||||
| // ERROR | // ERROR | ||||||
| provider: [{ provide: Foo, useValue: { 0: 'test' } }] | provider: [{ provide: Foo, useValue: { 0: 'test' } }] | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| Change the name of the property to something non-numeric. | Change the name of the property to something non-numeric. | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
|  | 
 | ||||||
| // CORRECTED | // CORRECTED | ||||||
| provider: [{ provide: Foo, useValue: { '0': 'test' } }] | provider: [{ provide: Foo, useValue: { '0': 'test' } }] | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| <hr> | <hr> | ||||||
| @ -1195,7 +1253,6 @@ that you referenced in metadata. | |||||||
| The compiler can understand simple enum values but not complex values such as those derived from computed properties. | The compiler can understand simple enum values but not complex values such as those derived from computed properties. | ||||||
| 
 | 
 | ||||||
| <code-example linenums="false"> | <code-example linenums="false"> | ||||||
| 
 |  | ||||||
| // ERROR | // ERROR | ||||||
| enum Colors { | enum Colors { | ||||||
|   Red = 1, |   Red = 1, | ||||||
| @ -1210,7 +1267,6 @@ enum Colors { | |||||||
|     { provide: StrongColor, useValue: Colors.Blue }  // bad |     { provide: StrongColor, useValue: Colors.Blue }  // bad | ||||||
|   ] |   ] | ||||||
|   ... |   ... | ||||||
| 
 |  | ||||||
| </code-example> | </code-example> | ||||||
| 
 | 
 | ||||||
| Avoid referring to enums with complicated initializers or computed properties. | Avoid referring to enums with complicated initializers or computed properties. | ||||||
| @ -1228,14 +1284,18 @@ _Tagged template expressions are not supported in metadata._ | |||||||
| </div> | </div> | ||||||
| 
 | 
 | ||||||
| The compiler encountered a JavaScript ES2015 [tagged template expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_template_literals) such as, | The compiler encountered a JavaScript ES2015 [tagged template expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_template_literals) such as, | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
|  | 
 | ||||||
| // ERROR | // ERROR | ||||||
| const expression = 'funky'; | const expression = 'funky'; | ||||||
| const raw = String.raw`A tagged template ${expression} string`; | const raw = String.raw`A tagged template ${expression} string`; | ||||||
|  ... |  ... | ||||||
|  template: '<div>' + raw + '</div>' |  template: '<div>' + raw + '</div>' | ||||||
|  ... |  ... | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
|  | 
 | ||||||
| [`String.raw()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/raw) | [`String.raw()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/raw) | ||||||
| is a _tag function_ native to JavaScript ES2015. | is a _tag function_ native to JavaScript ES2015. | ||||||
| 
 | 
 | ||||||
| @ -1254,6 +1314,7 @@ This error can occur if you use an expression in the `extends` clause of a class | |||||||
| Chuck: After reviewing your PR comment I'm still at a loss. See [comment there](https://github.com/angular/angular/pull/17712#discussion_r132025495). | Chuck: After reviewing your PR comment I'm still at a loss. See [comment there](https://github.com/angular/angular/pull/17712#discussion_r132025495). | ||||||
| 
 | 
 | ||||||
| --> | --> | ||||||
|  | 
 | ||||||
| {@a binding-expresion-validation} | {@a binding-expresion-validation} | ||||||
| 
 | 
 | ||||||
|   ## Phase 3: binding expression validation |   ## Phase 3: binding expression validation | ||||||
| @ -1270,6 +1331,7 @@ Chuck: After reviewing your PR comment I'm still at a loss. See [comment there]( | |||||||
|   For example, consider the following component: |   For example, consider the following component: | ||||||
| 
 | 
 | ||||||
|   ```typescript |   ```typescript | ||||||
|  | 
 | ||||||
|   @Component({ |   @Component({ | ||||||
|     selector: 'my-component', |     selector: 'my-component', | ||||||
|     template: '{{person.addresss.street}}' |     template: '{{person.addresss.street}}' | ||||||
| @ -1277,12 +1339,15 @@ Chuck: After reviewing your PR comment I'm still at a loss. See [comment there]( | |||||||
|   class MyComponent { |   class MyComponent { | ||||||
|     person?: Person; |     person?: Person; | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|   ``` |   ``` | ||||||
| 
 | 
 | ||||||
|   This will produce the following error: |   This will produce the following error: | ||||||
| 
 | 
 | ||||||
|   ``` |   ``` | ||||||
|  | 
 | ||||||
|   my.component.ts.MyComponent.html(1,1): : Property 'addresss' does not exist on type 'Person'. Did you mean 'address'? |   my.component.ts.MyComponent.html(1,1): : Property 'addresss' does not exist on type 'Person'. Did you mean 'address'? | ||||||
|  | 
 | ||||||
|   ``` |   ``` | ||||||
| 
 | 
 | ||||||
|   The file name reported in the error message, `my.component.ts.MyComponent.html`, is a synthetic file |   The file name reported in the error message, `my.component.ts.MyComponent.html`, is a synthetic file | ||||||
| @ -1307,6 +1372,7 @@ Chuck: After reviewing your PR comment I'm still at a loss. See [comment there]( | |||||||
|   interpolation if the value of `person` is initialized as shown below: |   interpolation if the value of `person` is initialized as shown below: | ||||||
| 
 | 
 | ||||||
|   ```typescript |   ```typescript | ||||||
|  | 
 | ||||||
|   @Component({ |   @Component({ | ||||||
|     selector: 'my-component', |     selector: 'my-component', | ||||||
|     template: '<span *ngIf="person"> {{person.addresss.street}} </span>' |     template: '<span *ngIf="person"> {{person.addresss.street}} </span>' | ||||||
| @ -1314,6 +1380,7 @@ Chuck: After reviewing your PR comment I'm still at a loss. See [comment there]( | |||||||
|   class MyComponent { |   class MyComponent { | ||||||
|     person?: Person; |     person?: Person; | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|   ``` |   ``` | ||||||
| 
 | 
 | ||||||
|   Using `*ngIf` allows the TypeScript compiler to infer that the `person` used in the |   Using `*ngIf` allows the TypeScript compiler to infer that the `person` used in the | ||||||
| @ -1326,7 +1393,9 @@ Chuck: After reviewing your PR comment I'm still at a loss. See [comment there]( | |||||||
|   like `*ngIf`. This static member for `*ngIf` is: |   like `*ngIf`. This static member for `*ngIf` is: | ||||||
| 
 | 
 | ||||||
|   ```typescript |   ```typescript | ||||||
|  | 
 | ||||||
|     public static ngIfUseIfTypeGuard: void; |     public static ngIfUseIfTypeGuard: void; | ||||||
|  | 
 | ||||||
|   ``` |   ``` | ||||||
| 
 | 
 | ||||||
|   This declares that the input property `ngIf` of the `NgIf` directive should be treated as a |   This declares that the input property `ngIf` of the `NgIf` directive should be treated as a | ||||||
| @ -1346,6 +1415,7 @@ Chuck: After reviewing your PR comment I'm still at a loss. See [comment there]( | |||||||
|   is suppressed in the example by using `address!.street`. |   is suppressed in the example by using `address!.street`. | ||||||
| 
 | 
 | ||||||
|   ```typescript |   ```typescript | ||||||
|  | 
 | ||||||
|   @Component({ |   @Component({ | ||||||
|     selector: 'my-component', |     selector: 'my-component', | ||||||
|     template: '<span *ngIf="person"> {{person.name}} lives on {{address!.street}} </span>' |     template: '<span *ngIf="person"> {{person.name}} lives on {{address!.street}} </span>' | ||||||
| @ -1359,6 +1429,7 @@ Chuck: After reviewing your PR comment I'm still at a loss. See [comment there]( | |||||||
|       this.address = address; |       this.address = address; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|   ``` |   ``` | ||||||
| 
 | 
 | ||||||
|   The non-null assertion operator should be used sparingly as refactoring of the component |   The non-null assertion operator should be used sparingly as refactoring of the component | ||||||
| @ -1368,6 +1439,7 @@ Chuck: After reviewing your PR comment I'm still at a loss. See [comment there]( | |||||||
|   in the `*ngIf`as shown below: |   in the `*ngIf`as shown below: | ||||||
| 
 | 
 | ||||||
|   ```typescript |   ```typescript | ||||||
|  | 
 | ||||||
|   @Component({ |   @Component({ | ||||||
|     selector: 'my-component', |     selector: 'my-component', | ||||||
|     template: '<span *ngIf="person && address"> {{person.name}} lives on {{address.street}} </span>' |     template: '<span *ngIf="person && address"> {{person.name}} lives on {{address.street}} </span>' | ||||||
| @ -1381,6 +1453,7 @@ Chuck: After reviewing your PR comment I'm still at a loss. See [comment there]( | |||||||
|       this.address = address; |       this.address = address; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|   ``` |   ``` | ||||||
| 
 | 
 | ||||||
|   ### Disabling type checking using `$any()` |   ### Disabling type checking using `$any()` | ||||||
| @ -1394,6 +1467,7 @@ Chuck: After reviewing your PR comment I'm still at a loss. See [comment there]( | |||||||
|   by casting `person` to the `any` type. |   by casting `person` to the `any` type. | ||||||
| 
 | 
 | ||||||
|   ```typescript |   ```typescript | ||||||
|  | 
 | ||||||
|   @Component({ |   @Component({ | ||||||
|     selector: 'my-component', |     selector: 'my-component', | ||||||
|     template: '{{$any(person).addresss.street}}' |     template: '{{$any(person).addresss.street}}' | ||||||
| @ -1401,6 +1475,7 @@ Chuck: After reviewing your PR comment I'm still at a loss. See [comment there]( | |||||||
|   class MyComponent { |   class MyComponent { | ||||||
|     person?: Person; |     person?: Person; | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|   ``` |   ``` | ||||||
| 
 | 
 | ||||||
| ## Summary | ## Summary | ||||||
|  | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -45,6 +45,17 @@ describe('从对照翻译文件中采集生成字典', () => { | |||||||
| 
 | 
 | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|  |   it('处理 a 标签包裹的单行翻译文本', () => { | ||||||
|  |     const result = gatherTranslations(` | ||||||
|  |     <a>a</a> | ||||||
|  | 
 | ||||||
|  |     <a>一</a> | ||||||
|  |      | ||||||
|  |     `);
 | ||||||
|  |     expect(result).eql([{original: '<a>a</a>', translation: '<a>一</a>'}]); | ||||||
|  | 
 | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|   it('从真实的文件中采集(测试)', function () { |   it('从真实的文件中采集(测试)', function () { | ||||||
|     const fs = require('fs'); |     const fs = require('fs'); | ||||||
|     const content = fs.readFileSync(dirs.content + 'guide/forms.md', 'utf-8'); |     const content = fs.readFileSync(dirs.content + 'guide/forms.md', 'utf-8'); | ||||||
|  | |||||||
| @ -2,11 +2,10 @@ import * as globby from 'globby'; | |||||||
| import { DictEntry } from './dict-entry'; | import { DictEntry } from './dict-entry'; | ||||||
| import { | import { | ||||||
|   isNotCnPages, |   isNotCnPages, | ||||||
|   isOnlyTag, |   isOnlyBeginTag, | ||||||
|   normalizeLines, |   normalizeLines, | ||||||
|   originalIsNotChinese, |   originalIsNotChinese, | ||||||
|   originalIsNotTag, |   originalIsNotOnlyBeginTag, | ||||||
|   originalIsOnlyTag, |  | ||||||
|   translationHasNotCodeExample, |   translationHasNotCodeExample, | ||||||
| } from './utils'; | } from './utils'; | ||||||
| 
 | 
 | ||||||
| @ -30,11 +29,11 @@ export function gatherTranslations(text: string): DictEntry[] { | |||||||
|     if (isTranslation(translation)) { |     if (isTranslation(translation)) { | ||||||
|       const original = purifyText(lines[i - 1]); |       const original = purifyText(lines[i - 1]); | ||||||
|       // 对于包裹在 html tag 中的翻译文本进行特殊处理
 |       // 对于包裹在 html tag 中的翻译文本进行特殊处理
 | ||||||
|       if (isOnlyTag(original)) { |       if (isOnlyBeginTag(original)) { | ||||||
|         const prevTag = lines[i - 4].trim(); |         const prevBeginTag = lines[i - 4].trim(); | ||||||
|         const prevEndTag = lines[i - 2].trim(); |         const prevEndTag = lines[i - 2].trim(); | ||||||
|         const thisEndTag = lines[i + 1].trim(); |         const thisEndTag = lines[i + 1].trim(); | ||||||
|         if (original === prevTag && prevEndTag === thisEndTag) { |         if (original === prevBeginTag && prevEndTag === thisEndTag) { | ||||||
|           result.push({ |           result.push({ | ||||||
|             original: lines[i - 3], |             original: lines[i - 3], | ||||||
|             translation: lines[i], |             translation: lines[i], | ||||||
| @ -49,8 +48,7 @@ export function gatherTranslations(text: string): DictEntry[] { | |||||||
|     .filter(isNotCnPages) |     .filter(isNotCnPages) | ||||||
|     .filter(translationHasNotCodeExample) |     .filter(translationHasNotCodeExample) | ||||||
|     .filter(originalIsNotChinese) |     .filter(originalIsNotChinese) | ||||||
|     .filter(originalIsNotTag) |     .filter(originalIsNotOnlyBeginTag) | ||||||
|     .filter(originalIsOnlyTag) |  | ||||||
|     .map(purifyEntry); |     .map(purifyEntry); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -4,7 +4,7 @@ import { kernelText, lookup } from './translate'; | |||||||
| 
 | 
 | ||||||
| describe('根据字典进行翻译', () => { | describe('根据字典进行翻译', () => { | ||||||
|   it('抽取核心字符', function () { |   it('抽取核心字符', function () { | ||||||
|     expect(kernelText(' # Forms   ABC. ')).eql('FormsABC'); |     expect(kernelText(' # Forms   ABC. ')).eql('#FormsABC'); | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|   it('查字典', () => { |   it('查字典', () => { | ||||||
|  | |||||||
| @ -17,7 +17,6 @@ export function lookup(english: string, filename: RegExp = /.*/): DictEntry[] { | |||||||
| export function kernelText(text: string): string { | export function kernelText(text: string): string { | ||||||
|   return text |   return text | ||||||
|     .replace(/[\s\n]+/g, '') |     .replace(/[\s\n]+/g, '') | ||||||
|     .replace(/^#+/g, '') |  | ||||||
|     .replace(/\.$/g, '') |     .replace(/\.$/g, '') | ||||||
|     .trim(); |     .trim(); | ||||||
| } | } | ||||||
|  | |||||||
| @ -61,11 +61,7 @@ def`); | |||||||
|     expect(lines).eql(` |     expect(lines).eql(` | ||||||
|     a |     a | ||||||
| 
 | 
 | ||||||
|     <h3 id="abc"> |     <h3 id="abc">line</h3> | ||||||
| 
 |  | ||||||
|     line |  | ||||||
| 
 |  | ||||||
|     </h3> |  | ||||||
| 
 | 
 | ||||||
|     b |     b | ||||||
| `);
 | `);
 | ||||||
|  | |||||||
| @ -17,12 +17,12 @@ export function originalIsNotTag(entry: DictEntry): boolean { | |||||||
|   return !isTagLine(entry.original); |   return !isTagLine(entry.original); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export function isOnlyTag(text: string) { | export function isOnlyBeginTag(text: string) { | ||||||
|   return /^\s*<\w+>\s*$/.test(text); |   return /^\s*<\w+>\s*$/.test(text); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export function originalIsOnlyTag(entry: DictEntry): boolean { | export function originalIsNotOnlyBeginTag(entry: DictEntry): boolean { | ||||||
|   return !isOnlyTag(entry.original); |   return !isOnlyBeginTag(entry.original); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export function isNotImg(entry: DictEntry): boolean { | export function isNotImg(entry: DictEntry): boolean { | ||||||
| @ -53,10 +53,10 @@ export function normalizeLines(text: string): string { | |||||||
|   text = text.replace(hxPattern, '\n$1\n\n'); |   text = text.replace(hxPattern, '\n$1\n\n'); | ||||||
|   const leadHxPattern = /^( *#.*)\n/g; |   const leadHxPattern = /^( *#.*)\n/g; | ||||||
|   text = text.replace(leadHxPattern, '$1\n\n'); |   text = text.replace(leadHxPattern, '$1\n\n'); | ||||||
|   const oneLinePairedTagPattern = /\n( *)<(p|code-example|div)( ?[^> \n]*)>([^<\n]*)<\/\2>( *)\n/g; |   const oneLinePairedTagPattern = /\n( *)<(p|code-example|div|h\d+|a)( ?[^> \n]*)>([^<\n]*)<\/\2>( *)\n/g; | ||||||
|   text = text.replace(oneLinePairedTagPattern, '\n\n$1<$2$3>$4</$2>$5\n\n'); |   text = text.replace(oneLinePairedTagPattern, '\n\n$1<$2$3>$4</$2>$5\n\n'); | ||||||
|   const oneLineHnTagPattern = /\n( *)<(h\d+|th|td)( ?[^> \n]*)>([^<\n]*)<\/\2>( *)\n/g; |   const oneLineThTdTagPattern = /\n( *)<(th|td)( ?[^> \n]*)>([^<\n]*)<\/\2>( *)\n/g; | ||||||
|   text = text.replace(oneLineHnTagPattern, '\n\n$1<$2$3>\n\n$1$4\n\n$1</$2>$5\n\n'); |   text = text.replace(oneLineThTdTagPattern, '\n\n$1<$2$3>\n\n$1$4\n\n$1</$2>$5\n\n'); | ||||||
|   const oneLineCommentPattern = /\n( *)(<!--.*-->)( *)\n/g; |   const oneLineCommentPattern = /\n( *)(<!--.*-->)( *)\n/g; | ||||||
|   text = text.replace(oneLineCommentPattern, '\n\n$1$2$3\n\n'); |   text = text.replace(oneLineCommentPattern, '\n\n$1$2$3\n\n'); | ||||||
|   const atTagCommentPattern = /\n( *)({@a.*})( *)\n/g; |   const atTagCommentPattern = /\n( *)({@a.*})( *)\n/g; | ||||||
| @ -66,8 +66,8 @@ export function normalizeLines(text: string): string { | |||||||
|   const multiLinePairedTagPattern = /\n( *)<(header|p)( *[^> \n]*)>\n*(.*?)\n*( *)<\/\2>( *)\n/g; |   const multiLinePairedTagPattern = /\n( *)<(header|p)( *[^> \n]*)>\n*(.*?)\n*( *)<\/\2>( *)\n/g; | ||||||
|   text = text.replace(multiLinePairedTagPattern, '\n\n$1<$2$3>\n\n$4\n\n$5</$2>$6\n\n'); |   text = text.replace(multiLinePairedTagPattern, '\n\n$1<$2$3>\n\n$4\n\n$5</$2>$6\n\n'); | ||||||
| 
 | 
 | ||||||
|   const multiLineCodePattern = /\n( *)```( *)\n/g; |   const multiLineCodePattern = /\n( *)```(\w*)( *)\n/g; | ||||||
|   text = text.replace(multiLineCodePattern, '\n\n$1```$2\n\n'); |   text = text.replace(multiLineCodePattern, '\n\n$1```$2$3\n\n'); | ||||||
| 
 | 
 | ||||||
|   const multipleBlankLinePattern = /\n\s*\n+/g; |   const multipleBlankLinePattern = /\n\s*\n+/g; | ||||||
|   text = text.replace(multipleBlankLinePattern, '\n\n'); |   text = text.replace(multipleBlankLinePattern, '\n\n'); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user