diff --git a/src/_node/html/apis.ts b/src/_node/html/apis.ts index c7b19018..08fca7a4 100644 --- a/src/_node/html/apis.ts +++ b/src/_node/html/apis.ts @@ -25,6 +25,20 @@ import { THtmlReferenceData, } from './types'; +const noNeedClosingTag = ['area', + 'base', + 'br', + 'col', + 'embed', + 'hr', + 'img', + 'input', + 'link', + 'meta', + 'param', + 'source', + 'track', + 'wbr'] const emptyImage = window.location.origin + "/images/empty-image.svg" export const setHtmlNodeInAppAttribName = (node: TNode, newUid: TNodeUid) => { const nodeData = node.data as THtmlNodeData @@ -308,7 +322,7 @@ export const serializeHtml = (tree: TNodeTreeData, htmlReferenceData: THtmlRefer nodeHtmlInApp = `` } else if (nodeData.type === 'text') { // replace "<" or ">" to "<" and ">", only in app - nodeHtml = nodeData.data.replace(//g, `>`) + nodeHtml = nodeData.data nodeHtmlInApp = nodeData.data.replace(//g, `>`) } else if (nodeData.type === 'script' || nodeData.type === 'style') { nodeHtml = `<${nodeData.type}${attribsHtml}>${childrenHtml}` @@ -393,7 +407,12 @@ export const parseHtmlCodePart = (content: string, htmlReferenceData: THtmlRefer ReactHtmlParser(content, { decodeEntities: true, transform: (node, index, transform) => { - node.valid = true + if ((node as THtmlDomNodeData).type === 'tag' && (htmlReferenceData.elements[(node as THtmlDomNodeData).name] || (node as THtmlDomNodeData).name.indexOf('-') !== -1)) { + node.valid = true + } + else{ + node.valid = false + } }, preprocessNodes: (nodes: THtmlDomNodeData[]) => { // build root node @@ -496,4 +515,43 @@ export const parseHtmlCodePart = (content: string, htmlReferenceData: THtmlRefer const { html: formattedContent } = serializeHtml(tree, htmlReferenceData, osType) return { formattedContent, contentInApp: '', tree, nodeMaxUid: String(_nodeMaxUid) as TNodeUid } +} + +export const checkValidHtml = (content: string): boolean => { + // remove code & pre & script tag's content + const tmpString = content.replace(/)<[^<]*)*<\/pre>/gi, '
').replace(/)<[^<]*)*<\/code>/gi, '').replace(/)<[^<]*)*<\/script>/gi, '').replace(/)<[^<]*)*<\/style>/gi, '');
+  let hasMismatchedTags = false   
+  let openingTags = [];
+  let closingTags = [];
+  let regex = /<\/?[a-zA-Z0-9]+\b[^>]*>/g; // Matches any HTML tag
+  let match = regex.exec(tmpString);
+  while (match) {
+    let tag = match[0];
+    if (tag.startsWith(' _tag === _item) === undefined) {
+        closingTags.push(_tag);
+      }
+    } else {
+      let _tag = tag.slice(1, -1).split(' ')[0]
+      if (noNeedClosingTag.find(_item => _tag === _item) === undefined) {
+        openingTags.push(_tag);
+      }
+    }
+    match = regex.exec(tmpString);
+  }
+
+  if (openingTags.length !== closingTags.length) {
+    hasMismatchedTags = true; // Different number of opening and closing tags
+  }
+  else {
+    openingTags.sort()
+    closingTags.sort()
+    for (let i = 0 ; i < openingTags.length ; i ++) {
+      if (openingTags[i] !== closingTags[i])
+        hasMismatchedTags = true
+    }
+  }
+
+  return hasMismatchedTags
 }
\ No newline at end of file
diff --git a/src/_ref/cmdk.ref/Actions.csv b/src/_ref/cmdk.ref/Actions.csv
index cc89cdfa..1568d94e 100644
--- a/src/_ref/cmdk.ref/Actions.csv
+++ b/src/_ref/cmdk.ref/Actions.csv
@@ -1,11 +1,8 @@
 Name,Icon,Description,Keyboard Shortcut,Group,Context
 Add,plus,Add something,a,Project,all
 Code,code-html,Open Code,c,Project,all
-Run,play,"""Run"" (Preview)",r,Project,all
 Save,data,Save current file,cmd+s,Project,all
 Design,edit,"""Design"" On/Off (hide panels)",\,Project,all
-Publish,cloud-upload,,p,Project,all
-Share,share,,h,Project,all
 Download,download,,cmd+d,Project,all
 Cut,copy,,cmd+x,Basic,"file, html"
 Copy,copy,,cmd+c,Basic,"file, html"
@@ -14,8 +11,6 @@ Delete,cross,,backspace,Basic,"file, html"
 Duplicate,copy,,cmd+j,Basic,"file, html"
 Group,border,,cmd+g,Basic,html
 Ungroup,position,,cmd+shift+g,Basic,html
-Style,brush,Add Style,s,Basic,html
 Text,text,Edit Text,t,Basic,html
 Undo,undo,,cmd+z,Basic,all
-Redo,redo,,cmd+shift+z,Basic,all
-Turn into,sync,,,Other,html
\ No newline at end of file
+Redo,redo,,cmd+shift+z,Basic,all
\ No newline at end of file
diff --git a/src/components/main/actionsPanel/navigatorPanel/NavigatorPanel.tsx b/src/components/main/actionsPanel/navigatorPanel/NavigatorPanel.tsx
index 336a8f30..86edae24 100644
--- a/src/components/main/actionsPanel/navigatorPanel/NavigatorPanel.tsx
+++ b/src/components/main/actionsPanel/navigatorPanel/NavigatorPanel.tsx
@@ -114,28 +114,28 @@ export default function NavigatorPanel(props: NavigatorPanelProps) {
     setFaviconFallback(false)
     // set favicons of the workspace
     if (file.uid === `${RootNodeUid}/index.html`) {
-      if (validNodeTree) {
-        let hasFavicon = false
-        for (const x in validNodeTree) {
-          const nodeData = validNodeTree[x].data as THtmlNodeData
-          if (nodeData && nodeData.type === 'tag' && nodeData.name === 'link' && nodeData.attribs.rel === 'icon') {
-            if (nodeData.attribs.href.startsWith('http') || nodeData.attribs.href.startsWith('//')) {
-              setFavicon(nodeData.attribs.href)
-            }
-            else{
-              setFavicon(window.location.origin + '/rnbw/' + project.name + '/' + nodeData.attribs.href)
-            }
-            hasFavicon = true
-          }
-        }
+      // if (validNodeTree) {
+      //   let hasFavicon = false
+      //   for (const x in validNodeTree) {
+      //     const nodeData = validNodeTree[x].data as THtmlNodeData
+      //     if (nodeData && nodeData.type === 'tag' && nodeData.name === 'link' && nodeData.attribs.rel === 'icon') {
+      //       if (nodeData.attribs.href.startsWith('http') || nodeData.attribs.href.startsWith('//')) {
+      //         setFavicon(nodeData.attribs.href)
+      //       }
+      //       else{
+      //         setFavicon(window.location.origin + '/rnbw/' + project.name + '/' + nodeData.attribs.href)
+      //       }
+      //       hasFavicon = true
+      //     }
+      //   }
   
-        if (!hasFavicon) {
-          setFavicon('')
-        }
-      }
-      else{
-        setFavicon('')
-      }
+      //   if (!hasFavicon) {
+      //     setFavicon('')
+      //   }
+      // }
+      // else{
+      //   setFavicon('')
+      // }
 
       let hasFavicon = false
       for (const x in validNodeTree) {
@@ -252,18 +252,7 @@ export default function NavigatorPanel(props: NavigatorPanelProps) {
     return file.uid !== '' ? <>