瀏覽代碼

Add popup options to the main options page

simov 1 年之前
父節點
當前提交
358a7d3d71
共有 8 個文件被更改,包括 360 次插入274 次删除
  1. 1 1
      build/bootstrap/package.json
  2. 40 48
      options/index.css
  3. 7 9
      options/index.html
  4. 4 9
      options/index.js
  5. 1 1
      options/origins.js
  6. 28 42
      options/settings.js
  7. 1 1
      popup/index.html
  8. 278 163
      popup/index.js

+ 1 - 1
build/bootstrap/package.json

@@ -4,7 +4,7 @@
   "description": "Markdown Viewer / Browser Extension",
   "private": true,
   "dependencies": {
-    "bootstrap": "5.2.3"
+    "bootstrap": "5.3.3"
   },
   "engines": {
     "node": ">=18.0.0"

+ 40 - 48
options/index.css

@@ -26,6 +26,11 @@ main {
   min-height: 52px;
 }
 
+.col-sm-12.m-overflow {
+  white-space: nowrap;
+  overflow: hidden;
+}
+
 .mdc-elevation--z2 {
   box-shadow:
     0 3px 1px -2px rgba(0,0,0,.2),
@@ -44,9 +49,6 @@ body.dark .navbar {
   filter: invert(90%) hue-rotate(180deg);
   background-color: transparent;
 }
-body.dark .navbar #menu > div {
-  filter: invert(100%) hue-rotate(180deg);
-}
 body.dark .m-select {
   background-color: #c5c5c5;
 }
@@ -63,9 +65,6 @@ body.dark .m-button {
     filter: invert(90%) hue-rotate(180deg);
     background-color: transparent;
   }
-  body.auto .navbar #menu > div {
-    filter: invert(100%) hue-rotate(180deg);
-  }
   body.auto .m-select {
     background-color: #c5c5c5;
   }
@@ -95,46 +94,12 @@ footer, #footer-push {
 /*---------------------------------------------------------------------------*/
 /*header menu*/
 
-#menu {
-  position: relative;
+.nav a,
+.nav a:hover,
+.nav a:visited,
+.nav-underline .nav-link.active {
   color: #fff;
 }
-#menu span {
-  font-size: 20px;
-  display: inline-block;
-  line-height: 60px;
-  padding: 0 20px;
-}
-#menu div {
-  position: absolute;
-  top: 68px;
-  right: 0;
-  z-index: 10;
-  width: 200px;
-  box-shadow:
-    0 3px 1px -2px rgba(0,0,0,.2),
-    0 2px 2px 0 rgba(0,0,0,.14),
-    0 1px 5px 0 rgba(0,0,0,.12);
-}
-#menu em {
-  display: block;
-  font-size: 20px;
-  line-height: 50px;
-  font-style: normal;
-  color: #333;
-  cursor: pointer;
-  padding: 0 20px;
-  background: #fff;
-  transition-duration: .28s;
-  transition-timing-function: cubic-bezier(.4,0,.2,1);
-  transition-property: background-color box-shadow;
-}
-#menu em:hover {
-  background: #ececec;
-}
-#menu em.active {
-  background: #ececec;
-}
 
 /*---------------------------------------------------------------------------*/
 /*scrollbar*/
@@ -229,10 +194,6 @@ footer, #footer-push {
   padding: 9px 12px;
 }
 
-.bs-callout .m-select {
-  margin: 2px 20px 3px 10px;
-}
-
 /*---------------------------------------------------------------------------*/
 /*misc*/
 
@@ -280,6 +241,37 @@ h4 {
   float: right;
 }
 
