diff --git a/icons/128x128icon.png b/icons/128x128icon.png new file mode 100644 index 0000000..f969f80 Binary files /dev/null and b/icons/128x128icon.png differ diff --git a/icons/200x200icon.png b/icons/200x200icon.png new file mode 100644 index 0000000..d397b7a Binary files /dev/null and b/icons/200x200icon.png differ diff --git a/icons/48x48icon.png b/icons/48x48icon.png new file mode 100644 index 0000000..0fb94ae Binary files /dev/null and b/icons/48x48icon.png differ diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..6a91ee1 --- /dev/null +++ b/manifest.json @@ -0,0 +1,31 @@ +{ + "manifest_version": 3, + "name": "HTML & CSS Code Viewer", + "version": "1.0", + "description": "An interactive HTML and CSS code editor with real-time preview and a sidebar. Easily import, edit, and visualize your code.", + "background": { + "service_worker": "service-worker.js" + }, + "action": { + "default_title": "Click to open panel" + }, + "icons": { + "48": "icons/48x48icon.png", + "128": "icons/128x128icon.png", + "200": "icons/200x200icon.png" + }, + "permissions": [ + "sidePanel", + "tabs", + "clipboardRead", + "notifications" + ], + "commands": { + "_execute_action": { + "suggested_key": { + "default": "Ctrl+B", + "mac": "Command+B" + } + } + } +} diff --git a/prism.css b/prism.css new file mode 100644 index 0000000..dffa913 --- /dev/null +++ b/prism.css @@ -0,0 +1,338 @@ +/* PrismJS 1.29.0 +https://prismjs.com/download.html#themes=prism-okaidia&languages=markup+css+clike+javascript+css-extras&plugins=line-highlight+line-numbers+show-language+inline-color+toolbar+copy-to-clipboard */ +/** + * okaidia theme for JavaScript, CSS and HTML + * Loosely based on Monokai textmate theme by http://www.monokai.nl/ + * @author ocodia + */ + +code[class*="language-"], +pre[class*="language-"] { + color: #f8f8f2; + background: none; + text-shadow: 0 1px rgba(0, 0, 0, 0.3); + font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + font-size: 1em; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; +} + +/* Code blocks */ +pre[class*="language-"] { + padding: 1em; + margin: .5em 0; + overflow: auto; + border-radius: 0.3em; +} + +:not(pre) > code[class*="language-"], +pre[class*="language-"] { + background: #272822; +} + +/* Inline code */ +:not(pre) > code[class*="language-"] { + padding: .1em; + border-radius: .3em; + white-space: normal; +} + +.token.comment, +.token.prolog, +.token.doctype, +.token.cdata { + color: #8292a2; +} + +.token.punctuation { + color: #f8f8f2; +} + +.token.namespace { + opacity: .7; +} + +.token.property, +.token.tag, +.token.constant, +.token.symbol, +.token.deleted { + color: #f92672; +} + +.token.boolean, +.token.number { + color: #ae81ff; +} + +.token.selector, +.token.attr-name, +.token.string, +.token.char, +.token.builtin, +.token.inserted { + color: #a6e22e; +} + +.token.operator, +.token.entity, +.token.url, +.language-css .token.string, +.style .token.string, +.token.variable { + color: #f8f8f2; +} + +.token.atrule, +.token.attr-value, +.token.function, +.token.class-name { + color: #e6db74; +} + +.token.keyword { + color: #66d9ef; +} + +.token.regex, +.token.important { + color: #fd971f; +} + +.token.important, +.token.bold { + font-weight: bold; +} +.token.italic { + font-style: italic; +} + +.token.entity { + cursor: help; +} + +pre[data-line] { + position: relative; + padding: 1em 0 1em 3em; +} + +.line-highlight { + position: absolute; + left: 0; + right: 0; + padding: inherit 0; + margin-top: 1em; /* Same as .prism’s padding-top */ + + background: hsla(24, 20%, 50%,.08); + background: linear-gradient(to right, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0)); + + pointer-events: none; + + line-height: inherit; + white-space: pre; +} + +@media print { + .line-highlight { + /* + * This will prevent browsers from replacing the background color with white. + * It's necessary because the element is layered on top of the displayed code. + */ + -webkit-print-color-adjust: exact; + color-adjust: exact; + } +} + + .line-highlight:before, + .line-highlight[data-end]:after { + content: attr(data-start); + position: absolute; + top: .4em; + left: .6em; + min-width: 1em; + padding: 0 .5em; + background-color: hsla(24, 20%, 50%,.4); + color: hsl(24, 20%, 95%); + font: bold 65%/1.5 sans-serif; + text-align: center; + vertical-align: .3em; + border-radius: 999px; + text-shadow: none; + box-shadow: 0 1px white; + } + + .line-highlight[data-end]:after { + content: attr(data-end); + top: auto; + bottom: .4em; + } + +.line-numbers .line-highlight:before, +.line-numbers .line-highlight:after { + content: none; +} + +pre[id].linkable-line-numbers span.line-numbers-rows { + pointer-events: all; +} +pre[id].linkable-line-numbers span.line-numbers-rows > span:before { + cursor: pointer; +} +pre[id].linkable-line-numbers span.line-numbers-rows > span:hover:before { + background-color: rgba(128, 128, 128, .2); +} + +pre[class*="language-"].line-numbers { + position: relative; + padding-left: 3.8em; + counter-reset: linenumber; +} + +pre[class*="language-"].line-numbers > code { + position: relative; + white-space: inherit; +} + +.line-numbers .line-numbers-rows { + position: absolute; + pointer-events: none; + top: 0; + font-size: 100%; + left: -3.8em; + width: 3em; /* works for line-numbers below 1000 lines */ + letter-spacing: -1px; + border-right: 1px solid #999; + + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + +} + + .line-numbers-rows > span { + display: block; + counter-increment: linenumber; + } + + .line-numbers-rows > span:before { + content: counter(linenumber); + color: #999; + display: block; + padding-right: 0.8em; + text-align: right; + } + +div.code-toolbar { + position: relative; +} + +div.code-toolbar > .toolbar { + position: absolute; + z-index: 10; + top: .3em; + right: .2em; + transition: opacity 0.3s ease-in-out; + opacity: 0; +} + +div.code-toolbar:hover > .toolbar { + opacity: 1; +} + +/* Separate line b/c rules are thrown out if selector is invalid. + IE11 and old Edge versions don't support :focus-within. */ +div.code-toolbar:focus-within > .toolbar { + opacity: 1; +} + +div.code-toolbar > .toolbar > .toolbar-item { + display: inline-block; +} + +div.code-toolbar > .toolbar > .toolbar-item > a { + cursor: pointer; +} + +div.code-toolbar > .toolbar > .toolbar-item > button { + background: none; + border: 0; + color: inherit; + font: inherit; + line-height: normal; + overflow: visible; + padding: 0; + -webkit-user-select: none; /* for button */ + -moz-user-select: none; + -ms-user-select: none; +} + +div.code-toolbar > .toolbar > .toolbar-item > a, +div.code-toolbar > .toolbar > .toolbar-item > button, +div.code-toolbar > .toolbar > .toolbar-item > span { + color: #bbb; + font-size: .8em; + padding: 0 .5em; + background: #f5f2f0; + background: rgba(224, 224, 224, 0.2); + box-shadow: 0 2px 0 0 rgba(0,0,0,0.2); + border-radius: .5em; +} + +div.code-toolbar > .toolbar > .toolbar-item > a:hover, +div.code-toolbar > .toolbar > .toolbar-item > a:focus, +div.code-toolbar > .toolbar > .toolbar-item > button:hover, +div.code-toolbar > .toolbar > .toolbar-item > button:focus, +div.code-toolbar > .toolbar > .toolbar-item > span:hover, +div.code-toolbar > .toolbar > .toolbar-item > span:focus { + color: inherit; + text-decoration: none; +} + +span.inline-color-wrapper { + /* + * The background image is the following SVG inline in base 64: + * + * + * + * + * + * + * SVG-inlining explained: + * https://stackoverflow.com/a/21626701/7595472 + */ + background: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyIDIiPjxwYXRoIGZpbGw9ImdyYXkiIGQ9Ik0wIDBoMnYySDB6Ii8+PHBhdGggZmlsbD0id2hpdGUiIGQ9Ik0wIDBoMXYxSDB6TTEgMWgxdjFIMXoiLz48L3N2Zz4="); + /* This is to prevent visual glitches where one pixel from the repeating pattern could be seen. */ + background-position: center; + background-size: 110%; + + display: inline-block; + height: 1.333ch; + width: 1.333ch; + margin: 0 .333ch; + box-sizing: border-box; + border: 1px solid white; + outline: 1px solid rgba(0,0,0,.5); + overflow: hidden; +} + +span.inline-color { + display: block; + /* To prevent visual glitches again */ + height: 120%; + width: 120%; +} + diff --git a/prism.js b/prism.js new file mode 100644 index 0000000..902f73a --- /dev/null +++ b/prism.js @@ -0,0 +1,3217 @@ +/* PrismJS 1.29.0 +https://prismjs.com/download.html#themes=prism-okaidia&languages=markup+css+clike+javascript+css-extras&plugins=line-highlight+line-numbers+show-language+inline-color+toolbar+copy-to-clipboard */ +/// + +var _self = (typeof window !== 'undefined') + ? window // if in browser + : ( + (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) + ? self // if in worker + : {} // if in node js + ); + +/** + * Prism: Lightweight, robust, elegant syntax highlighting + * + * @license MIT + * @author Lea Verou + * @namespace + * @public + */ +var Prism = (function (_self) { + + // Private helper vars + var lang = /(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i; + var uniqueId = 0; + + // The grammar object for plaintext + var plainTextGrammar = {}; + + + var _ = { + /** + * By default, Prism will attempt to highlight all code elements (by calling {@link Prism.highlightAll}) on the + * current page after the page finished loading. This might be a problem if e.g. you wanted to asynchronously load + * additional languages or plugins yourself. + * + * By setting this value to `true`, Prism will not automatically highlight all code elements on the page. + * + * You obviously have to change this value before the automatic highlighting started. To do this, you can add an + * empty Prism object into the global scope before loading the Prism script like this: + * + * ```js + * window.Prism = window.Prism || {}; + * Prism.manual = true; + * // add a new + + + + +
+
+

HTML & CSS Code Viewer

+
+ + + +
+
+ +
+
+
+
+ HTML + +
+
+
+ +
+
+ CSS + +
+
+
+ +
+ +
+
+
+
+ +
+

HTML & CSS Code Viewer extensions made by EnderMythex

+
+ + + \ No newline at end of file diff --git a/sidepanel.js b/sidepanel.js new file mode 100644 index 0000000..1cf6e40 --- /dev/null +++ b/sidepanel.js @@ -0,0 +1,72 @@ +document.addEventListener('DOMContentLoaded', function () { + // Sélection des éditeurs et boutons + const htmlEditor = document.getElementById('htmlInput'); + const cssEditor = document.getElementById('cssInput'); + const previewFrame = document.getElementById('previewFrame'); + + const htmlButton = document.getElementById('btn-html'); + const cssButton = document.getElementById('btn-css'); + const generateButton = document.getElementById('btn-gen'); + + const toggleHtmlEditor = document.getElementById('toggleEditorhtml'); + const toggleCssEditor = document.getElementById('toggleEditorcss'); + + let htmlContent = htmlEditor ? htmlEditor.textContent : ''; + let cssContent = cssEditor ? cssEditor.textContent : ''; + let combinedContent = `${htmlContent}`; + + // Copier le contenu HTML depuis le presse-papiers + if (htmlButton) { + htmlButton.addEventListener('click', async () => { + try { + const text = await navigator.clipboard.readText(); + htmlEditor.textContent = text; + Prism.highlightElement(htmlEditor); + } catch (err) { + console.error('Erreur lors de la lecture du presse-papiers :', err); + } + }); + } else { + console.error("Le bouton HTML n'a pas été trouvé."); + } + + // Copier le contenu CSS depuis le presse-papiers + if (cssButton) { + cssButton.addEventListener('click', async () => { + try { + const text = await navigator.clipboard.readText(); + cssEditor.textContent = text; + Prism.highlightElement(cssEditor); + } catch (err) { + console.error('Erreur lors de la lecture du presse-papiers :', err); + } + }); + } else { + console.error("Le bouton CSS n'a pas été trouvé."); + } + + // Fonction pour mettre à jour l'aperçu + function updatePreview() { + htmlContent = htmlEditor.textContent; + cssContent = cssEditor.textContent; + combinedContent = `${htmlContent}`; + + previewFrame.contentDocument.body.innerHTML = combinedContent; + Prism.highlightElement(htmlEditor); + Prism.highlightElement(cssEditor); + } + + if (generateButton) { + generateButton.addEventListener('click', updatePreview); + } + + toggleHtmlEditor.addEventListener('click', function () { + htmlEditor.parentElement.style.display = + htmlEditor.parentElement.style.display === 'none' ? 'block' : 'none'; + }); + + toggleCssEditor.addEventListener('click', function () { + cssEditor.parentElement.style.display = + cssEditor.parentElement.style.display === 'none' ? 'block' : 'none'; + }); +});