- Advanced TypeScript Programming Projects
- Peter O'Hanlon
- 728字
- 2021-06-24 13:27:09
Mapping our markdown tag types to HTML tag types
In our requirements, we set out a master list of tags that our parser is going to handle. In order to identify these tags, we are going to add an enumeration consisting of the tags we are making available to our users:
enum TagType {
Paragraph,
Header1,
Header2,
Header3,
HorizontalRule
}
From our requirements, we also know that we need to translate between these tags and their equivalent opening and closing HTML tags. The way that we are going to do this is to map tagType to an equivalent HTML tag. To do this, we are going to create a class that has the sole responsibility of handling this mapping for us. The following code shows this:
class TagTypeToHtml {
private readonly tagType : Map<TagType, string> = new Map<TagType, string>();
constructor() {
this.tagType.set(TagType.Header1, "h1");
this.tagType.set(TagType.Header2, "h2");
this.tagType.set(TagType.Header3, "h3");
this.tagType.set(TagType.Paragraph, "p");
this.tagType.set(TagType.HorizontalRule, "hr")
}
}
We also need a way to retrieve opening and closing tags from this class. We're going to start by creating a method to get the opening tag from tagType, as follows:
public OpeningTag(tagType : TagType) : string {
let tag = this.tagType.get(tagType);
if (tag !== null) {
return `<${tag}>`;
}
return `<p>`;
}
This method is pretty straightforward. It starts by trying to get tagType from the map. With the code we currently have, we will always have an entry in the map, but we could extend the enumeration in the future and forget to add the tag to the list of tags. That is why we check to see if the tag is present; if it is, we return the tag enclosed in <>. If the tag is not present, we return a paragraph tag as a default.
Now, let's look at ClosingTag:
public ClosingTag(tagType : TagType) : string {
let tag = this.tagType.get(tagType);
if (tag !== null) {
return `</${tag}>`;
}
return `</p>`;
}
Looking at these two methods, we can see that they are almost identical. When we think about the problem of creating our HTML tag, we realize that the only difference between an opening and a closing tag is that the closing tag has a / in it. With that in mind, we can change the code to use a helper method that accepts whether the tag starts with < or </:
private GetTag(tagType : TagType, openingTagPattern : string) : string {
let tag = this.tagType.get(tagType);
if (tag !== null) {
return `${openingTagPattern}${tag}>`;
}
return `${openingTagPattern}p>`;
}
All that remains is for us to add methods to retrieve the opening and closing tags:
public OpeningTag(tagType : TagType) : string {
return this.GetTag(tagType, `<`);
}
public ClosingTag(tagType : TagType) : string {
return this.GetTag(tagType, `</`);
}
Pulling this all together, the code for our TagTypeToHtml class now looks like this:
class TagTypeToHtml {
private readonly tagType : Map<TagType, string> = new Map<TagType, string>();
constructor() {
this.tagType.set(TagType.Header1, "h1");
this.tagType.set(TagType.Header2, "h2");
this.tagType.set(TagType.Header3, "h3");
this.tagType.set(TagType.Paragraph, "p");
this.tagType.set(TagType.HorizontalRule, "hr")
}
public OpeningTag(tagType : TagType) : string {
return this.GetTag(tagType, `<`);
}
public ClosingTag(tagType : TagType) : string {
return this.GetTag(tagType, `</`);
}
private GetTag(tagType : TagType, openingTagPattern : string) : string {
let tag = this.tagType.get(tagType);
if (tag !== null) {
return `${openingTagPattern}${tag}>`;
}
return `${openingTagPattern}p>`;
}
}
This handy acronym serves to guide us on how to structure classes and the most important part, in my opinion, is the Single Responsibility Principle, which states that a class should do one thing and one thing only. While I would certainly recommend reading about this topic (and we will touch on other aspects of it as we progress), in my opinion, the most important part of SOLID design is that classes are responsible for one thing and one thing only; everything else flows out of that principle. Classes that only do one thing are generally much easier to test and they are a lot easier to understand. That does not mean that they should only have one method. They can have many methods, as long as they are all related to the purpose of the class. We will cover this topic again and again throughout the book because it is so important.
- Implementing Cisco UCS Solutions
- Windows Vista基礎與應用精品教程
- 鴻蒙生態:開啟萬物互聯的智慧新時代
- 白話區塊鏈
- 精解Windows 8
- Mobile First Design with HTML5 and CSS3
- Windows 7中文版從入門到精通(修訂版)
- AWS Development Essentials
- 注冊表應用完全DIY
- Windows 7應用入門與技巧
- 云原生落地:產品、架構與商業模式
- Java EE 8 High Performance
- Less Web Development Essentials
- Instant Getting Started with VMware Fusion
- 數字系統設計與VHDL