+/*---------------------------------------------------------------------------*/
+/*settings*/
+
+.m-settings .m-label {
+  display: inline-block;
+  font-size: 1rem;
+  line-height: 1.5rem;
+  padding: 5px 0 5px 0;
+}
+.m-settings .m-select {
+  width: 100%;
+  margin-bottom: 20px;
+}
+
+.m-content .m-switch,
+.m-compiler .m-switch {
+  width: 100%;
+}
+
+.m-compiler .scroll {
+  margin-top: 10px;
+  overflow-y: auto;
+  overflow-x: hidden;
+}
+.m-compiler .scroll.max {
+  height: 324px;
+}
+
+/*---------------------------------------------------------------------------*/
+/*footer*/
+
 footer {
   text-align: center;
   margin: 0 auto;

+ 7 - 9
options/index.html

@@ -15,14 +15,11 @@
     <nav class="navbar navbar-dark bg-dark fixed-top">
       <div class="container">
         <a href="https://github.com/simov/markdown-viewer" class="navbar-brand">Markdown Viewer</a>
-        <a href="#" id="menu">
-          <span>☰</span>
-          <div class="hidden">
-            <em class="active">Origins</em>
-            <em>Settings</em>
-            <em>Help</em>
-          </div>
-        </a>
+        <ul class="nav nav-underline">
+          <li class="nav-item"><a href="#" class="nav-link active">Origins</a></li>
+          <li class="nav-item"><a href="#" class="nav-link">Settings</a></li>
+          <li class="nav-item"><a href="#" class="nav-link">Help</a></li>
+        </ul>
       </div>
     </nav>
     <div class="container">
@@ -33,7 +30,7 @@
   <footer>
     <nav>
       <a href="https://github.com/simov/markdown-viewer">GitHub</a> &bullet;
-      <a href="https://chrome.google.com/webstore/detail/markdown-viewer/ckkdlimhmcjmikdlpkmbgfkaikojcbjk">Chrome</a> &bullet;
+      <a href="https://chromewebstore.google.com/detail/markdown-viewer/ckkdlimhmcjmikdlpkmbgfkaikojcbjk">Chrome</a> &bullet;
       <a href="https://microsoftedge.microsoft.com/addons/detail/markdown-viewer/cgfmehpekedojlmjepoimbfcafopimdg">Edge</a> &bullet;
       <a href="https://addons.mozilla.org/en-US/firefox/addon/markdown-viewer-chrome/">Firefox</a>
     </nav>
@@ -41,5 +38,6 @@
 </body>
 <script src="/options/origins.js" type="text/javascript" charset="utf-8"></script>
 <script src="/options/settings.js" type="text/javascript" charset="utf-8"></script>
+<script src="/popup/index.js" type="text/javascript" charset="utf-8"></script>
 <script src="/options/index.js" type="text/javascript" charset="utf-8"></script>
 </html>

+ 4 - 9
options/index.js

@@ -1,22 +1,18 @@
 
 var origins = Origins()
-var settings = Settings()
+var popup = Popup()
 
 m.mount(document.querySelector('main'), {
   view: () => [
     origins.render(),
-    settings.render(),
+    popup.options(),
   ]
 })
 
 // header menu
-document.querySelector('#menu span').addEventListener('click', (e) => {
+document.querySelector('.nav').addEventListener('click', (e) => {
   e.preventDefault()
-  document.querySelector('#menu div').classList.toggle('hidden')
-})
-document.querySelector('#menu div').addEventListener('click', (e) => {
-  e.preventDefault()
-  Array.from(document.querySelectorAll('#menu em')).forEach((link) => {
+  Array.from(document.querySelectorAll('.nav a')).forEach((link) => {
     link.classList.remove('active')
   })
   if (e.target.innerText === 'Origins') {
@@ -32,5 +28,4 @@ document.querySelector('#menu div').addEventListener('click', (e) => {
   else if (e.target.innerText === 'Help') {
     window.location = 'https://github.com/simov/markdown-viewer#table-of-contents'
   }
-  document.querySelector('#menu div').classList.add('hidden')
 })

+ 1 - 1
options/origins.js

@@ -214,7 +214,7 @@ var Origins = () => {
     m('.bs-callout', {class: !state.permissions[origin] ? 'm-box-refresh' : undefined},
       // origin
       m('.row',
-        m('.col-xxl-8.col-xl-8.col-lg-8.col-md-7.col-sm-12', m('span.m-origin', origin)),
+        m('.col-xxl-8.col-xl-8.col-lg-8.col-md-7.col-sm-12 m-overflow', m('span.m-origin', origin)),
         m('.col-xxl-4.col-xl-4.col-lg-4.col-md-5.col-sm-12',
           // remove
           (origin !== 'file://' || null) &&

+ 28 - 42
options/settings.js

@@ -44,54 +44,40 @@ var Settings = () => {
 
   var onupdate = {}
 
-  var render = () =>
-    m('.m-settings hidden',
-      m('.row',
-        m('h3', 'Settings')
+  var render = () => [
+    m('.row',
+      m('.col-xxl-6.col-xl-6.col-lg-6.col-md-6.col-sm-12',
+        m('span.m-label',
+          'Extension Icon'
+        )
       ),
-      // icon
-      m('.bs-callout',
-        m('.row',
-          m('.col-sm-12',
-            m('.overflow',
-              m('label.mdc-switch',
-                m('select.mdc-elevation--z2 m-select', {
-                  onchange: events.icon
-                  },
-                  state._icons.map((icon) =>
-                    m('option', {selected: state.icon === icon}, icon)
-                  )
-                ),
-                m('span.mdc-switch-label',
-                  'Extension Icon and Content Favicon Color'
-                )
-              )
-            )
+      m('.col-xxl-6.col-xl-6.col-lg-6.col-md-6.col-sm-12',
+        m('select.mdc-elevation--z2 m-select', {
+          onchange: events.icon
+          },
+          state._icons.map((icon) =>
+            m('option', {selected: state.icon === icon}, icon)
           )
         )
       ),
-      // theme
-      m('.bs-callout',
-        m('.row',
-          m('.col-sm-12',
-            m('.overflow',
-              m('label.mdc-switch',
-                m('select.mdc-elevation--z2 m-select', {
-                  onchange: events.theme
-                  },
-                  state._themes.map((theme) =>
-                    m('option', {selected: state.theme === theme}, theme)
-                  )
-                ),
-                m('span.mdc-switch-label',
-                  'Popup and Options Page Color Mode'
-                )
-              )
-            )
+    ),
+    m('.row',
+      m('.col-xxl-6.col-xl-6.col-lg-6.col-md-6.col-sm-12',
+        m('span.m-label',
+          'Popup & Options Page'
+        )
+      ),
+      m('.col-xxl-6.col-xl-6.col-lg-6.col-md-6.col-sm-12',
+        m('select.mdc-elevation--z2 m-select', {
+          onchange: events.theme
+          },
+          state._themes.map((theme) =>
+            m('option', {selected: state.theme === theme}, theme)
           )
         )
-      )
-    )
+      ),
+    ),
+  ]
 
   return {state, render}
 }

+ 1 - 1
popup/index.html

@@ -9,6 +9,6 @@
   <script src="/vendor/mdc.min.js" type="text/javascript" charset="utf-8"></script>
   <script src="/vendor/mithril.min.js" type="text/javascript" charset="utf-8"></script>
 </head>
-<body></body>
+<body class="is-popup"></body>
 <script src="/popup/index.js" type="text/javascript" charset="utf-8"></script>
 </html>

+ 278 - 163
popup/index.js

@@ -1,190 +1,191 @@
 
-var state = {
-  compiler: '',
-  options: {},
-  content: {},
-  theme: '',
-  themes: {},
-  _themes: [
-    'github',
-    'github-dark',
-    // 'air',
-    'almond',
-    'awsm',
-    'axist',
-    'bamboo',
-    'bullframe',
-    'holiday',
-    'kacit',
-    'latex',
-    'marx',
-    'mini',
-    'modest',
-    'new',
-    'no-class',
-    'pico',
-    'retro',
-    'sakura',
-    'sakura-vader',
-    'semantic',
-    'simple',
-    // 'splendor',
-    'style-sans',
-    'style-serif',
-    'stylize',
-    'superstylin',
-    'tacit',
-    'vanilla',
-    'water',
-    'water-dark',
-    'writ',
-  ],
-  _width: [
-    'auto',
-    'full',
-    'wide',
-    'large',
-    'medium',
-    'small',
-    'tiny',
-  ],
-  raw: false,
-  tab: '',
-  tabs: ['theme', 'compiler', 'content'],
-  compilers: [],
-  description: {
+var Popup = () => {
+
+  var state = {
+    compiler: '',
+    options: {},
+    content: {},
+    theme: '',
     themes: {},
-    compiler: {},
-    content: {
-      autoreload: 'Auto reload on file change',
-      emoji: 'Convert emoji :shortnames: into EmojiOne images',
-      toc: 'Generate Table of Contents',
-      mathjax: 'Render MathJax formulas',
-      mermaid: 'Mermaid diagrams',
-      syntax: 'Syntax highlighting for fenced code blocks',
-    }
-  },
-  settings: {}
-}
+    _themes: [
+      'github',
+      'github-dark',
+      // 'air',
+      'almond',
+      'awsm',
+      'axist',
+      'bamboo',
+      'bullframe',
+      'holiday',
+      'kacit',
+      'latex',
+      'marx',
+      'mini',
+      'modest',
+      'new',
+      'no-class',
+      'pico',
+      'retro',
+      'sakura',
+      'sakura-vader',
+      'semantic',
+      'simple',
+      // 'splendor',
+      'style-sans',
+      'style-serif',
+      'stylize',
+      'superstylin',
+      'tacit',
+      'vanilla',
+      'water',
+      'water-dark',
+      'writ',
+    ],
+    _width: [
+      'auto',
+      'full',
+      'wide',
+      'large',
+      'medium',
+      'small',
+      'tiny',
+    ],
+    raw: false,
+    tab: '',
+    tabs: ['theme', 'compiler', 'content'],
+    compilers: [],
+    description: {
+      themes: {},
+      compiler: {},
+      content: {
+        autoreload: 'Auto reload on file change',
+        emoji: 'Convert emoji :shortnames: into EmojiOne images',
+        toc: 'Generate Table of Contents',
+        mathjax: 'Render MathJax formulas',
+        mermaid: 'Mermaid diagrams',
+        syntax: 'Syntax highlighting for fenced code blocks',
+      }
+    },
+    settings: {}
+  }
 
-var events = {
-  tab: (e) => {
-    state.tab = e.target.hash.replace('#tab-', '')
-    localStorage.setItem('tab', state.tab)
-    return false
-  },
+  var events = {
+    tab: (e) => {
+      state.tab = e.target.hash.replace('#tab-', '')
+      localStorage.setItem('tab', state.tab)
+      return false
+    },
 
-  compiler: {
-    name: (e) => {
-      state.compiler = state.compilers[e.target.selectedIndex]
+    compiler: {
+      name: (e) => {
+        state.compiler = state.compilers[e.target.selectedIndex]
+        chrome.runtime.sendMessage({
+          message: 'popup.compiler.name',
+          compiler: state.compiler,
+        }, () => {
+          chrome.runtime.sendMessage({message: 'popup'}, init)
+        })
+      },
+      options: (e) => {
+        state.options[e.target.name] = !state.options[e.target.name]
+        chrome.runtime.sendMessage({
+          message: 'popup.compiler.options',
+          compiler: state.compiler,
+          options: state.options,
+        })
+      }
+    },
+
+    content: (e) => {
+      state.content[e.target.name] = !state.content[e.target.name]
       chrome.runtime.sendMessage({
-        message: 'popup.compiler.name',
-        compiler: state.compiler,
-      }, () => {
-        chrome.runtime.sendMessage({message: 'popup'}, init)
+        message: 'popup.content',
+        content: state.content,
       })
     },
-    options: (e) => {
-      state.options[e.target.name] = !state.options[e.target.name]
+
+    themes: (e) => {
+      state.themes.width = state._width[e.target.selectedIndex]
       chrome.runtime.sendMessage({
-        message: 'popup.compiler.options',
-        compiler: state.compiler,
-        options: state.options,
+        message: 'popup.themes',
+        themes: state.themes,
       })
-    }
-  },
-
-  content: (e) => {
-    state.content[e.target.name] = !state.content[e.target.name]
-    chrome.runtime.sendMessage({
-      message: 'popup.content',
-      content: state.content,
-    })
-  },
-
-  themes: (e) => {
-    state.themes.width = state._width[e.target.selectedIndex]
-    chrome.runtime.sendMessage({
-      message: 'popup.themes',
-      themes: state.themes,
-    })
-  },
+    },
 
-  theme: (e) => {
-    state.theme = state._themes[e.target.selectedIndex]
-    chrome.runtime.sendMessage({
-      message: 'popup.theme',
-      theme: state.theme
-    })
-  },
+    theme: (e) => {
+      state.theme = state._themes[e.target.selectedIndex]
+      chrome.runtime.sendMessage({
+        message: 'popup.theme',
+        theme: state.theme
+      })
+    },
 
-  raw: () => {
-    state.raw = !state.raw
-    chrome.runtime.sendMessage({
-      message: 'popup.raw',
-      raw: state.raw
-    })
-  },
+    raw: () => {
+      state.raw = !state.raw
+      chrome.runtime.sendMessage({
+        message: 'popup.raw',
+        raw: state.raw
+      })
+    },
 
-  defaults: () => {
-    chrome.runtime.sendMessage({
-      message: 'popup.defaults'
-    }, () => {
-      chrome.runtime.sendMessage({message: 'popup'}, init)
-      localStorage.removeItem('tab')
-      state._tabs.activeTabIndex = 0
-    })
-  },
+    defaults: () => {
+      chrome.runtime.sendMessage({
+        message: 'popup.defaults'
+      }, () => {
+        chrome.runtime.sendMessage({message: 'popup'}, init)
+        localStorage.removeItem('tab')
+        state._tabs.activeTabIndex = 0
+      })
+    },
 
-  advanced: () => {
-    chrome.runtime.sendMessage({message: 'popup.advanced'})
+    advanced: () => {
+      chrome.runtime.sendMessage({message: 'popup.advanced'})
+    }
   }
-}
 
-var init = (res) => {
-  state.compiler = res.compiler
-  state.options = res.options
-  state.content = res.content
-  state.theme = res.theme
-  state.themes = res.themes
+  var init = (res) => {
+    state.compiler = res.compiler
+    state.options = res.options
+    state.content = res.content
+    state.theme = res.theme
+    state.themes = res.themes
 
-  state.raw = res.raw
-  state.tab = localStorage.getItem('tab') || 'theme'
-  state.compilers = res.compilers
-  state.description.compiler = res.description
+    state.raw = res.raw
+    state.tab = localStorage.getItem('tab') || 'theme'
+    state.compilers = res.compilers
+    state.description.compiler = res.description
 
-  state.settings = res.settings
-  document.querySelector('body').classList.add(state.settings.theme)
+    state.settings = res.settings
+    document.querySelector('body').classList.add(state.settings.theme)
 
-  m.redraw()
-}
+    m.redraw()
+  }
 
-chrome.runtime.sendMessage({message: 'popup'}, init)
+  chrome.runtime.sendMessage({message: 'popup'}, init)
 
-var oncreate = {
-  ripple: (vnode) => {
-    mdc.ripple.MDCRipple.attachTo(vnode.dom)
-  },
-  tabs: (vnode) => {
-    state._tabs = mdc.tabs.MDCTabBar.attachTo(vnode.dom)
-    setTimeout(() => {
-      state._tabs.activeTabIndex = state.tabs.indexOf(state.tab)
-    }, 250)
+  var oncreate = {
+    ripple: (vnode) => {
+      mdc.ripple.MDCRipple.attachTo(vnode.dom)
+    },
+    tabs: (vnode) => {
+      state._tabs = mdc.tabs.MDCTabBar.attachTo(vnode.dom)
+      setTimeout(() => {
+        state._tabs.activeTabIndex = state.tabs.indexOf(state.tab)
+      }, 250)
+    }
   }
-}
 
-var onupdate = (tab, key) => (vnode) => {
-  var value = tab === 'compiler' ? state.options[key]
-    : tab === 'content' ? state.content[key]
-    : null
+  var onupdate = (tab, key) => (vnode) => {
+    var value = tab === 'compiler' ? state.options[key]
+      : tab === 'content' ? state.content[key]
+      : null
 
-  if (vnode.dom.classList.contains('is-checked') !== value) {
-    vnode.dom.classList.toggle('is-checked')
+    if (vnode.dom.classList.contains('is-checked') !== value) {
+      vnode.dom.classList.toggle('is-checked')
+    }
   }
-}
 
-m.mount(document.querySelector('body'), {
-  view: (vnode) =>
+  var render = () =>
     m('#popup',
       // raw
       m('button.mdc-button mdc-button--raised m-button', {
@@ -302,4 +303,118 @@ m.mount(document.querySelector('body'), {
         'Advanced Options'
       )
     )
-})
+
+  var options = () =>
+    m('.row m-settings hidden',
+      m('.col-xxl-4.col-xl-4.col-lg-6.col-md-6.col-sm-12',
+        m('h3', 'Theme'),
+        m('.bs-callout m-theme',
+          m('.row',
+            m('.col-xxl-6.col-xl-6.col-lg-6.col-md-6.col-sm-12',
+              m('span.m-label',
+                'Content Theme'
+              )
+            ),
+            m('.col-xxl-6.col-xl-6.col-lg-6.col-md-6.col-sm-12',
+              m('select.mdc-elevation--z2 m-select', {
+                onchange: events.theme
+                },
+                state._themes.map((theme) =>
+                  m('option', {selected: state.theme === theme}, theme)
+                )
+              )
+            ),
+          ),
+          m('.row',
+            m('.col-xxl-6.col-xl-6.col-lg-6.col-md-6.col-sm-12',
+              m('span.m-label',
+                'Content Width'
+              )
+            ),
+            m('.col-xxl-6.col-xl-6.col-lg-6.col-md-6.col-sm-12',
+              m('select.mdc-elevation--z2 m-select', {
+                onchange: events.themes
+                },
+                state._width.map((width) =>
+                  m('option', {
+                    selected: state.themes.width === width,
+                  }, width)
+                )
+              )
+            ),
+          ),
+          settings.render()
+        ),
+      ),
+
+      m('.col-xxl-4.col-xl-4.col-lg-6.col-md-6.col-sm-12',
+        m('h3', 'Compiler'),
+        m('.bs-callout m-compiler',
+          m('select.mdc-elevation--z2 m-select', {
+            onchange: events.compiler.name
+            },
+            state.compilers.map((name) =>
+              m('option', {selected: state.compiler === name}, name)
+            )
+          ),
+          m('.scroll', {
+            class: Object.keys(state.options)
+              .filter((key) => typeof state.options[key] === 'boolean')
+              .length > 8
+              ? 'max' : ''
+            },
+            Object.keys(state.options)
+            .filter((key) => typeof state.options[key] === 'boolean')
+            .map((key) =>
+              m('label.mdc-switch m-switch', {
+                onupdate: onupdate('compiler', key),
+                title: state.description.compiler[key]
+                },
+                m('input.mdc-switch__native-control', {
+                  type: 'checkbox',
+                  name: key,
+                  checked: state.options[key],
+                  onchange: events.compiler.options
+                }),
+                m('.mdc-switch__background', m('.mdc-switch__knob')),
+                m('span.mdc-switch-label', key)
+              )
+            )
+          )
+        ),
+      ),
+
+      m('.col-xxl-4.col-xl-4.col-lg-6.col-md-6.col-sm-12',
+        m('h3', 'Content'),
+        m('.bs-callout m-content',
+          m('.scroll', Object.keys(state.content).map((key) =>
+            m('label.mdc-switch m-switch', {
+              onupdate: onupdate('content', key),
+              title: state.description.content[key]
+              },
+              m('input.mdc-switch__native-control', {
+                type: 'checkbox',
+                name: key,
+                checked: state.content[key],
+                onchange: events.content
+              }),
+              m('.mdc-switch__background', m('.mdc-switch__knob')),
+              m('span.mdc-switch-label', key)
+            ))
+          )
+        ),
+      ),
+    )
+
+  return {state, render, options}
+}
+
+if (document.querySelector('.is-popup')) {
+  var popup = Popup()
+  m.mount(document.querySelector('body'), {
+    view: (vnode) => popup.render()
+  })
+}
+else {
+  var settings = Settings()
+}