整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          在Django中使用Markdown

          為開發人員,我們依賴于靜態分析工具來檢查、lint(分析)和轉換我們的代碼。我們使用這些工具來幫助我們提高生產效率并生成更好的代碼。然而,當我們使用markdown編寫內容時,可用的工具就很少。

          在本文中,我們將介紹如何開發一個Markdown擴展來解決在使用Markdown管理Django站點中的內容時遇到的挑戰。

          你認為他們有linter嗎?

          照片來自Pexels,由mali maeder拍攝

          問題

          像每個網站一樣,我們在主頁、FAQ部分和“關于”頁面等地方都有不同類型的(大部分)靜態內容。很長一段時間以來,我們都是在Django模板中直接管理這些內容的。

          當我們最終決定是時候將這些內容從模板轉移到數據庫中時,我們認為最好使用Markdown。從Markdown生成HTML更安全,它提供了一定程度的控制和一致性,并且對于非技術用戶來說更容易處理。隨著我們轉移過程的進展,我們注意到我們遺漏了一些東西:

          內部鏈接

          當URL更改時,鏈接到內部頁面的鏈接可能會中斷。在Django模板和視圖中,我們使用了reverseand {% url %},但是這在普通的Markdown中是不可用的。

          在不同環境之間進行復制

          絕對內部連接不能在不同環境之間進行復制。這可以使用相對鏈接來解決,不過目前沒有開箱即用的增強這一點的方法。

          無效鏈接

          無效鏈接會損害用戶體驗,并導致用戶質疑整個內容的可靠性。這并不是Markdown獨有的東西,只不過HTML模板是由對URL有一定了解的開發人員維護的。另一方面,Markdown文檔是為非技術寫作人員設計的。

          前期工作

          當我研究這個問題時,我搜索了Python linters、Markdown預處理器和擴展來幫助生成更好的Markdown。結果都不是很好。一個引人注目的方法是使用Django模板來生成Markdown文檔。

          使用Django模板預處理Markdown

          使用Django模板,你可以使用諸如url之類的模板標記來反向查詢URL名稱,并配合使用條件、變量、日期格式和所有其他Django模板特性。這種方法本質上是使用Django模板作為Markdown文檔的預處理程序。

          我個人認為這可能不是非技術作家的最佳解決方案。另外,我擔心提供對Django模板標記的訪問可能是危險的。

          使用 Markdown

          對這個問題有了更好的理解之后,我們準備在Python中更深入地研究Markdown。

          將Markdown轉換為HTML

          要在Python中開始使用Markdown,我們先安裝markdown包:

          接著,創建一個Markdown對象并使用其函數將一些Markdown轉換成HTML:

          你現在可以在你的模板中使用這個HTML代碼片段。

          使用Markdown擴展

          基本的Markdown處理器提供了生成HTML內容的基本要素。對于更“新奇”的選項,Python markdown包包含了一些內置擴展。一個流行的擴展是“extra”擴展,除了其他東西之外,它增加了對隔離代碼塊的支持:

          為了使用我們獨特的Django功能擴展Markdown,我們將開發自己的擴展。

          創建一個Markdown擴展來處理內聯鏈接

          如果你查看源代碼,你將看到要將markdown轉換為HTML, Markdown會使用多種不同的處理器。一種類型的處理器是內聯處理器。內聯處理器會匹配特定的內聯模式,如鏈接、反引號、粗體文本和帶下劃線的文本,并將它們轉換為HTML。

          我們的Markdown擴展的主要目的是驗證和轉換鏈接。因此,我們最感興趣的內聯處理器是LinkInlineProcessor。這個處理器以[Haki的網站](https://hakibenito.com)的形式獲取markdown ,解析它并返回一個包含鏈接和文本的元組。

          為了擴展該功能,我們擴展了LinkInlineProcessor并創建了一個Markdown.Extension, 我們用它來處理鏈接:

          我們來將這段代碼分解一下::

          • DjangoUrlExtension擴展注冊了一個名為DjangoLinkInlineProcessor的內聯鏈接處理器。這個處理器將取代任何其他現有的鏈接處理器。

          • 內聯處理器DjangoLinkInlineProcessor擴展了內置的LinkInlineProcessor,并在它處理的每個鏈接上調用clean_link函數。

          • clean_link函數接收一個鏈接和一個域名,并返回一個轉換后的鏈接。這就是我們要插入我們的實現的地方。

          如何獲得網站域名


          要識別到你自己網站的鏈接,你必須知道你的網站的域名。如果你正在使用Django的sites框架,那么你可以使用它來獲取當前域名。


          我沒有把它包含在我的實現中,因為我們沒有使用sites框架。相反,我們在Django設置中設置了一個變量。


          獲取當前域名的另一種方法是使用HttpRequest對象。如果內容只在你自己的站點中被編輯,你可以嘗試從請求對象中插入站點域名。這可能需要對你的實現進行一些更改。

          要使用該擴展,請在初始化一個新的Markdown實例時添加它:

          太好了,這個擴展已經被使用了,我們準備進入有趣的部分了!

          驗證和轉換Django鏈接

          既然我們得到了在所有鏈接上調用clean_link的擴展,那我們可以來實現我們的驗證和轉換邏輯。

          驗證mailto鏈接

          要開始工作,我們將從一個簡單的驗證開始。mailto鏈接對于使用預定義的收件人地址、主題甚至消息正文打開用戶的電子郵件客戶端非常有用。

          一個常見的mailto鏈接是這樣的:

          這個鏈接將打開你的電子郵件客戶端,并設置成撰寫一封主題行為“我需要幫助!”的新電子郵件給“support@service.com”。

          mailto鏈接不一定非要包含電子郵件地址。如果你看一看這篇文章底部的“分享”按鈕,你會發現像這樣的一個mailto鏈接:

          這個mailto鏈接沒有包含收件人,僅包含了主題行和消息正文。

          既然我們已經很好地理解了mailto鏈接是什么樣子的,我們就可以向clean_link函數添加第一個驗證:

          為了驗證mailto鏈接,我們向clean_link中添加了以下代碼:

          • 檢查鏈接是否以mailto:開頭,以識別相關鏈接。

          • 使用正則表達式將鏈接分割到它的組件。

          • 從mailto鏈接中刪除實際的電子郵件地址,并使用Django的EmailValidator驗證它。

          注意,我們還添加了一種名為InvalidMarkdown的新異常類型。我們定義了自己的自定義異常類型,以將它與markdown本身所引發的其他錯誤區分開來。

          自定義錯誤類

          我曾經寫過關于自定義錯誤類的文章,為什么它們是有用的,以及你什么時候應該使用它們。

          在我們繼續之前,讓我們添加一些測試,看看它的實際效果:

          太棒了!按預期的運行了。

          處理內部和外部鏈接

          既然我們已經了解了mailto鏈接,我們也可以處理其他類型的鏈接:

          外部鏈接

          • 我們的Django應用程序外部的鏈接。

          • 必須包含一個頁面跳轉協議(scheme):http或https。

          • 理想情況下,我們還希望確保這些鏈接沒有被破壞,但我們現在不會這樣做。

          內部鏈接

          • 到我們的Django應用程序中的頁面的鏈接。

          • 鏈接必須是相對的:這將允許我們在不同環境之間移動內容。

          • 使用Django的URL名稱而不是一個URL路徑:這將允許我們安全地來回移動視圖,而不必擔心markdown內容中的失效鏈接。

          • 鏈接可能包含查詢參數(?)和片段(#)。

          SEO

          從SEO的角度來看,公共URL不應該改變。當他們這樣做的時候,你應該使用重定向正確地處理它,否則你可能會受到搜索引擎的懲罰。

          有了這個需求列表,我們就可以開始工作了。

          解析URL名稱

          要鏈接到內部頁面,我們希望編寫者提供一個URL名稱,而不是URL路徑。例如,假設我們有這個視圖:

          這個頁面的URL路徑是https://example.com/, URL名稱是home。我們想要在我們的markdown鏈接中使用這個URL名稱home,就像這樣:

          這將渲染到:

          我們還想支持查詢參數和散列:

          這將渲染到以下HTML:

          在使用URL名稱時,如果我們更改了URL路徑,內容中的鏈接將不會被破壞。要檢查作者提供的href是否是一個有效的url_name,我們可以嘗試reverse它:

          URL名稱“home”指向URL路徑“/”。當沒有匹配項時,將會引發一個異常:

          在我們繼續之前,當URL名稱包含查詢參數或散列時,會發生什么:

          這是有意義的,因為查詢參數和散列不是URL名稱的一部分。

          要使用reverse并支持查詢參數和散列,我們首先需要清除值。然后,檢查它是一個有效的URL名稱,并返回包含查詢參數和散列的URL路徑,如果提供了的話:

          這個代碼段使用一個正則表達式來以?或#的出現對href進行分割,并返回各部分。

          請確保它可以工作:

          太了不起了!作者們現在可以在Markdown中使用URL名稱了。它們還可以包括要添加到該URL的查詢參數和片段。

          處理外部鏈接

          要正確處理外部鏈接,我們需要檢查兩件事:

          1.外部鏈接總是提供一個跳轉協議,http:或者https:。

          2.阻止到我們自己網站的絕對鏈接。內部鏈接應該使用URL名稱。

          到目前為止,我們已經處理了URL名稱和mailto鏈接。如果我們通過了這兩個檢查,這意味著href是一個URL。讓我們從檢查鏈接是否是鏈接到我們自己的網站開始:

          函數urlparse會返回一個命名元組,該元組包含URL的不同部分。如果netloc屬性等于site_domain,那么該鏈接就確實是一個內部鏈接。

          如果URL實際上是內部的,我們就需要終止。但是,請記住,作者們不一定是技術人員,因此我們希望幫助他們,并提供一個有用的錯誤消息。我們要求該內部鏈接使用URL名稱而不是URL路徑,所以最好讓作者們知道他們提供的路徑的URL名稱。

          要獲得一個URL路徑的URL名稱,Django為我們提供了一個名為resolve的函數:

          當找到匹配項時,resolve會返回一個ResolverMatch對象,其中包含URL名稱和其他信息。當沒有找到匹配項時,它就會引發一個錯誤:

          這實際上就是Django在底層所做的工作,用來確定在一個新請求到來時執行哪個視圖函數。

          為了給作者們提供更好的錯誤信息,我們可以使用來自ResolverMatch對象的URL名稱:

          當我們識別出內部鏈接時,我們要處理兩種情況:

          • 我們沒有識別出這個URL:這個URL很可能是不正確的。請作者檢查該URL是否有錯誤。

          • 我們識別出了這個URL: 這個URL是正確的,所以就告訴作者應該使用什么URL名稱。

          我們來實際地看一下它:

          漂亮!外部鏈接被接受,內部鏈接被拒絕,并帶有一個有用的消息。

          要求跳轉協議

          我們要做的最后一件事是確保外部鏈接包含一個跳轉協議,要么是http:,要么是https:。讓我們將這最后一部分添加到函數clean_link:

          使用解析后的URL,我們可以很容易地檢查跳轉協議。讓我們確保它正在工作:

          我們向這個函數提供了一個沒有跳轉協議的鏈接,但是它運行失敗了,并顯示了一條有用的消息。太酷了!

          整合代碼

          這是clean_link函數的全部代碼:

          要了解所有這些特性的一個實際用例是什么樣子的,請看下面的內容:

          這將產生以下HTML:

          不錯!

          結論

          我們現在有一個很不錯的擴展,它可以驗證和轉換Markdown文檔中的鏈接!現在,在不同環境之間移動文檔和保持內容整潔要容易多了,最重要的是,可以保持正確和最新!

          源碼

          你可以在這個gist中找到全部源代碼。(地址:https://gist.github.com/hakib/73fccc340e855bb65f42197e298c0c7d )

          題外話

          本文中所描述的功能對我們很有用,但是你可能需要根據自己的需求對它進行調整。

          如果你需要一些想法,那么除了這個擴展之外,我們還創建了一個markdown Preprocessor,它允許作者們在markdown中使用常量。例如,我們定義了一個名為SUPPORT_EMAIL的常量,我們像這樣使用它:

          該預處理程序將用我們定義的文本替換字符串$SUPPORT_EMAIL,然后才渲染Markdown。

          英文原文:https://hakibenita.com/django-markdown
          譯者:Nothing

          站的建站流程

          頁面圖例

          網頁的結構

          WEB標準

          WEB標準是網頁制作的標準,它不是一個標準,它是根據網頁的不同組成部分生成的一系列標準。這些標準大部分由W3C起草發布,也有部分標準由ECMA起草發布

          (1)W3C( World Wide Web Consortium )萬維網聯盟,創建于1994年是Web技術領域最具權威和影響力的國際中立性技術標準機構;是專門負責網絡標準制定的非贏利組織。制定了結構標準和樣式標準; (2)ECMA:歐洲電腦網商聯合會(廠商協會),制定了行為標準;

          計算機語言

          HTML

          HTML 指的是超文本標記語言 (Hyper Text Markup Language) www萬維網的描述性語言。 XHTML指可擴展超文本標記語言(標識語言)(EXtensible HyperText Markup Language)是一種置標語言,表現方式與超文本標記語言(HTML)類似,不過語法上更加嚴格。 HTML5指的是HTML的第五次重大修改(第5個版本)

          HTML發展

          編輯器

          建立站點

          規劃網站的所有內容和代碼
          整合資源

          文件的命名規范

          • 小寫英文字母、數字、下劃線的組合,
          • 其中不得包含漢字、空格和特殊字符;
          • 必須以英文字母開頭。

          HTML開始

          1:HTML架構

          <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

          有三種:Strict(嚴格型)、

          Trasitional(過渡型)、

          Frameset(框架型)

          2:HTML5基本結構

          3:HTML語言

          • HTML語言組成

          (1)標簽

          txt 寫在尖角號<>里的第一個單詞,叫做標記,也叫做標簽,也稱作元素;

          (2)屬性

          標記和屬性用空格隔開,屬性和屬性值用等號連接,屬性值必須放在雙引號內 一個標記可以有多個屬性,屬性和屬性之間用空格隔開,屬性不分先后順序

          • HTML語法

          (1)常規標記(雙標記): <標記名稱 屬性1名="屬性1值" 屬性2名="屬性2值" ………… >

          (2)空標記(單標記):<標記名 屬性1名="屬性1值" />

          常用標簽

          1 : 文本標題標簽

          文本標題共有6個(h1-h6)
          <h1>一級標題</h1>(唯一性,放網站LOGO)
          <h2>二級標題</h2>
          ...
          <h6>六級標題</h6>

          2:字體傾斜&加粗標記

          文本傾斜:
              <i></i>
              <em></em>
          
          文本加粗:
              <b></b>
              <strong></strong>

          3:下劃線

          <u></u>

          4 : 換行&水平線

          <br>
          <hr>

          5:上標&下標

          <sup></sup>
          <sub></sub>

          6 : 段落標記

          <p></p>

          7 : 字符 ( 小段文本 )

          <span></span>

          8 : (1) 無序列表

          <ul>
               <li>列表項內容</li>
               <li>列表項內容</li>
               <li>列表項內容</li>
                 ........   
          </ul>

          ? (2)有序列表

          <ol>
              <li>列表項內容</li>
              <li>列表項內容</li>
              <li>列表項內容</li>
              ........   
          </ol>

          type:規定列表中的列表項目的項目符號的類型 語法:<ol type=“ a"></ol> 1 數字順序的有序列表(默認值)(1, 2, 3, 4)。 a 字母順序的有序列表,小寫(a, b, c, d)。 A 字母順序的有序列表,大寫(A,B,C,D) i 羅馬數字,小寫(i, ii, iii, iv)。 I 羅馬數字,大寫(i, ii, iii, iv)。 start 屬性規定有序列表的開始點。(start的屬性值必須是數字) 語法:<ol start="5"></ol>

          ? (3)自定義列表

          <dl>
               dt></dt>
               <dd></dd>
          </dl>

          9 : 超鏈接

          <a></a>
              屬性:
                  href = 'url'
                  target = "_blank  /  _self";
                  title = '文本提示'
          
              拓展:
                  rel = 'nofollow';

          10 : 圖片

          <img>
              屬性:
                  src = 'url';
                  alt = ' 標簽 實例 帶有指定替代文本的圖像'  
                  title = '文本提示'
                  width = ''
                  height = ''
                  border = ''

          圖片 title 和 alt區別:

          alt:

          1、alt屬性是考慮到不支持圖像顯示或者圖像顯示被關閉的瀏覽器的用戶,

          以及視覺障礙的用戶和使用屏幕閱讀器的用戶。當圖片不顯示的時候,圖片的替換文字。

          2、alt屬性值的長度必須少于100個英文字符

          3、alt屬性是img標簽的必須屬性,如果沒有特別意義的圖片,可以寫alt=""

          4、alt屬性是搜索引擎判斷圖片與文字是否相關的重要依據, alt屬性添加到img主要的目的才是為了SEO

          title:

          1、title屬性并不是必須的。

          2、title屬性規定元素的額外信息,有視覺效果, 當鼠標放到文字或是圖片上時有文字顯示。

          3、title屬性并不作為搜索引擎抓取圖片的參考, 更多傾向于用戶體驗的考慮。

          11 : 相對路徑

          (同級)

          1)當當前文件與目標文件在同一目錄下, 直接書寫目標文件的文件名+擴展名;

          (上級找下級)

          2)當當前文件與目標文件所處的文件夾在同一目錄下,寫法如下:

          文件夾名/目標文件全稱+擴展名;

          (下級找上級)

          3)當當前文件所處的文件夾和目標文件在同一目錄下,寫法如下:

          ../目標文件文件名+擴展名;

          12 : DIV

          13 : HTML注釋

          <!-- 注釋 -->

          表格

          1 : 表格基本結構

          <table>
              <tr>
                  <td></td>
                  <td></td>
              </tr>
          </table>
          
          <!-- 
              table 為表格
              tr 行
              td 列(每一個單元格)
          -->

          2:表格的html屬性

          1)width="表格的寬度"
          2)height="表格的高度"
          3)border="表格的邊框"
          4)bordercolor="邊框色"
          5)cellspacing="單元格與單元格之間的間距"
          6)cellpadding=“單元格與內容之間的距離"
          7)align="表格水平對齊方式"
             取值:left、right、center、
             valign=“垂直對齊” top\bottom\middle
          8)合并單元格屬性:(td)
            合并列: colspan=“所要合并的單元格的列數"
            合并行: rowspan=“所要合并單元格的行數”

          3 : 數據行分組

          <thead></thead>
          <tbody></tbody>
          <tfoot></tfoot>

          4 : 數據列分組

          <colgroup span="value"></colgroup>
          <!--span屬性為把幾列分為一組-->

          5 : 列標題

          <th></th>

          6: 表格標題

          <caption></caption>

          7: 表格屬性

          1、單元格間距:border-spacing:value; 說明:單元格間距(該屬性必須給table添加) 表示單元格邊框之間的距離, 不可取負值 2、合并相鄰單元格邊框:border-collapse:separate/collapse; 說明:合并相鄰單元格邊框 (該屬性必須給table添加) separate(邊框分開)默認值; collapse(邊框合并) 3、無內容時單元格的設置:empty-cells:show/hide; 說明:定義當單元格無內容時,是否顯示該單元格的邊框區域;show:顯示 ;hide:隱藏; 4、顯示單元格行和列的算法(加快運行的速度): table-layout:auto/fixed;



          本文轉自知乎號:千鋒HTML5學院

          篇文章介紹了<!--...--> 注釋標簽,我個人感覺很容易理解,在日常編碼中,大多數編輯器都有注釋標簽的快捷鍵,如sublime或VS code里在html代碼里,選中想要注釋掉的代碼后,直接按ctrl+/即可。幾乎不用手動輸入了。還是很方便的。

          這篇我寫<!DOCTYPE>標簽,說起來這個標簽,很常見,因為它會出現在每一個httml文檔的最開頭,然而,我們很少去重視它,為什么呢?

          說到這個標簽,我不得不說起html的版本歷史了。

          在大約10年前吧,html5應用還不如今天這么廣泛吧,于是當時的文檔類型聲明如下

          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
          

          很長,也很難記,由于我入行晚,懂得這玩意就只是一個聲明了,比如strict表示嚴格模式。其他的我也不想知道了。

          當然html版本的規范從4到5的過渡經歷了太多年,因為要考慮老瀏覽器的兼容性,再加上前期移動設備配置低,不支持較為復雜的媒體元素。于是,一些資歷深的前端開發人員,面對這么長的代碼還是有很長一段時間。

          當然,9102年都快過完了,我們這邊已經不需要再考慮這些了,于是,我直接就用html5了。

          然后聲明文檔給格式,就變得很簡單了。

          <!DOCTYPE html>
          

          最開始我是使用sublime生成的模板練習的,然后,犯懶,直接輸入了<html>就出來下面的代碼:

          <!DOCTYPE html>
          <html>
          <head>
          	<title></title>
          </head>
          <body>
          </body>
          </html>
          

          然后就開始進行填充了。

          直到今天我才注意到原來<!DOCTYPE html>是單獨的一行,與下方<html></html>是兩碼事。

          所以,我重新看了下書上的強調內容:

          1. <!DOCTYPE> 聲明必須是 HTML 文檔的第一行,位于 <html> 標簽之前,沒有結束標簽,對大小寫不敏感。
          2. <!DOCTYPE> 聲明不是 HTML 標簽;它是指示 web 瀏覽器關于頁面使用哪個 HTML 版本進行編寫的指令。
          3. 在 HTML 4.01 中,<!DOCTYPE> 聲明引用 DTD(文檔類型定義),因為 HTML 4.01 基于 SGML(標準通用標記語言))。DTD 規定了標記語言的規則,這樣瀏覽器才能正確地呈現內容。
          4. HTML5 不基于 SGML,所以不需要引用 DTD。

          關于SGML,參見https://wiki.mbalib.com/wiki/SGML

          常用的 DOCTYPE 聲明

          HTML 5

          <!DOCTYPE html>
          

          HTML 4.01 Strict

          該 DTD 包含所有 HTML 元素和屬性,但不包括展示性的和棄用的元素(比如 font)。不允許框架集(Framesets)。

          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

          HTML 4.01 Transitional

          該 DTD 包含所有 HTML 元素和屬性,包括展示性的和棄用的元素(比如 font)。不允許框架集(Framesets)。

          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
          "http://www.w3.org/TR/html4/loose.dtd">
          

          HTML 4.01 Frameset

          該 DTD 等同于 HTML 4.01 Transitional,但允許框架集內容。

          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" 
          "http://www.w3.org/TR/html4/frameset.dtd">
          

          XHTML 1.0 Strict

          該 DTD 包含所有 HTML 元素和屬性,但不包括展示性的和棄用的元素(比如 font)。不允許框架集(Framesets)。必須以格式正確的 XML 來編寫標記。

          <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
          

          XHTML 1.0 Transitional

          該 DTD 包含所有 HTML 元素和屬性,包括展示性的和棄用的元素(比如 font)。不允許框架集(Framesets)。必須以格式正確的 XML 來編寫標記。

          <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "
          http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
          

          XHTML 1.0 Frameset

          該 DTD 等同于 XHTML 1.0 Transitional,但允許框架集內容。

          <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" 
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
          

          XHTML 1.1

          該 DTD 等同于 XHTML 1.0 Strict,但允許添加模型(例如提供對東亞語系的 ruby 支持)。

          <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
          

          最后,雖然上方的html4和xml的文檔類型聲明這么麻煩了,但是這里沒什么知識點了,因為如今,html5應用這么普及了,我們只需在文檔開頭寫<!DOCTYPE html>即可,當然html4的嚴格模式和傳統模式大概知道就行了。


          主站蜘蛛池模板: 无码乱人伦一区二区亚洲一| 一区二区免费在线观看| 国产精品福利一区| 久夜色精品国产一区二区三区| 久久久久人妻一区精品色 | 无码av中文一区二区三区桃花岛 | 无码人妻啪啪一区二区| 日本一区二区高清不卡| 亚洲一区二区三区在线观看蜜桃| 一区二区国产在线观看| 色窝窝免费一区二区三区| 亚洲国产美国国产综合一区二区| 冲田杏梨高清无一区二区| 日韩精品中文字幕视频一区| 精品欧洲AV无码一区二区男男| 伦理一区二区三区| 国产美女av在线一区| 国产精品久久久久一区二区| 中文字幕在线不卡一区二区| 亚拍精品一区二区三区| 精品福利一区二区三| 国产福利一区二区在线视频| 在线|一区二区三区| 在线观看一区二区三区av| 亚洲一区二区三区在线网站| 无码国产精成人午夜视频一区二区| 国产精品 视频一区 二区三区| 国产一区二区三区在线免费观看| 色综合视频一区二区三区44| 精品国产一区二区三区不卡| 日韩人妻无码一区二区三区久久 | 免费日本一区二区| 国产乱码精品一区三上| 亚洲熟女综合一区二区三区| 亚洲av成人一区二区三区| 中文字幕AV一区二区三区人妻少妇| 国产一区二区三区在线2021| 成人精品一区二区三区中文字幕| 国产一区中文字幕在线观看| 精品一区二区三区在线视频观看| 精品一区二区三区四区电影|