├── .eslintrc.js ├── .gitignore ├── .stylelintrc ├── README.md ├── gulpfile.js ├── package-lock.json ├── package.json └── src ├── index-src.html ├── js └── script.js ├── scss └── styles.scss └── translate ├── en.json ├── pt.json ├── ru.json ├── tr.json ├── zh-cn.json └── zh-tw.json /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | es6: true 5 | }, 6 | extends: [`standard`], 7 | globals: { 8 | Atomics: `readonly`, 9 | SharedArrayBuffer: `readonly` 10 | }, 11 | parser: `babel-eslint`, 12 | parserOptions: { 13 | ecmaVersion: 2018 14 | }, 15 | rules: { 16 | semi: [`error`, `always`], 17 | indent: [`error`, 2], 18 | quotes: [2, `backtick`] 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | build 4 | -------------------------------------------------------------------------------- /.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "stylelint-config-standard", 3 | "rules": { 4 | "at-rule-no-unknown": [ 5 | true, 6 | ignoreAtRules: [ 7 | "mixin", "include" 8 | ] 9 | ], 10 | "indentation": 2, 11 | "string-quotes": "double", 12 | "no-duplicate-selectors": true, 13 | "color-hex-case": "upper", 14 | "color-hex-length": "short", 15 | "selector-max-id": 0, 16 | "selector-combinator-space-after": "always", 17 | "selector-attribute-quotes": "always", 18 | "selector-type-case": "upper", 19 | "declaration-block-trailing-semicolon": "always", 20 | "declaration-no-important": true, 21 | "declaration-colon-space-before": "never", 22 | "declaration-colon-space-after": "always-single-line", 23 | "declaration-colon-newline-after": null, 24 | "property-no-vendor-prefix": true, 25 | "value-no-vendor-prefix": true, 26 | "number-leading-zero": "never", 27 | "function-url-quotes": "always", 28 | "font-family-name-quotes": "always-where-required", 29 | "comment-whitespace-inside": "always", 30 | "comment-empty-line-before": null, 31 | "custom-property-empty-line-before": null, 32 | "at-rule-no-vendor-prefix": true, 33 | "selector-pseudo-element-colon-notation": "double", 34 | "selector-pseudo-class-parentheses-space-inside": "never", 35 | "selector-no-vendor-prefix": true, 36 | "media-feature-range-operator-space-before": "always", 37 | "media-feature-range-operator-space-after": "always", 38 | "media-feature-parentheses-space-inside": "always", 39 | "media-feature-colon-space-before": "never", 40 | "media-feature-colon-space-after": "always" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Url encoder for SVG 2 | 3 | http://yoksel.github.io/url-encoder 4 | 5 | ## Usage 6 | 7 | 1. Take `svg`. 8 | 2. Encode it with [url-encoder](http://yoksel.github.io/url-encoder/). 9 | 3. Use code as `background-image` or `border-image` or `mask`. 10 | 4. Enjoy! 11 | 12 | Demo: https://codepen.io/yoksel/full/WNrLpYW. 13 | 14 | ## How to add translate 15 | 16 | 1. Create translation file (use `src/translate/en.json` as example) and place it to `src/translate/` 17 | 2. Add new language to section `langs` in all translation files 18 | 3. Add item with your language to section `translates` in `gulpfile.js`. 19 | 4. Run `npm start` in console (wait until project will be opened in browser) and check all pages: 20 | * Link to new page must appear in all pages 21 | * In the page with new translate new language in list must looks like current (bold and black) 22 | 5. Send pull request 23 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | const gulp = require(`gulp`); 2 | const sass = require('gulp-sass')(require('sass')); 3 | const sync = require(`browser-sync`).create(); 4 | const reload = sync.reload; 5 | const colors = require(`colors/safe`); 6 | const del = require(`del`); 7 | const mustache = require(`gulp-mustache`); 8 | const rename = require(`gulp-rename`); 9 | 10 | const SERVER_ROOT = `build/`; 11 | 12 | const translates = [ 13 | { 14 | dest: SERVER_ROOT, 15 | url: `./src/translate/en.json` 16 | }, 17 | { 18 | dest: `${SERVER_ROOT}pt`, 19 | url: `./src/translate/pt.json` 20 | }, 21 | { 22 | dest: `${SERVER_ROOT}ru`, 23 | url: `./src/translate/ru.json` 24 | }, 25 | { 26 | dest: `${SERVER_ROOT}zh-cn`, 27 | url: `./src/translate/zh-cn.json` 28 | }, 29 | { 30 | dest: `${SERVER_ROOT}zh-tw`, 31 | url: `./src/translate/zh-tw.json` 32 | }, 33 | { 34 | dest: `${SERVER_ROOT}tr`, 35 | url: `./src/translate/tr.json` 36 | } 37 | ]; 38 | 39 | // TEMPLATES 40 | const tmplTasks = translates.map(({ dest, url }) => { 41 | return (done) => { 42 | gulp.src(`./src/index-src.html`) 43 | .pipe(mustache(url)) 44 | .pipe(rename(`index.html`)) 45 | .pipe(gulp.dest(dest)) 46 | .pipe(reload({ stream: true })); 47 | done(); 48 | }; 49 | }); 50 | 51 | gulp.task(`tmpl`, gulp.series(...tmplTasks)); 52 | 53 | // SCSS 54 | gulp.task(`scss`, function () { 55 | return gulp.src(`src/scss/**/styles.scss`) 56 | .pipe(sass().on(`error`, sass.logError)) 57 | .pipe(gulp.dest(`${SERVER_ROOT}assets/css`)) 58 | .pipe(reload({ stream: true })); 59 | }); 60 | 61 | // JS 62 | gulp.task(`js`, function () { 63 | return gulp.src(`src/js/**/*.js`) 64 | .pipe(gulp.dest(`${SERVER_ROOT}assets/js`)) 65 | .pipe(reload({ stream: true })); 66 | }); 67 | 68 | // CLEAN BUILD 69 | gulp.task(`clean`, function (done) { 70 | del([`${SERVER_ROOT}*`]).then(paths => { 71 | console.log(`⬤ Deleted files and folders:\n`, paths.join(`\n`)); 72 | }); 73 | 74 | done(); 75 | }); 76 | 77 | // CLEAN BUILD & COPY FILES TO IT 78 | gulp.task(`build`, gulp.series([`scss`, `js`, `tmpl`])); 79 | 80 | // WATCH FILES 81 | function watchTasks () { 82 | sync.init({ 83 | ui: false, 84 | notify: false, 85 | server: { 86 | baseDir: SERVER_ROOT 87 | } 88 | }); 89 | 90 | gulp.watch([`src/scss/**/*.scss`], gulp.series(`scss`)); 91 | gulp.watch([`src/index-src.html`, `src/translate/**/*`], gulp.series(`tmpl`)); 92 | gulp.watch([`src/js/**/*`], gulp.series(`js`)); 93 | } 94 | 95 | gulp.task(`serve`, gulp.series([`build`], watchTasks)); 96 | 97 | gulp.task(`default`, function () { 98 | console.log(colors.rainbow(`⬤ ================================ ⬤\n`)); 99 | console.log(` AVAILABLE COMMANDS:`); 100 | console.log(` ` + colors.cyan(`-------------------\n`)); 101 | console.log(` ` + colors.yellow(`npm start`) + 102 | ` — run local server with watcher`); 103 | console.log(` ` + colors.green(`npm run build`) + 104 | ` — make build of the project`); 105 | console.log(` ` + colors.cyan(`npm run deploy`) + 106 | ` — make build and publish project to Github Pages`); 107 | console.log(colors.rainbow(`\n⬤ ================================ ⬤`)); 108 | }); 109 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "url-encoder", 3 | "version": "1.0.1", 4 | "description": "http://yoksel.github.io/url-encoder", 5 | "main": ".eslintrc.js", 6 | "scripts": { 7 | "start": "gulp clean && gulp serve", 8 | "build": "gulp clean && gulp build", 9 | "deploy": "npm run build && gh-pages -d build -b gh-pages", 10 | "lint": "npm run js:lint && npm run css:lint", 11 | "lint:fix": "npm run js:fix && npm run css:fix", 12 | "js:lint": "eslint src", 13 | "js:fix": "eslint src --fix", 14 | "css:lint": "stylelint **/*.scss", 15 | "css:fix": "stylelint **/*.scss --fix" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/yoksel/url-encoder.git" 20 | }, 21 | "keywords": [], 22 | "author": "", 23 | "license": "ISC", 24 | "bugs": { 25 | "url": "https://github.com/yoksel/url-encoder/issues" 26 | }, 27 | "homepage": "https://github.com/yoksel/url-encoder#readme", 28 | "devDependencies": { 29 | "babel-eslint": "10.1.0", 30 | "browser-sync": "^2.26.10", 31 | "colors": "^1.1.2", 32 | "del": "^2.2.0", 33 | "eslint": "7.5.0", 34 | "eslint-config-standard": "14.1.1", 35 | "eslint-plugin-import": "2.22.0", 36 | "eslint-plugin-node": "^11.1.0", 37 | "eslint-plugin-promise": "4.2.1", 38 | "eslint-plugin-standard": "4.0.1", 39 | "gh-pages": "^3.1.0", 40 | "gulp": "^4.0.2", 41 | "gulp-mustache": "^5.0.0", 42 | "gulp-rename": "2.0.0", 43 | "gulp-sass": "^5.1.0", 44 | "sass": "^1.58.3", 45 | "stylelint": "^13.0.0", 46 | "stylelint-config-standard": "^19.0.0" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/index-src.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{title}} 4 | 5 | 6 | 7 |
8 |
9 |

{{title}}

10 | 11 | 18 |
19 | 20 |
21 |
22 | 23 |
24 | {{quotes}}: 25 | 34 | 35 | / 36 | 37 | 47 |
48 | 49 | 50 |
51 |
{{aboutTitle}}
52 | 53 | 56 |
57 |
58 | 59 |
60 |
61 |

{{insertSVG}}:

62 | 63 | 64 | 65 | 70 |
71 | 72 |
73 |

{{takeEncoded}}:

74 | 75 | 79 | 80 | 85 | 86 |
{{decodeTip}}
87 |
88 |
89 | 90 |
91 |
92 |

{{readyForCSS}}:

93 | 94 | 96 | 97 | 102 |
103 | 104 |
105 |

{{preview}}:

106 | 107 |
{{background}}: 108 | 115 | 116 | 123 | 124 | 131 |
132 | 133 |
134 |
135 |
136 |
137 |
138 |
139 | 140 | 144 | 145 |
146 |
147 | 148 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /src/js/script.js: -------------------------------------------------------------------------------- 1 | const doc = document; 2 | 3 | const initTextarea = doc.querySelector(`#init`); 4 | const resultTextarea = doc.querySelector(`#result`); 5 | const resultCssTextarea = doc.querySelector(`#result-css`); 6 | const resultDemo = doc.querySelector(`#demo`); 7 | const demoWrapper = doc.querySelector(`.demo-wrapper`); 8 | const contrastButtons = doc.querySelectorAll(`.contrast-button`); 9 | const dropzoneEl = doc.querySelector(`#dropzone`); 10 | let contrastButtonCurrent = null; 11 | let backgroundColor = ``; 12 | 13 | const expanders = doc.querySelectorAll(`.expander`); 14 | const expandedClass = `expanded`; 15 | const symbols = /[\r\n%#()<>?[\\\]^`{|}]/g; 16 | 17 | const quotesInputs = doc.querySelectorAll(`.options__input`); 18 | let externalQuotesValue = doc.querySelector(`.options__input:checked`).value; 19 | let quotes = getQuotes(); 20 | 21 | const buttonExample = doc.querySelector(`.button-example`); 22 | 23 | // Textarea Actions 24 | // ---------------------------------------- 25 | 26 | initTextarea.oninput = function () { 27 | getResults(); 28 | }; 29 | 30 | resultTextarea.oninput = function () { 31 | const value = resultTextarea.value.trim() 32 | .replace(/background-image:\s{0,}url\(/, ``) 33 | .replace(/["']{0,}data:image\/svg\+xml,/, ``) 34 | .replace(/["']\);{0,}$/, ``); 35 | initTextarea.value = decodeURIComponent(value); 36 | getResults(); 37 | }; 38 | 39 | function getResults () { 40 | if (!initTextarea.value) { 41 | resultCssTextarea.value = ``; 42 | resultDemo.setAttribute(`style`, ``); 43 | return; 44 | } 45 | 46 | const namespaced = addNameSpace(initTextarea.value); 47 | const escaped = encodeSVG(namespaced); 48 | resultTextarea.value = escaped; 49 | const resultCss = `background-image: url(${quotes.level1}data:image/svg+xml,${escaped}${quotes.level1});`; 50 | resultCssTextarea.value = resultCss; 51 | resultDemo.setAttribute(`style`, resultCss); 52 | } 53 | 54 | // Tabs Actions 55 | // ---------------------------------------- 56 | 57 | for (let i = 0; i < expanders.length; i++) { 58 | const expander = expanders[i]; 59 | 60 | expander.onclick = function () { 61 | const parent = this.parentNode; 62 | const expanded = parent.querySelector(`.` + expandedClass); 63 | expanded.classList.toggle(`hidden`); 64 | this.classList.toggle(`opened`); 65 | }; 66 | } 67 | 68 | // Switch quotes 69 | // ---------------------------------------- 70 | 71 | quotesInputs.forEach(input => { 72 | input.addEventListener(`input`, function () { 73 | externalQuotesValue = this.value; 74 | quotes = getQuotes(); 75 | getResults(); 76 | }); 77 | }); 78 | 79 | // Set example 80 | // ---------------------------------------- 81 | 82 | buttonExample.addEventListener(`click`, () => { 83 | initTextarea.value = ` 84 | 85 | 86 | 87 | 88 | 89 | 90 | `; 91 | getResults(); 92 | }); 93 | 94 | // Demo Background Switch 95 | // ---------------------------------------- 96 | 97 | function contrastButtonsSetCurrent (button) { 98 | const classCurrent = `contrast-button--current`; 99 | 100 | if (contrastButtonCurrent) { 101 | contrastButtonCurrent.classList.remove(classCurrent); 102 | } 103 | 104 | backgroundColor = button.dataset.color; 105 | contrastButtonCurrent = button; 106 | button.classList.add(classCurrent); 107 | } 108 | 109 | contrastButtons.forEach(button => { 110 | if (!backgroundColor) { 111 | contrastButtonsSetCurrent(button); 112 | } 113 | 114 | button.addEventListener(`click`, function () { 115 | contrastButtonsSetCurrent(this); 116 | demoWrapper.style.background = backgroundColor; 117 | }); 118 | }); 119 | 120 | // Namespace 121 | // ---------------------------------------- 122 | 123 | function addNameSpace (data) { 124 | if (data.indexOf(`http://www.w3.org/2000/svg`) < 0) { 125 | data = data.replace(/\s{1,}<`); 143 | data = data.replace(/\s{2,}/g, ` `); 144 | 145 | // Using encodeURIComponent() as replacement function 146 | // allows to keep result code readable 147 | return data.replace(symbols, encodeURIComponent); 148 | } 149 | 150 | // Get quotes for levels 151 | // ---------------------------------------- 152 | 153 | function getQuotes () { 154 | const double = `"`; 155 | const single = `'`; 156 | 157 | return { 158 | level1: externalQuotesValue === `double` ? double : single, 159 | level2: externalQuotesValue === `double` ? single : double 160 | }; 161 | } 162 | 163 | // Copy to clipboard 164 | // ---------------------------------------- 165 | 166 | const copyResultButton = doc.getElementById(`copy-result-button`); 167 | const copyCSSResultButton = doc.getElementById(`copy-css-result-button`); 168 | 169 | copyResultButton.addEventListener(`click`, function (event) { 170 | const textToCopy = doc.getElementById(`result`); 171 | textToCopy.select(); 172 | doc.execCommand(`copy`); 173 | }); 174 | 175 | copyCSSResultButton.addEventListener(`click`, function (event) { 176 | const textToCopy = doc.getElementById(`result-css`); 177 | textToCopy.select(); 178 | doc.execCommand(`copy`); 179 | }); 180 | 181 | // Common 182 | // ---------------------------------------- 183 | 184 | // eslint-disable-next-line no-unused-vars 185 | function out (data) { 186 | console.log(data); 187 | } 188 | 189 | // Dropzone logic 190 | // ---------------------------------------- 191 | 192 | if (dropzoneEl) { 193 | const dropzoneActiveCls = `dropzone--active`; 194 | doc.addEventListener(`dragover`, (e) => { 195 | e.preventDefault(); 196 | dropzoneEl.classList.add(dropzoneActiveCls); 197 | }); 198 | dropzoneEl.addEventListener(`dragleave`, () => { 199 | dropzoneEl.classList.remove(dropzoneActiveCls); 200 | }); 201 | dropzoneEl.addEventListener(`drop`, (e) => { 202 | e.preventDefault(); 203 | const data = e.dataTransfer; 204 | const reader = new FileReader(); 205 | const file = data.files[0]; 206 | 207 | if (file.type == `image/svg+xml`) { 208 | reader.readAsText(file); 209 | reader.onload = () => { 210 | initTextarea.value = reader.result; 211 | getResults(); 212 | }; 213 | } 214 | dropzoneEl.classList.remove(dropzoneActiveCls); 215 | }); 216 | } -------------------------------------------------------------------------------- /src/scss/styles.scss: -------------------------------------------------------------------------------- 1 | $black-transp-25: rgba(0, 0, 0, .25); 2 | $gray: #CCC; 3 | 4 | BODY { 5 | font: 16px/1.4 Trebuchet MS, Arial, sans-serif; 6 | color: #000; 7 | } 8 | 9 | A { 10 | color: steelblue; 11 | } 12 | 13 | H1 { 14 | font: 2em/1.4 Georgia, serif; 15 | text-align: center; 16 | } 17 | 18 | H4 { 19 | margin: 0; 20 | margin-bottom: .15em; 21 | font: 1.3em/1.4 Georgia, serif; 22 | } 23 | 24 | P { 25 | margin: 1.2rem 0; 26 | } 27 | 28 | TEXTAREA { 29 | width: 100%; 30 | height: 150px; 31 | margin: 0; 32 | border: 1px solid $gray; 33 | border-radius: 10px; 34 | font-size: 13px; 35 | font-family: monospace; 36 | } 37 | 38 | CODE { 39 | padding: 0 3px; 40 | background: #EEE; 41 | border-radius: 5px; 42 | text-shadow: 1px 1px 0 white; 43 | font: 14px/1.4 monospace; 44 | color: #333; 45 | } 46 | 47 | CODE I { 48 | font-style: italic; 49 | color: black; 50 | } 51 | 52 | DL, 53 | DD, 54 | DT { 55 | margin: 0; 56 | } 57 | 58 | DL { 59 | text-align: right; 60 | } 61 | 62 | DT { 63 | border-bottom: 1px dashed; 64 | display: inline-block; 65 | line-height: 1; 66 | color: steelblue; 67 | cursor: pointer; 68 | } 69 | 70 | DT::after { 71 | content: ""; 72 | display: inline-block; 73 | border: 0 solid transparent; 74 | border-width: 8px 4px 0; 75 | border-top-color: currentColor; 76 | border-bottom-color: currentColor; 77 | margin-left: 5px; 78 | } 79 | 80 | .opened::after { 81 | border-width: 0 4px 8px; 82 | } 83 | 84 | DD { 85 | text-align: left; 86 | } 87 | 88 | .hidden { 89 | display: none; 90 | } 91 | 92 | .visuallyhidden { 93 | position: absolute; 94 | width: 1px; 95 | height: 1px; 96 | margin: -1px; 97 | border: 0; 98 | padding: 0; 99 | white-space: nowrap; 100 | clip-path: inset(100%); 101 | clip: rect(0 0 0 0); 102 | overflow: hidden; 103 | } 104 | 105 | .wrapper { 106 | width: 650px; 107 | margin: 1.5rem auto 4rem; 108 | } 109 | 110 | .header { 111 | position: relative; 112 | margin-bottom: 2rem; 113 | padding-bottom: 1rem; 114 | border-bottom: 1px solid $gray; 115 | } 116 | 117 | .header::before { 118 | content: ""; 119 | display: table; 120 | width: 100%; 121 | clear: both; 122 | } 123 | 124 | .langs { 125 | position: absolute; 126 | top: 0; 127 | right: 0; 128 | margin: auto; 129 | display: flex; 130 | list-style-type: none; 131 | 132 | A:not([href]) { 133 | font-weight: bold; 134 | color: inherit; 135 | } 136 | } 137 | 138 | .langs__item { 139 | & + & { 140 | margin-left: .5rem; 141 | } 142 | } 143 | 144 | .footer { 145 | position: relative; 146 | display: flex; 147 | justify-content: space-between; 148 | margin-top: 3rem; 149 | padding-top: 2rem; 150 | border-top: 1px solid $gray; 151 | } 152 | 153 | .panel { 154 | position: relative; 155 | z-index: 1; 156 | margin-bottom: 2.5rem; 157 | display: flex; 158 | justify-content: space-between; 159 | } 160 | 161 | .options { 162 | position: relative; 163 | } 164 | 165 | .options__middle-word { 166 | vertical-align: middle; 167 | color: #AAA; 168 | } 169 | 170 | .options__text { 171 | display: inline-block; 172 | border-bottom: 1px dashed; 173 | color: steelblue; 174 | cursor: pointer; 175 | } 176 | 177 | .options__input:checked + .options__text { 178 | border: 0; 179 | color: inherit; 180 | cursor: default; 181 | } 182 | 183 | .expander { 184 | position: relative; 185 | z-index: 2; 186 | } 187 | 188 | .expanded { 189 | position: absolute; 190 | top: -15px; 191 | right: -15px; 192 | left: -15px; 193 | padding: 2rem 1.5rem 1rem; 194 | background: #FFF; 195 | border: 1px solid $gray; 196 | border-radius: 5px; 197 | box-shadow: 0 0 0 5px rgba(0, 0, 0, .1); 198 | } 199 | 200 | .button-example, 201 | .copy-button { 202 | padding: 0; 203 | border: 0; 204 | border-bottom: 1px dashed; 205 | background: transparent; 206 | align-self: center; 207 | font: inherit; 208 | line-height: 1; 209 | font-size: 14px; 210 | color: steelblue; 211 | cursor: pointer; 212 | } 213 | 214 | .containers { 215 | margin-bottom: 32px; 216 | display: flex; 217 | flex-wrap: wrap; 218 | justify-content: space-between; 219 | } 220 | 221 | .container { 222 | position: relative; 223 | width: 48%; 224 | margin-bottom: 1em; 225 | display: flex; 226 | flex-wrap: wrap; 227 | justify-content: space-between; 228 | align-content: flex-start; 229 | } 230 | 231 | .demo-wrapper { 232 | width: 100%; 233 | border: 1px dashed $black-transp-25; 234 | } 235 | 236 | .demo { 237 | height: 150px; 238 | background-repeat: no-repeat; 239 | } 240 | 241 | .contrast-buttons { 242 | display: flex; 243 | align-items: center; 244 | margin-bottom: .4em; 245 | } 246 | 247 | .contrast-button { 248 | display: block; 249 | width: 2em; 250 | height: 2em; 251 | margin-left: 5px; 252 | padding: 0; 253 | border-radius: 50%; 254 | border: 1px solid $black-transp-25; 255 | outline: none; 256 | cursor: pointer; 257 | } 258 | 259 | .contrast-button--current { 260 | box-shadow: 0 0 0 3px steelblue; 261 | } 262 | 263 | .contrast-button:active { 264 | box-shadow: 0 0 0 3px $black-transp-25; 265 | } 266 | 267 | .contrast-button--white { 268 | background: white; 269 | } 270 | 271 | .contrast-button--silver { 272 | background: silver; 273 | } 274 | 275 | .contrast-button--black { 276 | background: black; 277 | } 278 | 279 | .tip { 280 | margin-top: .5rem; 281 | font-size: .9em; 282 | color: #777; 283 | } 284 | 285 | .dropzone { 286 | $svgIconSize: 80; 287 | background-color: rgba(#4d4d52, 0.6); 288 | backdrop-filter: blur(0.75rem); 289 | background-image: url("data:image/svg+xml,%3Csvg height='#{$svgIconSize}' width='#{$svgIconSize}' xmlns='http://www.w3.org/2000/svg' fill='%23fff' class='bi bi-filetype-svg' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M14 4.5V14a2 2 0 0 1-2 2v-1a1 1 0 0 0 1-1V4.5h-2A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v9H2V2a2 2 0 0 1 2-2h5.5L14 4.5ZM0 14.84a1.13 1.13 0 0 0 .4.82c.13.11.29.2.48.26s.41.09.66.09c.34 0 .63-.06.86-.16.24-.1.42-.25.54-.44a1.17 1.17 0 0 0 .19-.66c0-.22-.05-.4-.14-.56a1 1 0 0 0-.37-.35 2.03 2.03 0 0 0-.57-.21l-.62-.15a.97.97 0 0 1-.4-.17.37.37 0 0 1-.15-.3.5.5 0 0 1 .19-.39.8.8 0 0 1 .51-.15c.14 0 .27.02.37.07a.63.63 0 0 1 .25.18.56.56 0 0 1 .12.26h.75a1.1 1.1 0 0 0-.2-.57 1.21 1.21 0 0 0-.5-.4 1.81 1.81 0 0 0-.78-.16c-.3 0-.55.05-.78.15-.22.1-.4.24-.53.42-.12.18-.19.4-.19.64a1 1 0 0 0 .47.9c.16.09.34.16.55.2l.62.15c.2.05.36.11.46.2a.39.39 0 0 1 .15.32.51.51 0 0 1-.08.29.56.56 0 0 1-.26.19 1 1 0 0 1-.41.07c-.12 0-.23-.01-.32-.04a.84.84 0 0 1-.25-.12.58.58 0 0 1-.26-.38H0Zm4.58 1.1h.95l1.32-4h-.87l-.9 3.13h-.03l-.9-3.14h-.91l1.33 4Zm5.48-3.3c.07.15.12.31.14.49h-.78a.8.8 0 0 0-.1-.25.69.69 0 0 0-.16-.19.7.7 0 0 0-.24-.13.96.96 0 0 0-.3-.04.8.8 0 0 0-.66.3c-.16.2-.24.49-.24.85v.5c0 .23.03.44.1.62a.88.88 0 0 0 .3.4.87.87 0 0 0 .52.15.96.96 0 0 0 .46-.1.67.67 0 0 0 .27-.26.74.74 0 0 0 .09-.36v-.25h-.82v-.6h1.57v.8c0 .2-.03.38-.1.55a1.29 1.29 0 0 1-.29.46 1.37 1.37 0 0 1-.5.32c-.19.07-.42.1-.69.1a1.98 1.98 0 0 1-.75-.12 1.45 1.45 0 0 1-.53-.38 1.58 1.58 0 0 1-.32-.58 2.48 2.48 0 0 1-.1-.75v-.5c0-.36.06-.68.19-.95.13-.27.33-.48.58-.64.26-.15.57-.22.93-.22.24 0 .45.03.63.1a1.3 1.3 0 0 1 .8.68Z'/%3E%3C/svg%3E"); 290 | background-position: center; 291 | background-repeat: no-repeat; 292 | position: fixed; 293 | top: 0; 294 | right: 0; 295 | bottom: 0; 296 | left: 0; 297 | z-index: 100000; 298 | display: block; 299 | transform: scale(1.4); 300 | transition: transform 0.1s, opacity 0.1s; 301 | pointer-events: none; 302 | opacity: 0; 303 | 304 | &--active { 305 | transform: scale(1); 306 | pointer-events: all; 307 | opacity: 1; 308 | } 309 | } -------------------------------------------------------------------------------- /src/translate/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": ".", 3 | "title": "URL-encoder for SVG", 4 | "quotes": "External quotes", 5 | "single": "single", 6 | "double": "double", 7 | "aboutTitle": "About tool", 8 | "aboutText": "

We can use SVG in CSS via data URI, but without encoding it works only in Webkit based browsers. If encode SVG using encodeURIComponent() it will work everywhere.

SVG must have attribute xmlns like this: xmlns='http: //www.w3.org/2000/svg'. If it doesn't exist, it will be added automagically.

Encoded SVG can be used in background, in border-image or in mask (live demo).

", 9 | "insertSVG": "Insert SVG", 10 | "example": "Example", 11 | "takeEncoded": "Take encoded", 12 | "copy": "Copy", 13 | "readyForCSS": "Ready for CSS", 14 | "preview": "Preview", 15 | "background": "Background", 16 | "white": "white", 17 | "silver": "silver", 18 | "black": "black", 19 | "projectOn": "Project on", 20 | "twitter": "yoksel_en", 21 | "langs": [ 22 | "En", 23 | "Br", 24 | "Рус", 25 | "简中", 26 | "繁中", 27 | "Tr" 28 | ], 29 | "decodeTip": "You may place encoded SVG here to decode it back" 30 | } 31 | -------------------------------------------------------------------------------- /src/translate/pt.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": "..", 3 | "title": "Codificador de URL para SVG", 4 | "quotes": "Aspas externas", 5 | "single": "simples", 6 | "double": "duplas", 7 | "aboutTitle": "Sobre", 8 | "aboutText": "

Podemos usar SVG em CSS via dados URI, mas sem codificação, funciona apenas em navegadores baseados em Webkit. Se codificar SVG usando encodeURIComponent(), ele funcionará em qualquer lugar.

O SVG deve ter o atributo xmlns desta maneira: xmlns='http: / /www.w3.org/2000/svg'. Se não existir, ele será adicionado automagicamente.

SVGs codificados podem ser usado em background, em border-image ou em mask (Demonstração).

", 9 | "insertSVG": "Código SVG", 10 | "example": "Exemplo", 11 | "takeEncoded": "Trecho codificado", 12 | "copy": "Copiar", 13 | "readyForCSS": "Código CSS", 14 | "preview": "Preview", 15 | "background": "Cor de fundo", 16 | "white": "Branco", 17 | "silver": "Prata", 18 | "black": "Preto", 19 | "projectOn": "Repositório no", 20 | "twitter": "yoksel_en", 21 | "langs": [ 22 | "En", 23 | "Br", 24 | "Рус", 25 | "简中", 26 | "繁中", 27 | "Tr" 28 | ], 29 | "decodeTip": "Você pode colocar um SVG codificado aqui para decodificar de volta." 30 | } 31 | -------------------------------------------------------------------------------- /src/translate/ru.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": "..", 3 | "title": "URL-encoder для SVG", 4 | "quotes": "Внешние кавычки", 5 | "single": "oдинарные", 6 | "double": "двойные", 7 | "aboutTitle": "Назначение инструмента", 8 | "aboutText": "

SVG можно использовать в CSS через data URI, но вставку незакодированного SVG поддерживают только браузеры на Webkit. Если закодировать SVG с помощью encodeURIComponent() — SVG начинает отображаться во всех современных браузерах.

У тега SVG обязательно должен быть атрибут xmlns, вот такой: xmlns='http://www.w3.org/2000/svg'. Если его нет, он будет добавлен автоматически.

Закодированный SVG можно использовать в background, в border-image или в mask (демо).

", 9 | "insertSVG": "Вставьте код SVG", 10 | "example": "Пример", 11 | "takeEncoded": "Закодированный", 12 | "copy": "Скопировать", 13 | "readyForCSS": "CSS для фона", 14 | "preview": "Превью", 15 | "background": "Фон", 16 | "white": "белый", 17 | "silver": "серый", 18 | "black": "черный", 19 | "projectOn": "Проект на", 20 | "twitter": "yoksel", 21 | "langs": [ 22 | "En", 23 | "Br", 24 | "Рус", 25 | "简中", 26 | "繁中", 27 | "Tr" 28 | ], 29 | "decodeTip": "Сюда можно вставить закодированный SVG, чтобы раскодировать его обратно" 30 | } 31 | -------------------------------------------------------------------------------- /src/translate/tr.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": "..", 3 | "title": "SVG için URL oluşturucu", 4 | "quotes": "Tırnak Kullanımı", 5 | "single": "tek", 6 | "double": "çift", 7 | "aboutTitle": "Araç Hakkında", 8 | "aboutText": "

SVG kodlarınızı CSS içinde URI formatında kullanmak istediğinizde ve dönüştürülmemişse sadece Webkit tabanlı tarayıcılarda çalışır. SVG kodunuzu encodeURIComponent() fonksiyonu ile kullanırsanız her yerde çalışır.

SVG kodunuz xmlns özelliğine sahip olmalıdır: xmlns='http: //www.w3.org/2000/svg'. Bu kod eksikse sistem otomatik olarak ekleyecektir.

Dönüştürülmüş SVG kodlarınızı background, border-image veya mask ile kullanabilirsiniz (örnek proje).

", 9 | "insertSVG": "SVG Kodu", 10 | "example": "Örnek", 11 | "takeEncoded": "Dönüştürülmüş kod", 12 | "copy": "Kopyala", 13 | "readyForCSS": "CSS için kod", 14 | "preview": "Ön izleme", 15 | "background": "Arka Plan", 16 | "white": "Beyaz", 17 | "silver": "Gri", 18 | "black": "Siyah", 19 | "projectOn": "Bu proje", 20 | "twitter": "yoksel_en", 21 | "langs": [ 22 | "En", 23 | "Br", 24 | "Рус", 25 | "简中", 26 | "繁中", 27 | "Tr" 28 | ], 29 | "decodeTip": "Dönüştürülmüş SVG kodunuzu eski haline çevirmek için buraya yapıştırabilirsiniz" 30 | } 31 | -------------------------------------------------------------------------------- /src/translate/zh-cn.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": "..", 3 | "title": "用于 SVG 的 URL-encoder", 4 | "quotes": "引号 ", 5 | "single": "单引号", 6 | "double": "双引号", 7 | "aboutTitle": "关于此工具", 8 | "aboutText": "

不进行编码的话,我们可以以 data URI 形式在 CSS 中直接使用 SVG,但这仅在基于 Webkit 的浏览器中有效;如果用 encodeURIComponent() 对 SVG 编码,就可在全部地方都生效。

SVG 必须有 xmlns 属性,例如:xmlns='http: //www.w3.org/2000/svg'。如果不存在则会自动添加。

编码后的 SVG 可在 backgroundborder-imagemask中使用(实例演示)。

", 9 | "insertSVG": "插入 SVG ", 10 | "example": "示例", 11 | "takeEncoded": "编码后 ", 12 | "copy": "复制", 13 | "readyForCSS": "在 CSS 里使用 ", 14 | "preview": "预览 ", 15 | "background": "背景 ", 16 | "white": "白色", 17 | "silver": "银色", 18 | "black": "黑色", 19 | "projectOn": "查看项目于 ", 20 | "twitter": "yoksel_en", 21 | "langs": [ 22 | "En", 23 | "Br", 24 | "Рус", 25 | "简中", 26 | "繁中", 27 | "Tr" 28 | ], 29 | "decodeTip": "您可将编码后的 SVG 粘贴到此处以解码" 30 | } 31 | -------------------------------------------------------------------------------- /src/translate/zh-tw.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": "..", 3 | "title": "給 SVG 使用的 URL-encoder", 4 | "quotes": "引號 ", 5 | "single": "單個", 6 | "double": "雙重", 7 | "aboutTitle": "關於此工具", 8 | "aboutText": "

我們可以通過數據 URI 在 CSS 中使用 SVG,但無需編碼,它僅在基於 Webkit 的瀏覽器中有效。如果使用 encodeURIComponent() 對 SVG 進行編碼,它將在任何地方都可以使用。

SVG 必須具有如下屬性 xmlns 像這樣:xmlns='http: //www.w3.org/2000/svg'。如果不存在,則會自動添加。

編碼的 SVG 可以在 backgroundborder-imagemask 中使用(實時演示)。

", 9 | "insertSVG": "插入 SVG ", 10 | "example": "例子", 11 | "takeEncoded": "編碼後 ", 12 | "copy": "複製", 13 | "readyForCSS": "在 CSS 裡使用 ", 14 | "preview": "預覽 ", 15 | "background": "背景 ", 16 | "white": "白色", 17 | "silver": "銀色", 18 | "black": "黑色", 19 | "projectOn": "項目在 ", 20 | "twitter": "yoksel_en", 21 | "langs": [ 22 | "En", 23 | "Br", 24 | "Рус", 25 | "简中", 26 | "繁中", 27 | "Tr" 28 | ], 29 | "decodeTip": "您可以將編碼後的 SVG 放在此處以將其解碼回去" 30 | } 31 | --------------------------------------------------------------------------------