Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

move to vuepress #94

Open
8 tasks
Aratramba opened this issue Aug 9, 2018 · 3 comments
Open
8 tasks

move to vuepress #94

Aratramba opened this issue Aug 9, 2018 · 3 comments
Assignees

Comments

@Aratramba
Copy link
Owner

Aratramba commented Aug 9, 2018

let Design Manual only do the generating of components, let Vuepress handle the pages.

  • Add copyable vue single file component for embedding components
  • Add copyable vuepress config
  • Add output data json file alongside component html
  • Remove all page generating code
  • Remove static page analysis
  • Remove all page related configuration
  • Update docs (install instruction)
  • Add demo
@Aratramba Aratramba self-assigned this Aug 9, 2018
@Aratramba
Copy link
Owner Author

add output data json file alongisde component html

{
  "height": 100,
  "description": "<p></p>",
  "source": ""
}

@Aratramba
Copy link
Owner Author

add vue single file component for embedding components

<template>
  <div class="component">

    <!-- tools -->
    <div class="component__tools">

      <!-- code button -->
      <button v-on:click="toggleCodeView" class="component__tools__button" v-bind:class="{ 'active': showsource }" v-if="jsonLoaded && source">
        <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
          <path d="M0.7 9.3l4.8-4.8 1.4 1.42-4.060 4.080 4.070 4.070-1.41 1.42-5.5-5.49 0.7-0.7zM19.3 10.7l0.7-0.7-5.49-5.49-1.4 1.42 4.050 4.070-4.070 4.070 1.41 1.42 4.78-4.78z"></path>  
        </svg>
        <span>code</span>
      </button>

      <!-- link button -->
      <a :href="htmlFile" target="_blank" class="component__tools__button">
        <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
          <path d="M9.26 13c-0.167-0.286-0.266-0.63-0.266-0.996 0-0.374 0.103-0.724 0.281-1.023l-0.005 0.009c1.549-0.13 2.757-1.419 2.757-2.99 0-1.657-1.343-3-3-3-0.009 0-0.019 0-0.028 0l0.001-0h-4c-1.657 0-3 1.343-3 3s1.343 3 3 3v0h0.080c-0.053 0.301-0.083 0.647-0.083 1s0.030 0.699 0.088 1.036l-0.005-0.036h-0.080c-2.761 0-5-2.239-5-5s2.239-5 5-5v0h4c0.039-0.001 0.084-0.002 0.13-0.002 2.762 0 5.002 2.239 5.002 5.002 0 2.717-2.166 4.927-4.865 5l-0.007 0zM10.74 7c0.167 0.286 0.266 0.63 0.266 0.996 0 0.374-0.103 0.724-0.281 1.023l0.005-0.009c-1.549 0.13-2.757 1.419-2.757 2.99 0 1.657 1.343 3 3 3 0.009 0 0.019-0 0.028-0l-0.001 0h4c1.657 0 3-1.343 3-3s-1.343-3-3-3v0h-0.080c0.053-0.301 0.083-0.647 0.083-1s-0.030-0.699-0.088-1.036l0.005 0.036h0.080c2.761 0 5 2.239 5 5s-2.239 5-5 5v0h-4c-0.039 0.001-0.084 0.002-0.13 0.002-2.762 0-5.002-2.239-5.002-5.002 0-2.717 2.166-4.927 4.865-5l0.007-0z"></path>
        </svg>
        <span>{{ htmlFile }}</span>
      </a>
    </div>

    <!-- code view -->
    <div class="component__code" v-if="showsource && jsonLoaded && source">
      <pre class="language-html"><code v-html="prettifyHTML(source)"></code></pre>
    </div>
    
    <!-- component iframe -->
    <div class="component__preview" v-show="!showsource">

      <!-- resizer -->
      <span class="component__preview__handle">
        <span class="component__preview__handle__overlay"></span>
        <svg class="component__preview__handle__icon" width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
          <path d="M10 12c-1.105 0-2-0.895-2-2s0.895-2 2-2v0c1.105 0 2 0.895 2 2s-0.895 2-2 2v0zM10 6c-1.105 0-2-0.895-2-2s0.895-2 2-2v0c1.105 0 2 0.895 2 2s-0.895 2-2 2v0zM10 18c-1.105 0-2-0.895-2-2s0.895-2 2-2v0c1.105 0 2 0.895 2 2s-0.895 2-2 2v0z"></path>
        </svg>
      </span>

      <!-- height spacer -->
      <div ref="iframe_spacer" v-if="!htmlLoaded" v-bind:style="{ height: height + 'px' }"></div>

      <!-- component iframe -->
      <iframe class="component__preview__iframe" ref="iframe" v-if="inview" :src="htmlFile" frameborder="0" scrolling="no" v-on:load="onIframeLoad"></iframe>
    </div>
  </div>
