1+ <!DOCTYPE html>
2+ < html >
3+
4+ < head >
5+ < link href ="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900 " rel ="stylesheet ">
6+ < link href ="https://cdn.jsdelivr.net/npm/@mdi/font@6.x/css/materialdesignicons.min.css " rel ="stylesheet ">
7+ < link href ="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css " rel ="stylesheet ">
8+ < meta name ="viewport " content ="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui ">
9+
10+ < link rel ="stylesheet " data-name ="vs/editor/editor.main "
11+ href ="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.26.1/min/vs/editor/editor.main.min.css ">
12+
13+ < title >
14+ TailwindCSS to SASS Converter
15+ </ title >
16+
17+ < style >
18+ [v-cloak ]> * {
19+ display : none
20+ }
21+
22+ [v-cloak ]::before {
23+ content : "loading…"
24+ }
25+
26+ .code-container {
27+ height : 500px ;
28+ width : 100% ;
29+ }
30+ </ style >
31+ </ head >
32+
33+ < body >
34+ < div id ="app ">
35+ < v-app v-cloak >
36+ <!-- Must have the app property -->
37+ < v-toolbar class ="pa-0 ">
38+ < v-row >
39+ < v-col cols ="2 "> </ v-col >
40+ < v-col class ="d-flex justify-space-around ">
41+ < v-toolbar-title >
42+ TailwindCSS to SASS Converter
43+ </ v-toolbar-title >
44+ </ v-col >
45+ < v-col cols ="2 " class ="d-flex justify-end "> </ v-col >
46+ </ v-toolbar >
47+
48+ < v-main class ="my-5 mx-5 ">
49+ < v-container fluid >
50+ < v-row >
51+ < v-col cols ="12 ">
52+ < v-row >
53+ < v-col >
54+ Tailwind template (HTML format)
55+ </ v-col >
56+ </ v-row >
57+ < v-row >
58+ < v-col >
59+ < div id ="htmlContainer " class ="code-container "> </ div >
60+ </ v-col >
61+ </ v-row >
62+ </ v-col >
63+ </ v-row >
64+
65+ < v-row >
66+ < v-col cols ="12 ">
67+ < v-row >
68+ < v-col >
69+ SASS Output
70+ </ v-col >
71+ </ v-row >
72+ < v-row >
73+ < v-col >
74+ < div id ="sassContainer " class ="code-container "> </ div >
75+ </ v-col >
76+ </ v-row >
77+ </ v-col >
78+ </ v-row >
79+ </ v-container >
80+ </ v-main >
81+ </ v-app >
82+ </ div >
83+
84+ < script src ="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js "> </ script >
85+ < script src ="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js "> </ script >
86+ < script src ="https://unpkg.com/@egoistdeveloper/twcss-to-sass@1.0.1/dist/twcss-to-sass.js "> </ script >
87+
88+ < script >
89+ var require = {
90+ paths : {
91+ 'vs' : 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.26.1/min/vs'
92+ }
93+ }
94+ </ script >
95+ < script src ="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.26.1/min/vs/loader.min.js "> </ script >
96+ < script src ="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.26.1/min/vs/editor/editor.main.nls.js "> </ script >
97+ < script src ="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.26.1/min/vs/editor/editor.main.js "> </ script >
98+
99+ < script >
100+ const isBrowserDarkTheme = window . matchMedia ( '(prefers-color-scheme: dark)' ) . matches ;
101+
102+ new Vue ( {
103+ el : '#app' ,
104+ vuetify : new Vuetify ( {
105+ theme : {
106+ dark : isBrowserDarkTheme
107+ } ,
108+ } ) ,
109+
110+ data : {
111+ htmlInput : null ,
112+ sassOutput : null ,
113+ htmlMonacoEditor : null ,
114+ sassMonacoEditor : null ,
115+ } ,
116+
117+ methods : {
118+ loadEditors : function ( ) {
119+ const defaultTemplate =
120+ `<div class="bg-white">\n\t<div class="flex justify-center items-center min-h-screen min-w-full">\n\t\t<div class="flex relative">\n\t\t\t<div class="w-72 h-40 bg-green-400 transform transition-all skew-x-12 -skew-y-12 absolute rounded-lg">\n\t\t\t\tMy Text 1\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>` ;
121+
122+ const {
123+ convertToSass
124+ } = twcssToSass ,
125+ theme = this . getCurrentTheme ( ) ,
126+ commonEditorConfig = {
127+ theme : `vs-${ theme } ` ,
128+ minimap : {
129+ enabled : false
130+ }
131+ } ;
132+
133+ htmlMonacoEditor = monaco . editor . create ( document . getElementById ( 'htmlContainer' ) , Object
134+ . assign ( commonEditorConfig , {
135+ value : defaultTemplate ,
136+ language : 'html' ,
137+ } ) ) ;
138+
139+ sassMonacoEditor = monaco . editor . create ( document . getElementById ( 'sassContainer' ) , Object
140+ . assign ( commonEditorConfig , {
141+ language : 'scss' ,
142+ } ) ) ;
143+
144+ sassMonacoEditor . getModel ( ) . setValue ( convertToSass ( defaultTemplate ) ) ;
145+
146+ htmlMonacoEditor . onDidChangeModelContent ( function ( e ) {
147+ let sassOutput = convertToSass ( htmlMonacoEditor . getValue ( ) ) ;
148+
149+ if ( ! sassOutput || ! sassOutput . length ) {
150+ sassOutput = 'Invalid HTML content.' ;
151+ }
152+
153+ sassMonacoEditor . getModel ( ) . setValue ( sassOutput ) ;
154+ } ) ;
155+ } ,
156+
157+ /** get current browser theme */
158+ getCurrentTheme : function ( ) {
159+ if ( window . matchMedia ) {
160+ return window . matchMedia ( '(prefers-color-scheme: dark)' ) . matches ? 'dark' : 'light' ;
161+ }
162+ } ,
163+
164+ /** watch browser theme*/
165+ watchBrowserTheme : function ( ) {
166+ window . matchMedia ( '(prefers-color-scheme: dark)' ) . addEventListener ( 'change' , e => {
167+ const themeOption = {
168+ theme : `vs-${ e . matches ? 'dark' : 'light' } `
169+ } ;
170+
171+ htmlMonacoEditor . updateOptions ( themeOption ) ;
172+ sassMonacoEditor . updateOptions ( themeOption ) ;
173+
174+ this . $vuetify . theme . isDark = e . matches ;
175+ } ) ;
176+ }
177+ } ,
178+
179+ mounted : function ( ) {
180+ this . loadEditors ( ) ;
181+ this . watchBrowserTheme ( ) ;
182+ }
183+ } ) ;
184+ </ script >
185+ </ body >
186+
187+ </ html >
0 commit comments