icons
This commit is contained in:
parent
eb34393407
commit
a6cf7c1b16
@ -1,190 +1,49 @@
|
||||
<template>
|
||||
<span class="icon" :class="sizeClass" @click="$emit('click', $event)" ref="container">
|
||||
|
||||
<span class="icon" :class="iconClasses" @click="$emit('click', $event)">
|
||||
<app-iconic-icon :icon="iconicIcon" :size="iconicSize" v-bind="iconicAttributes"></app-iconic-icon>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import IconicJs from "../iconic/js/iconic.min";
|
||||
|
||||
import Caret from "../iconic/svg/smart/caret";
|
||||
import Check from "../iconic/svg/smart/check";
|
||||
import CircleCheck from "../iconic/svg/smart/circle-check";
|
||||
import Link from "../iconic/svg/smart/link";
|
||||
import Lock from "../iconic/svg/smart/lock";
|
||||
import Menu from "../iconic/svg/smart/menu";
|
||||
import Person from "../iconic/svg/smart/person";
|
||||
import Pencil from "../iconic/svg/smart/pencil";
|
||||
import Star from "../iconic/svg/smart/star";
|
||||
import StarEmpty from "../iconic/svg/smart/star-empty";
|
||||
import X from "../iconic/svg/smart/x";
|
||||
|
||||
const SVG_CACHE = {};
|
||||
let REMAP_COUNT = 0;
|
||||
|
||||
class IconData {
|
||||
constructor(svgData, dataAttributes) {
|
||||
this.svgData = svgData;
|
||||
constructor(iconicIcon, dataAttributes) {
|
||||
this.iconicIcon = iconicIcon;
|
||||
this.dataAttributes = dataAttributes || {};
|
||||
this.svgTemplate = null;
|
||||
}
|
||||
|
||||
getSvg() {
|
||||
if (this.svgTemplate === null) {
|
||||
const iconicName = this.svgData.attributes.class;
|
||||
|
||||
this.svgTemplate = SVG_CACHE[iconicName] || null;
|
||||
|
||||
if (this.svgTemplate === null) {
|
||||
this.svgTemplate = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
||||
SVG_CACHE[iconicName] = this.svgTemplate;
|
||||
|
||||
for (let attr in this.svgData.attributes) {
|
||||
this.svgTemplate.setAttribute(attr, this.svgData.attributes[attr]);
|
||||
}
|
||||
this.svgTemplate.innerHTML = this.svgData.content;
|
||||
|
||||
|
||||
// Find then prune the scripts
|
||||
const scripts = [...this.svgTemplate.querySelectorAll('script')];
|
||||
|
||||
scripts.filter(s => {
|
||||
let scriptType = s.getAttribute("type");
|
||||
return !scriptType || scriptType === 'application/ecmascript' || scriptType === 'application/javascript'
|
||||
}).forEach(s => {
|
||||
new Function(s.innerText || s.textContent)(window);
|
||||
this.svgTemplate.removeChild(s);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const clone = this.svgTemplate.cloneNode(true);
|
||||
this.remapIds(clone);
|
||||
this.attachIconicApi(clone);
|
||||
for (let attr in this.dataAttributes) {
|
||||
clone.setAttribute(`data-${attr}`, this.dataAttributes[attr]);
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
remapIds(svg) {
|
||||
const iriElementsAndProperties = {
|
||||
'clipPath': ['clip-path'],
|
||||
'color-profile': ['color-profile'],
|
||||
'cursor': ['cursor'],
|
||||
'filter': ['filter'],
|
||||
'linearGradient': ['fill', 'stroke'],
|
||||
'marker': ['marker', 'marker-start', 'marker-mid', 'marker-end'],
|
||||
'mask': ['mask'],
|
||||
'pattern': ['fill', 'stroke'],
|
||||
'radialGradient': ['fill', 'stroke']
|
||||
};
|
||||
|
||||
REMAP_COUNT += 1;
|
||||
|
||||
let element, elementDefs, properties, currentId, newId;
|
||||
Object.keys(iriElementsAndProperties).forEach(function (key) {
|
||||
element = key;
|
||||
properties = iriElementsAndProperties[key];
|
||||
|
||||
elementDefs = svg.querySelectorAll('defs ' + element + '[id]');
|
||||
for (var i = 0, elementsLen = elementDefs.length; i < elementsLen; i++) {
|
||||
currentId = elementDefs[i].id;
|
||||
newId = currentId + '-' + REMAP_COUNT;
|
||||
|
||||
// All of the properties that can reference this element type
|
||||
var referencingElements;
|
||||
properties.forEach(function (property) {
|
||||
// :NOTE: using a substring match attr selector here to deal with IE "adding extra quotes in url() attrs"
|
||||
referencingElements = svg.querySelectorAll('[' + property + '*="' + currentId + '"]');
|
||||
for (var j = 0, referencingElementLen = referencingElements.length; j < referencingElementLen; j++) {
|
||||
referencingElements[j].setAttribute(property, 'url(#' + newId + ')');
|
||||
}
|
||||
});
|
||||
|
||||
elementDefs[i].id = newId;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
attachIconicApi(svg) {
|
||||
const key = svg.getAttribute("data-icon");
|
||||
const apis = window.iconicSmartIconApis;
|
||||
if (key && apis[key]) {
|
||||
const iconApi = apis[key](svg);
|
||||
for (let func in iconApi) svg[func] = iconApi[func]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SizeData {
|
||||
constructor(bulmaIconClass, defaultPadding) {
|
||||
constructor(bulmaIconClass, iconicSize, customClass) {
|
||||
this.bulmaIconClass = bulmaIconClass;
|
||||
this.defaultPadding = defaultPadding || null;
|
||||
this.iconicSize = iconicSize || null;
|
||||
this.customIconClass = customClass || null;
|
||||
}
|
||||
}
|
||||
|
||||
class IconicQueue {
|
||||
constructor(iconicInstance) {
|
||||
this.iconic = iconicInstance;
|
||||
this.updateQueue = [];
|
||||
this.isTimerRunning = false;
|
||||
}
|
||||
|
||||
processQueues() {
|
||||
if (this.updateQueue.length > 0) {
|
||||
console.log(`updating ${this.updateQueue.length}`);
|
||||
this.iconic.update(this.updateQueue);
|
||||
this.updateQueue.forEach(s => (s.style.visibility = null));
|
||||
this.updateQueue = [];
|
||||
}
|
||||
|
||||
this.isTimerRunning = false;
|
||||
}
|
||||
|
||||
ensureTimer() {
|
||||
if (!this.isTimerRunning) {
|
||||
this.isTimerRunning = true;
|
||||
setTimeout(() => this.processQueues());
|
||||
}
|
||||
}
|
||||
|
||||
updateSvg(svgElem) {
|
||||
this.updateQueue.push(svgElem);
|
||||
this.ensureTimer();
|
||||
}
|
||||
}
|
||||
|
||||
const iconicInstance = IconicJs({
|
||||
autoInjectSelector: "#notreal-noinjection"
|
||||
});
|
||||
|
||||
const iconicQueue = new IconicQueue(iconicInstance);
|
||||
|
||||
const iconMap = {
|
||||
'caret-bottom': new IconData(Caret, {direction: 'bottom'}),
|
||||
'caret-top': new IconData(Caret, {direction: 'top'}),
|
||||
check: new IconData(Check),
|
||||
'circle-check': new IconData(CircleCheck),
|
||||
'link-broken': new IconData(Link, {state: 'broken'}),
|
||||
'link-intact': new IconData(Link, {state: 'intact'}),
|
||||
'lock-locked': new IconData(Lock, {state: 'locked'}),
|
||||
'lock-unlocked': new IconData(Lock, {state: 'unlocked'}),
|
||||
menu: new IconData(Menu),
|
||||
pencil: new IconData(Pencil),
|
||||
person: new IconData(Person),
|
||||
star: new IconData(Star),
|
||||
'star-empty': new IconData(StarEmpty),
|
||||
x: new IconData(X)
|
||||
'caret-bottom': new IconData('caret', {'data-direction': 'bottom'}),
|
||||
'caret-top': new IconData('caret', {'data-direction': 'top'}),
|
||||
check: new IconData('check'),
|
||||
'circle-check': new IconData('circle-check'),
|
||||
'link-broken': new IconData('link', {'data-state': 'broken'}),
|
||||
'link-intact': new IconData('link', {'data-state': 'intact'}),
|
||||
'lock-locked': new IconData('lock', {'data-state': 'locked'}),
|
||||
'lock-unlocked': new IconData('lock', {'data-state': 'unlocked'}),
|
||||
menu: new IconData('menu'),
|
||||
pencil: new IconData('pencil'),
|
||||
person: new IconData('person'),
|
||||
star: new IconData('star'),
|
||||
'star-empty': new IconData('star-empty'),
|
||||
x: new IconData('x')
|
||||
};
|
||||
|
||||
const sizeMap = {
|
||||
xs: new SizeData('is-small', '25%'),
|
||||
sm: new SizeData('is-small'),
|
||||
md: new SizeData(''),
|
||||
lg: new SizeData('is-medium'),
|
||||
xl: new SizeData('is-large')
|
||||
xs: new SizeData('is-small', 'sm', 'is-xs'),
|
||||
sm: new SizeData('is-small', 'sm'),
|
||||
md: new SizeData('', 'sm', 'is-md'),
|
||||
lg: new SizeData('is-medium', 'md'),
|
||||
xl: new SizeData('is-large', 'md', 'is-xl')
|
||||
};
|
||||
|
||||
export default {
|
||||
@ -220,45 +79,24 @@
|
||||
return sizeMap[this.size];
|
||||
},
|
||||
|
||||
sizeClass() {
|
||||
return this.sizeData.bulmaIconClass;
|
||||
iconClasses() {
|
||||
return [
|
||||
this.sizeData.bulmaIconClass,
|
||||
this.sizeData.customIconClass
|
||||
]
|
||||
},
|
||||
|
||||
svgPadding() {
|
||||
return this.padding || this.sizeData.defaultPadding || "15%";
|
||||
}
|
||||
iconicSize() {
|
||||
return this.sizeData.iconicSize;
|
||||
},
|
||||
|
||||
methods: {
|
||||
insertSvg() {
|
||||
const parent = this.$refs.container;
|
||||
|
||||
while (parent.firstChild) {
|
||||
parent.removeChild(parent.firstChild);
|
||||
}
|
||||
|
||||
const svg = this.iconData.getSvg();
|
||||
this.injectedSvg = svg;
|
||||
|
||||
svg.style.padding = this.svgPadding;
|
||||
svg.style.visibility = "hidden";
|
||||
svg.classList.add("iconic-fluid");
|
||||
parent.appendChild(svg);
|
||||
iconicQueue.updateSvg(svg);
|
||||
}
|
||||
iconicIcon() {
|
||||
return this.iconData.iconicIcon;
|
||||
},
|
||||
|
||||
mounted() {
|
||||
let self = this;
|
||||
this.$watch(
|
||||
function() { return this.icon + this.size + this.padding },
|
||||
function() {
|
||||
this.insertSvg();
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
iconicAttributes() {
|
||||
return this.iconData.dataAttributes;
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -266,6 +104,41 @@
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
span.icon.is-xs {
|
||||
svg.iconic {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
span.icon.is-sm {
|
||||
svg.iconic {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
span.icon.is-md {
|
||||
svg.iconic {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
span.icon.is-lg {
|
||||
svg.iconic {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
span.icon.is-xl {
|
||||
svg.iconic {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</style>
|
151
app/javascript/components/AppIconicIcon.vue
Normal file
151
app/javascript/components/AppIconicIcon.vue
Normal file
@ -0,0 +1,151 @@
|
||||
<template>
|
||||
<svg v-bind="svgAttributes" v-html="svgContent" :class="calculatedClasses"></svg>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import Caret from "../iconic/svg/smart/caret";
|
||||
import Check from "../iconic/svg/smart/check";
|
||||
import CircleCheck from "../iconic/svg/smart/circle-check";
|
||||
import Link from "../iconic/svg/smart/link";
|
||||
import Lock from "../iconic/svg/smart/lock";
|
||||
import Menu from "../iconic/svg/smart/menu";
|
||||
import Person from "../iconic/svg/smart/person";
|
||||
import Pencil from "../iconic/svg/smart/pencil";
|
||||
import Star from "../iconic/svg/smart/star";
|
||||
import StarEmpty from "../iconic/svg/smart/star-empty";
|
||||
import X from "../iconic/svg/smart/x";
|
||||
|
||||
const APIS = {};
|
||||
const LOADED_APIS = {};
|
||||
|
||||
window._Iconic = {
|
||||
smartIconApis: APIS
|
||||
};
|
||||
|
||||
let globalIdCounter = 0;
|
||||
|
||||
const iconMap = {
|
||||
caret: Caret,
|
||||
check: Check,
|
||||
'circle-check': CircleCheck,
|
||||
link: Link,
|
||||
lock: Lock,
|
||||
menu: Menu,
|
||||
pencil: Pencil,
|
||||
person: Person,
|
||||
star: Star,
|
||||
'star-empty': StarEmpty,
|
||||
x: X
|
||||
};
|
||||
|
||||
export default {
|
||||
props: {
|
||||
icon: {
|
||||
type: String,
|
||||
required: true,
|
||||
validator: (i) => iconMap[i] !== undefined
|
||||
},
|
||||
|
||||
size: {
|
||||
type: String,
|
||||
default: "lg",
|
||||
validator: (s) => ["sm", "md", "lg"].indexOf(s) >= 0
|
||||
},
|
||||
|
||||
iconSizeOverride: {
|
||||
type: String,
|
||||
validator: (s) => ["sm", "md", "lg", null].indexOf(s) >= 0
|
||||
},
|
||||
|
||||
displaySizeOverride: {
|
||||
type: String,
|
||||
validator: (s) => ["sm", "md", "lg", null].indexOf(s) >= 0
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
calculatedClasses: []
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
svgData() {
|
||||
return iconMap[this.icon];
|
||||
},
|
||||
|
||||
svgAttributes() {
|
||||
return this.svgData.attributes;
|
||||
},
|
||||
|
||||
svgName() {
|
||||
return this.svgAttributes['data-icon'];
|
||||
},
|
||||
|
||||
svgContent() {
|
||||
let content = String(this.svgData.content);
|
||||
|
||||
for (let idRep of this.svgData.idReplacements) {
|
||||
let newId = `__new_id_${globalIdCounter}`;
|
||||
globalIdCounter += 1;
|
||||
|
||||
content = content.replace(new RegExp(idRep, "g"), newId);
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
rebind() {
|
||||
const apis = APIS;
|
||||
|
||||
if (apis && this.svgName && apis[this.svgName]) {
|
||||
const iconApi = apis[this.svgName](this.$el);
|
||||
for (let func in iconApi) this.$el[func] = iconApi[func]
|
||||
} else {
|
||||
this.$el.update = function() {}
|
||||
}
|
||||
|
||||
this.calculatedClasses = (this.svgAttributes.class || "").split(" ");
|
||||
|
||||
this.calculatedClasses.push(`iconic-${this.size}`);
|
||||
|
||||
if (this.iconSizeOverride) {
|
||||
this.calculatedClasses.push(`iconic-icon-${this.iconSizeOverride}`);
|
||||
}
|
||||
|
||||
if (this.displaySizeOverride) {
|
||||
this.calculatedClasses.push(`iconic-size-${this.displaySizeOverride}`);
|
||||
}
|
||||
|
||||
this.$el.update();
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
if (LOADED_APIS[this.svgName] !== true) {
|
||||
for (let sb of this.svgData.scriptBlocks) {
|
||||
new Function(sb)(window);
|
||||
}
|
||||
LOADED_APIS[this.svgName] = true;
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
|
||||
this.$watch(
|
||||
function() { return [this.$attrs, this.icon, this.fluid] },
|
||||
function() {
|
||||
this.rebind()
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
@ -1,10 +1,12 @@
|
||||
import '../styles';
|
||||
import "vue-resize/dist/vue-resize";
|
||||
|
||||
import Vue from 'vue'
|
||||
import { sync } from 'vuex-router-sync';
|
||||
import { swInit } from "../lib/ServiceWorker";
|
||||
import responsiveSync from "../lib/VuexResponsiveSync";
|
||||
import VueProgressBar from "vue-progressbar";
|
||||
import VueResize from "vue-resize";
|
||||
import config from '../config';
|
||||
import store from '../store';
|
||||
import router from '../router';
|
||||
@ -18,6 +20,7 @@ import AppDatePicker from "../components/AppDatePicker";
|
||||
import AppDropdown from "../components/AppDropdown";
|
||||
import AppExpandTransition from "../components/AppExpandTransition";
|
||||
import AppIcon from "../components/AppIcon";
|
||||
import AppIconicIcon from "../components/AppIconicIcon";
|
||||
import AppModal from "../components/AppModal";
|
||||
import AppNavbar from "../components/AppNavbar";
|
||||
import AppPager from "../components/AppPager";
|
||||
@ -33,6 +36,7 @@ Vue.component("AppDatePicker", AppDatePicker);
|
||||
Vue.component("AppDropdown", AppDropdown);
|
||||
Vue.component("AppExpandTransition", AppExpandTransition);
|
||||
Vue.component("AppIcon", AppIcon);
|
||||
Vue.component("AppIconicIcon", AppIconicIcon);
|
||||
Vue.component("AppModal", AppModal);
|
||||
Vue.component("AppNavbar", AppNavbar);
|
||||
Vue.component("AppPager", AppPager);
|
||||
@ -56,6 +60,8 @@ Vue.use(VueProgressBar, {
|
||||
// inverse: false
|
||||
});
|
||||
|
||||
Vue.use(VueResize);
|
||||
|
||||
sync(store, router);
|
||||
swInit(store);
|
||||
responsiveSync(store);
|
||||
|
@ -1,3 +1,17 @@
|
||||
/* Iconic Responsive Support Styles */
|
||||
.iconic-property-fill, .iconic-property-text {stroke: none !important;}
|
||||
.iconic-property-stroke {fill: none !important;}
|
||||
svg.iconic.iconic-fluid {height:100% !important;width:100% !important;}
|
||||
svg.iconic.iconic-sm:not(.iconic-size-md):not(.iconic-size-lg), svg.iconic.iconic-size-sm{width:16px;height:16px;}
|
||||
svg.iconic.iconic-md:not(.iconic-size-sm):not(.iconic-size-lg), svg.iconic.iconic-size-md{width:32px;height:32px;}
|
||||
svg.iconic.iconic-lg:not(.iconic-size-sm):not(.iconic-size-md), svg.iconic.iconic-size-lg{width:128px;height:128px;}
|
||||
svg.iconic-sm > g.iconic-md, svg.iconic-sm > g.iconic-lg, svg.iconic-md > g.iconic-sm, svg.iconic-md > g.iconic-lg, svg.iconic-lg > g.iconic-sm, svg.iconic-lg > g.iconic-md {display: none;}
|
||||
svg.iconic.iconic-icon-sm > g.iconic-lg, svg.iconic.iconic-icon-md > g.iconic-lg {display:none;}
|
||||
svg.iconic-sm:not(.iconic-icon-md):not(.iconic-icon-lg) > g.iconic-sm, svg.iconic-md.iconic-icon-sm > g.iconic-sm, svg.iconic-lg.iconic-icon-sm > g.iconic-sm {display:inline;}
|
||||
svg.iconic-md:not(.iconic-icon-sm):not(.iconic-icon-lg) > g.iconic-md, svg.iconic-sm.iconic-icon-md > g.iconic-md, svg.iconic-lg.iconic-icon-md > g.iconic-md {display:inline;}
|
||||
svg.iconic-lg:not(.iconic-icon-sm):not(.iconic-icon-md) > g.iconic-lg, svg.iconic-sm.iconic-icon-lg > g.iconic-lg, svg.iconic-md.iconic-icon-lg > g.iconic-lg {display:inline;}
|
||||
|
||||
|
||||
@mixin iconic-color($color) {
|
||||
fill: $color;
|
||||
stroke: $color;
|
||||
|
81
config/webpack/loaders/iconic_svg_loader.js
Normal file
81
config/webpack/loaders/iconic_svg_loader.js
Normal file
@ -0,0 +1,81 @@
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
const iriElementsAndProperties = {
|
||||
'clipPath': ['clip-path'],
|
||||
'color-profile': ['color-profile'],
|
||||
'cursor': ['cursor'],
|
||||
'filter': ['filter'],
|
||||
'linearGradient': ['fill', 'stroke'],
|
||||
'marker': ['marker', 'marker-start', 'marker-mid', 'marker-end'],
|
||||
'mask': ['mask'],
|
||||
'pattern': ['fill', 'stroke'],
|
||||
'radialGradient': ['fill', 'stroke']
|
||||
};
|
||||
|
||||
module.exports = function(content) {
|
||||
this.cacheable && this.cacheable();
|
||||
|
||||
const $ = cheerio.load(content, {
|
||||
lowerCaseTags: false
|
||||
});
|
||||
|
||||
let idReplacements = [];
|
||||
|
||||
for(let element in iriElementsAndProperties) {
|
||||
let properties = iriElementsAndProperties[element];
|
||||
|
||||
$(`svg defs ${element}[id]`).each(function() {
|
||||
const $elem = $(this);
|
||||
const id = $elem.attr("id");
|
||||
const newId = `__ICONIC_SVG_REPLACEMENT_${idReplacements.length}`;
|
||||
idReplacements.push(newId);
|
||||
|
||||
$elem.attr("id", newId);
|
||||
|
||||
for (let property of properties) {
|
||||
$(`svg *[${property}="url(#${id})"]`).each(function() {
|
||||
const $elem = $(this);
|
||||
$elem.attr(property, `url(#${newId})`);
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const $svg = $("svg");
|
||||
let iconName = $svg.attr("data-icon");
|
||||
|
||||
if (!iconName) {
|
||||
const match = $svg.attr("class").match(/iconic-([a-z\-]+)/);
|
||||
if (match) {
|
||||
$svg.attr("data-icon", match[1]);
|
||||
} else {
|
||||
throw "Can't parse class into data-icon";
|
||||
}
|
||||
}
|
||||
|
||||
const scriptBlocks = [];
|
||||
|
||||
// Find then prune the scripts
|
||||
$("svg script").each(function() {
|
||||
const $script = $(this);
|
||||
const scriptType = $script.attr("type");
|
||||
if (!scriptType || scriptType === 'application/ecmascript' || scriptType === 'application/javascript') {
|
||||
scriptBlocks.push($script.html());
|
||||
}
|
||||
});
|
||||
|
||||
$("svg script").remove();
|
||||
|
||||
|
||||
const attributes = $svg.get(0).attribs;
|
||||
const svgMarkup = $("svg").html();
|
||||
|
||||
|
||||
return `module.exports = ${JSON.stringify({
|
||||
attributes: attributes,
|
||||
content: svgMarkup,
|
||||
idReplacements: idReplacements,
|
||||
scriptBlocks: scriptBlocks
|
||||
})}`;
|
||||
|
||||
};
|
@ -1,9 +1,9 @@
|
||||
const path = require("path");
|
||||
|
||||
module.exports = {
|
||||
test: /\.svg$/,
|
||||
test: /\/iconic\/svg\/.*\.svg$/,
|
||||
use: [{
|
||||
loader: path.join(__dirname, 'svg_loader.js')
|
||||
loader: path.join(__dirname, 'iconic_svg_loader.js')
|
||||
}]
|
||||
};
|
||||
|
||||
|
@ -1,27 +0,0 @@
|
||||
module.exports = function(content) {
|
||||
this.cacheable && this.cacheable();
|
||||
|
||||
var match = content.match(/<svg([^>]+)+>([\s\S]+)<\/svg>/i);
|
||||
var attrs = {};
|
||||
|
||||
if (match) {
|
||||
attrs = match[1];
|
||||
if (attrs) {
|
||||
attrs = attrs.match(/([\w-:]+)(=)?("[^<>"]*"|'[^<>']*'|[\w-:]+)/g)
|
||||
.reduce(function(obj, attr){
|
||||
var split = attr.split('=');
|
||||
var name = split[0];
|
||||
var value = true;
|
||||
if (split && split[1]) {
|
||||
value = split[1].replace(/['"]/g, '');
|
||||
}
|
||||
obj[name] = value;
|
||||
return obj;
|
||||
}, {})
|
||||
}
|
||||
|
||||
content = match[2] || '';
|
||||
};
|
||||
|
||||
return "module.exports = " + JSON.stringify({attributes: attrs, content: content});
|
||||
};
|
@ -4,6 +4,7 @@
|
||||
"autosize": "^4.0.1",
|
||||
"bulma": "^0.7.1",
|
||||
"caniuse-lite": "^1.0.30000815",
|
||||
"cheerio": "^1.0.0-rc.2",
|
||||
"css-loader": "^0.28.11",
|
||||
"lodash": "^4.17.5",
|
||||
"svg-loader": "^0.0.2",
|
||||
@ -11,6 +12,7 @@
|
||||
"vue": "^2.5.16",
|
||||
"vue-loader": "^14.2.2",
|
||||
"vue-progressbar": "^0.7.4",
|
||||
"vue-resize": "^0.4.4",
|
||||
"vue-router": "^3.0.1",
|
||||
"vue-template-compiler": "^2.5.16",
|
||||
"vuex": "^3.0.1",
|
||||
|
100
yarn.lock
100
yarn.lock
@ -32,6 +32,10 @@
|
||||
webpack "^3.12.0"
|
||||
webpack-manifest-plugin "^1.3.2"
|
||||
|
||||
"@types/node@*":
|
||||
version "10.9.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.9.4.tgz#0f4cb2dc7c1de6096055357f70179043c33e9897"
|
||||
|
||||
abbrev@1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
|
||||
@ -872,6 +876,10 @@ bonjour@^3.5.0:
|
||||
multicast-dns "^6.0.1"
|
||||
multicast-dns-service-types "^1.1.0"
|
||||
|
||||
boolbase@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||
@ -1130,6 +1138,17 @@ chalk@^2.0.1, chalk@^2.4.1:
|
||||
escape-string-regexp "^1.0.5"
|
||||
supports-color "^5.3.0"
|
||||
|
||||
cheerio@^1.0.0-rc.2:
|
||||
version "1.0.0-rc.2"
|
||||
resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.2.tgz#4b9f53a81b27e4d5dac31c0ffd0cfa03cc6830db"
|
||||
dependencies:
|
||||
css-select "~1.2.0"
|
||||
dom-serializer "~0.1.0"
|
||||
entities "~1.1.1"
|
||||
htmlparser2 "^3.9.1"
|
||||
lodash "^4.15.0"
|
||||
parse5 "^3.0.1"
|
||||
|
||||
chokidar@^2.0.0, chokidar@^2.0.2:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26"
|
||||
@ -1522,6 +1541,15 @@ css-loader@^0.28.11:
|
||||
postcss-value-parser "^3.3.0"
|
||||
source-list-map "^2.0.0"
|
||||
|
||||
css-select@~1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858"
|
||||
dependencies:
|
||||
boolbase "~1.0.0"
|
||||
css-what "2.1"
|
||||
domutils "1.5.1"
|
||||
nth-check "~1.0.1"
|
||||
|
||||
css-selector-tokenizer@^0.7.0:
|
||||
version "0.7.0"
|
||||
resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz#e6988474ae8c953477bf5e7efecfceccd9cf4c86"
|
||||
@ -1534,6 +1562,10 @@ css-unit-converter@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.1.tgz#d9b9281adcfd8ced935bdbaba83786897f64e996"
|
||||
|
||||
css-what@2.1:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd"
|
||||
|
||||
cssesc@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4"
|
||||
@ -1746,10 +1778,45 @@ dns-txt@^2.0.2:
|
||||
dependencies:
|
||||
buffer-indexof "^1.0.0"
|
||||
|
||||
dom-serializer@0, dom-serializer@~0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82"
|
||||
dependencies:
|
||||
domelementtype "~1.1.1"
|
||||
entities "~1.1.1"
|
||||
|
||||
domain-browser@^1.1.1:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda"
|
||||
|
||||
domelementtype@1, domelementtype@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2"
|
||||
|
||||
domelementtype@~1.1.1:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b"
|
||||
|
||||
domhandler@^2.3.0:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803"
|
||||
dependencies:
|
||||
domelementtype "1"
|
||||
|
||||
domutils@1.5.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf"
|
||||
dependencies:
|
||||
dom-serializer "0"
|
||||
domelementtype "1"
|
||||
|
||||
domutils@^1.5.1:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"
|
||||
dependencies:
|
||||
dom-serializer "0"
|
||||
domelementtype "1"
|
||||
|
||||
duplexify@^3.4.2, duplexify@^3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.6.0.tgz#592903f5d80b38d037220541264d69a198fb3410"
|
||||
@ -1809,6 +1876,10 @@ enhanced-resolve@^3.4.0:
|
||||
object-assign "^4.0.1"
|
||||
tapable "^0.2.7"
|
||||
|
||||
entities@^1.1.1, entities@~1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0"
|
||||
|
||||
errno@^0.1.3, errno@~0.1.7:
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618"
|
||||
@ -2530,6 +2601,17 @@ html-entities@^1.2.0:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f"
|
||||
|
||||
htmlparser2@^3.9.1:
|
||||
version "3.9.2"
|
||||
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338"
|
||||
dependencies:
|
||||
domelementtype "^1.3.0"
|
||||
domhandler "^2.3.0"
|
||||
domutils "^1.5.1"
|
||||
entities "^1.1.1"
|
||||
inherits "^2.0.1"
|
||||
readable-stream "^2.0.2"
|
||||
|
||||
http-deceiver@^1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87"
|
||||
@ -3180,7 +3262,7 @@ lodash.uniq@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
|
||||
|
||||
"lodash@>=3.5 <5", lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.17.5, lodash@~4.17.10:
|
||||
"lodash@>=3.5 <5", lodash@^4.0.0, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.17.5, lodash@~4.17.10:
|
||||
version "4.17.10"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7"
|
||||
|
||||
@ -3647,6 +3729,12 @@ npm-run-path@^2.0.0:
|
||||
gauge "~2.7.3"
|
||||
set-blocking "~2.0.0"
|
||||
|
||||
nth-check@~1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.1.tgz#9929acdf628fc2c41098deab82ac580cf149aae4"
|
||||
dependencies:
|
||||
boolbase "~1.0.0"
|
||||
|
||||
num2fraction@^1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
|
||||
@ -3842,6 +3930,12 @@ parse-json@^4.0.0:
|
||||
error-ex "^1.3.1"
|
||||
json-parse-better-errors "^1.0.1"
|
||||
|
||||
parse5@^3.0.1:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c"
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
parseurl@~1.3.2:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3"
|
||||
@ -5796,6 +5890,10 @@ vue-progressbar@^0.7.4:
|
||||
version "0.7.5"
|
||||
resolved "https://registry.yarnpkg.com/vue-progressbar/-/vue-progressbar-0.7.5.tgz#414730892252b1e45582d4979dec93038e007f79"
|
||||
|
||||
vue-resize@^0.4.4:
|
||||
version "0.4.4"
|
||||
resolved "https://registry.yarnpkg.com/vue-resize/-/vue-resize-0.4.4.tgz#dee9b8dd1b189e7e3f6ec47f86c60694a241bb17"
|
||||
|
||||
vue-router@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.0.1.tgz#d9b05ad9c7420ba0f626d6500d693e60092cc1e9"
|
||||
|
Loading…
Reference in New Issue
Block a user