</template>

<script>
export default {
  props: ["name"],
  data() {
    return {
      htmlLoaded: false,
      jsonLoaded: false,
      height: 0,
      source: null,
      showsource: false,
      inview: false,
      htmlFile: this.getHTMLFilePath(this.$props.name),
      jsonFile: this.getJSONFilePath(this.$props.name),
    };
  },
  mounted() {
    /**
     * set in view observer for async loading iframe
     */

    var observer = new IntersectionObserver(
      function(entries, observer) {
        entries.forEach(
          function(entry) {
            if (entry.isIntersecting) {
              if (!this.inview) {
                this.inview = true;
              }
            }
          }.bind(this)
        );
      }.bind(this)
    );
    observer.observe(this.$el);

    /**
     * get meta info from lib/file.json
     */

    fetch(this.jsonFile).then((res) => {
      if (res.status === 200) {
        return res.json();
      }
    }).then((obj) => {
      this.jsonLoaded = true;

      if (obj) {
        this.height = obj.height;
        this.source = obj.source;
      }
    }).catch((err) => {});
  },
  methods: {

    /**
     * get html file path
     */

    getHTMLFilePath: function(str) {
      return "/lib/" + this.slugify(str) + ".html";
    },

    /**
     * get json file path
     */

    getJSONFilePath: function(str) {
      return "/lib/" + this.slugify(str) + ".json";
    },

    /**
     * beautify and highlight html
     */
    prettifyHTML: function(str) {
      return window.Prism.highlight(window.html_beautify(str), window.Prism.languages.markup)
    },

    /**
     * create slug-from-string
     */

    slugify: function(str) {
      return str
        .toString()
        .toLowerCase()
        .replace(/\s+/g, "-") // Replace spaces with -
        .replace(/[^\w-]+/g, "") // Remove all non-word chars
        .replace(/--+/g, "-") // Replace multiple - with single -
        .replace(/^-+/, "") // Trim - from start of text
        .replace(/-+$/, ""); // Trim - from end of text
    },

    /**
     * toggle code/preview view
     */

    toggleCodeView: function (e) {
      this.showsource = !this.showsource;
      
      if (!this.showsource) {
        window.iFrameResize({ checkOrigin: false }, this.$refs.iframe);
      }
    },

    /**
     * iframe loaded handler
     */

    onIframeLoad: function(e) {

      // resize iframe
      window.iFrameResize({ checkOrigin: false }, this.$refs.iframe);

      // make preview draggable
      window.interact(this.$el.querySelector(".component__preview")).resizable({
        edges: {
          left: false,
          right: ".component__preview__handle",
          bottom: false,
          top: false
        },
        onmove: function(e) {
          e.target.style.width = e.rect.width - 24 + "px";
          e.target.querySelector('iframe').contentWindow.parentIFrame.size();
          if (!e.target.classList.contains("component-is-resizing")) {
            e.target.classList.add("component-is-resizing");
          }
        },
        onend: function(e) {
          e.target.querySelector("iframe").contentWindow.parentIFrame.size();
          if (e.target.classList.contains("component-is-resizing")) {
            e.target.classList.remove("component-is-resizing");
          }
        }
      });

      // set loaded state
      this.htmlLoaded = true;
    }
  }
};
</script>

<style scoped>
iframe {
  width: 100%;
}

.component {
  --grey: #eaecef;
  --darkgrey: #111;
  margin-top: 20px;
  margin-bottom: 150px;
}

/**
 * Tools
 */

.component__tools {
  display: flex;
}

.component__tools__button {
  border: 1px solid var(--grey);
  border-radius: 3px;
  padding: 6px 8px;
  margin-left: 5px;
  display: inline-flex;
  outline: 0;
  text-decoration: none !important;
  cursor: pointer;
}

.component__tools__button:hover,
.component__tools__button.active {
  background-color: var(--grey);
}

.component__tools__button svg {
  margin: auto;
}

.component__tools__button span {
  font-size: 12px;
  font-weight: normal;
  color: var(--darkgrey);
  margin: auto 0 auto 6px;
}

/**
 * Code
 */

.component__code {
  max-width: 100vw;
  margin-top: 20px;
  width: 1200px;
  transform: translateX(-50%) translateX(370px);
  position: relative;
  min-width: 275px;
}

/**
 * Preview
 */

.component__preview {
  max-width: 100vw;
  margin-top: 20px;
  width: 1200px;
  transform: translateX(-50%) translateX(370px);
  position: relative;
  min-width: 275px;
  padding-right: 24px;
  border: 1px solid var(--grey);
}

.component__preview__iframe {
  display: block;
  width: 100%;
}

/**
 * Resize handle
 */

.component__preview__handle {
  display: block;
  position: absolute;
  width: 24px;
  height: 100%;
  right: 0;
  top: 0;
  bottom: 0;
}

.component-is-resizing >>> .component__preview__handle {
  left: 0;
  width: 100%;
}

.component__preview__handle__overlay {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 24px;
  content: "";
  background-color: white;
  transition: background-color 0.15s, border-color 0.15s;
  border-left: 1px solid var(--grey);
}

.component__preview__handle:hover >>> .component__preview__handle__overlay,
.component-is-resizing >>> .component__preview__handle__overlay {
  background-color: #f5f5f5;
  border-color: var(--grey);
}

/**
 * Resize handle icon
 */

.component__preview__handle__icon {
  display: block;
  width: 20px;
  height: 20px;
  position: absolute;
  top: 50%;
  right: 2px;
  transform: translate(0, -50%);
  opacity: 0.25;
  transition: opacity 0.15s;
}

.component-is-resizing >>> .component__preview__handle__icon {
  opacity: 0.5;
}
</style>

@Aratramba
Copy link
Owner Author

Add copyable vuepress config

module.exports = {
  title: "Design Manual",
  description: "this is my design manual",
  head: [
    ['script', { src: 'https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/3.6.0/iframeResizer.min.js' }],
    ['script', { src: 'https://cdnjs.cloudflare.com/ajax/libs/vanilla-lazyload/10.14.0/lazyload.min.js' }],
    ['script', { src: 'https://unpkg.com/[email protected]/dist/interact.min.js' }],
    ['script', { src: 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.14.0/prism.min.js' }],
    ['script', { src: 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.14.0/components/prism-markup-templating.js' }],
    ['script', { src: 'https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.7.5/beautify-html.min.js' }],
  ],
  themeConfig: {
    nav: [
      { text: "Home", link: "/" },
      { text: "Guide", link: "/guide/" },
      { text: "External", link: "https://google.com" }
    ],
    sidebar: [
      {
        title: "Components",
        collapsable: false,
        children: ["/"]
      },
      {
        title: "Content",
        children: [
          /* ... */
        ]
      },
      {
        title: "Whatever",
        children: [
          /* ... */
        ]
      }
    ]
  }
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant