4 |
5 |
6 | Asset Provider
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/packages/list/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # CHANGELOG
2 |
3 | ### 2.0.0
4 |
5 | - Major: Upgraded to use the latest `@babel/*` 7.0 packages.
6 |
7 | ### 1.1.0
8 |
9 | - Point main/browser to ES5 builds.
10 |
11 | ### 1.0.1
12 |
13 | - [#3] Verifying `dist/` dir exists prior to writing `bundle.md`
14 |
15 | ### 1.0.0
16 |
17 | - Initial public release.
18 |
19 |
20 | [#3]: https://github.com/godaddy/asset-system/issues/3
21 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "8"
4 | - "10"
5 | - "12"
6 | sudo: required
7 | before_script:
8 | - sudo chown root /opt/google/chrome/chrome-sandbox
9 | - sudo chmod 4755 /opt/google/chrome/chrome-sandbox
10 | - export DISPLAY=:99.0
11 | - sh -e /etc/init.d/xvfb start
12 | addons:
13 | chrome: stable
14 | after_success:
15 | - bash <(curl -s https://codecov.io/bash)
16 | matrix:
17 | fast_finish: true
18 |
--------------------------------------------------------------------------------
/examples/reactnative/android/app/src/main/java/com/reactnative/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.reactnative;
2 |
3 | import com.facebook.react.ReactActivity;
4 |
5 | public class MainActivity extends ReactActivity {
6 |
7 | /**
8 | * Returns the name of the main component registered from JavaScript.
9 | * This is used to schedule rendering of the component.
10 | */
11 | @Override
12 | protected String getMainComponentName() {
13 | return "reactnative";
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/examples/reactnative/ios/reactnative/AppDelegate.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | #import
11 |
12 | @interface AppDelegate : UIResponder
13 |
14 | @property (nonatomic, strong) UIWindow *window;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/examples/web/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | module.exports = {
4 | name: 'JS',
5 | entry: [
6 | path.join(__dirname, 'index.js')
7 | ],
8 | output: {
9 | path: path.join(__dirname, 'dist'),
10 | filename: 'client.js'
11 | },
12 | module: {
13 | rules: [{
14 | test: /\.jsx?$/,
15 | use: [{
16 | loader: 'babel-loader',
17 | options: {
18 | presets: [
19 | 'babel-preset-es2015',
20 | 'babel-preset-react'
21 | ]
22 | }
23 | }]
24 | }]
25 | }
26 | };
27 |
--------------------------------------------------------------------------------
/examples/reactnative/ios/reactnative/main.m:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | #import
11 |
12 | #import "AppDelegate.h"
13 |
14 | int main(int argc, char * argv[]) {
15 | @autoreleasepool {
16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/examples/reactnative/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "asset-system-react-native",
3 | "version": "1.0.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "node node_modules/react-native/local-cli/cli.js start",
7 | "test": "jest"
8 | },
9 | "dependencies": {
10 | "asset-provider": "latest",
11 | "react": "16.2.0",
12 | "react-native": "0.52.1",
13 | "react-native-svg": "^6.0.1-rc.3"
14 | },
15 | "devDependencies": {
16 | "babel-jest": "22.1.0",
17 | "babel-preset-react-native": "4.0.0",
18 | "jest": "22.1.4",
19 | "react-test-renderer": "16.2.0"
20 | },
21 | "jest": {
22 | "preset": "react-native"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/packages/provider/test/nock.js:
--------------------------------------------------------------------------------
1 | import { encode, version } from 'asset-parser';
2 | import * as fixture from './fixtures';
3 | import route from 'nock-knock';
4 | import nock from 'nock';
5 |
6 | //
7 | // Setup Nock for our asset loading tests.
8 | //
9 | nock('http://example.com')
10 | .get('/500')
11 | .times(Infinity)
12 | .reply(500)
13 | .get('/404')
14 | .times(Infinity)
15 | .reply(404)
16 | .get(route('/:fixture/bundle.svgs'))
17 | .times(Infinity)
18 | .delay(10)
19 | .reply(200, function (uri, body, fn) {
20 | const name = uri.split('/')[1];
21 | const data = fixture[name];
22 |
23 | encode(version || '0.1.0', data, fn);
24 | });
25 |
--------------------------------------------------------------------------------
/packages/webpack/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # CHANGELOG
2 |
3 | ### 6.0.0
4 |
5 | - Major: Upgraded to latest `asset-bundle`.
6 |
7 | ### 5.0.0
8 |
9 | - Major: Upgraded to use the latest `@babel/*` 7.0 packages.
10 | - Major: Upgraded to `Webpack@4` syntax.
11 |
12 | ### 4.0.0
13 |
14 | - Major: Introduced a new `loader` method that will take care of the file
15 | content renaming so we can leverage the build-in functionality of `file-loader`.
16 |
17 | ### 3.0.0
18 |
19 | - Bump `asset-bundle` to `3.0.0` which moved `puppeteer` to an optional
20 | dependency.
21 |
22 | ### 2.0.0
23 |
24 | - Point main/browser to ES5 builds.
25 | - Various of fixes to make it work with Next.js based webpacks.
26 |
27 | ### 1.0.0
28 |
29 | - Initial public release.
30 |
--------------------------------------------------------------------------------
/examples/reactnative/android/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.2.3'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | mavenLocal()
18 | jcenter()
19 | maven {
20 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
21 | url "$rootDir/../node_modules/react-native/android"
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/packages/bundle/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # CHANGELOG
2 |
3 | - Moved `dimensions` to it's own standalone project for re-use purposes.
4 |
5 | ### 4.1.0
6 |
7 | - Remove workaround to `await` page renders from puppeteer.
8 |
9 | ### 4.0.0
10 |
11 | - Major: Upgraded to use the latest `@babel/*` 7.0 packages.
12 |
13 | ### 3.0.1
14 |
15 | - Also lazy require the `puppeteer` library in our render method.
16 |
17 | ### 3.0.0
18 |
19 | - Removed `puppeteer` from the dependencies and made it an optional dependency
20 | instead as it needs to download 230mb+ files on installation each time for
21 | an edge case as documented in #13
22 |
23 | ### 2.1.0
24 |
25 | - Point main/browser to ES5 builds.
26 |
27 | ### 2.0.0
28 |
29 | - Bump to asset-parser@2.0.0
30 |
31 | ### 1.0.0
32 |
33 | - Initial public release.
34 |
--------------------------------------------------------------------------------
/examples/reactnative/ios/reactnative/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | }
33 | ],
34 | "info" : {
35 | "version" : 1,
36 | "author" : "xcode"
37 | }
38 | }
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Reporting Security Issues
2 |
3 | We take security very seriously at GoDaddy. We appreciate your efforts to
4 | responsibly disclose your findings, and will make every effort to acknowledge
5 | your contributions.
6 |
7 | ## Where should I report security issues?
8 |
9 | In order to give the community time to respond and upgrade, we strongly urge you
10 | report all security issues privately.
11 |
12 | To report a security issue in one of our Open Source projects email us directly
13 | at **oss@godaddy.com** and include the word "SECURITY" in the subject line.
14 |
15 | This mail is delivered to our Open Source Security team.
16 |
17 | After the initial reply to your report, the team will keep you informed of the
18 | progress being made towards a fix and announcement, and may ask for additional
19 | information or guidance.
20 |
--------------------------------------------------------------------------------
/examples/webpack.config.js:
--------------------------------------------------------------------------------
1 | const Pipeline = require('asset-webpack');
2 | const List = require('asset-list');
3 | const path = require('path');
4 |
5 | module.exports = {
6 | entry: path.join(__dirname, 'index.js'),
7 | output: {
8 | path: path.resolve(__dirname, 'dist'),
9 | filename: 'output.js'
10 | },
11 |
12 | module: {
13 | loaders: [
14 | { test: /\.svg$/, loaders: ['file-loader'] }
15 | ]
16 | },
17 |
18 | plugins: [
19 | new Pipeline('bundle.svgs', {
20 | //
21 | // Set to `true` if you want to use the folder structure of the files as
22 | // basic namespacing.
23 | //
24 | namespace: true,
25 |
26 | plugins: [
27 | [List, {
28 | //
29 | // `asset-list` options here.
30 | //
31 | }]
32 | ]
33 | })
34 | ]
35 | };
36 |
--------------------------------------------------------------------------------
/examples/reactnative/ios/reactnativeTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/examples/reactnative/ios/reactnative-tvOSTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/examples/reactnative/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | android.useDeprecatedNdk=true
21 |
--------------------------------------------------------------------------------
/examples/reactnative/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Xcode
6 | #
7 | build/
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata
17 | *.xccheckout
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 | *.xcuserstate
23 | project.xcworkspace
24 |
25 | # Android/IntelliJ
26 | #
27 | build/
28 | .idea
29 | .gradle
30 | local.properties
31 | *.iml
32 |
33 | # node.js
34 | #
35 | node_modules/
36 | npm-debug.log
37 | yarn-error.log
38 |
39 | # BUCK
40 | buck-out/
41 | \.buckd/
42 | *.keystore
43 |
44 | # fastlane
45 | #
46 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
47 | # screenshots whenever they are needed.
48 | # For more information about the recommended setup visit:
49 | # https://docs.fastlane.tools/best-practices/source-control/
50 |
51 | */fastlane/report.xml
52 | */fastlane/Preview.html
53 | */fastlane/screenshots
54 |
--------------------------------------------------------------------------------
/examples/web/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "asset-system-react",
3 | "version": "1.0.0",
4 | "description": "Examples of how the asset-provider works.",
5 | "main": "index.js",
6 | "scripts": {
7 | "start": "node babel.js"
8 | },
9 | "private": true,
10 | "license": "MIT",
11 | "browserify": {
12 | "transform": [
13 | "babelify"
14 | ]
15 | },
16 | "babel": {
17 | "plugins": [
18 | "transform-object-rest-spread"
19 | ],
20 | "presets": [
21 | "babel-preset-es2015",
22 | "babel-preset-react"
23 | ]
24 | },
25 | "dependencies": {
26 | "asset-bundle": "latest",
27 | "asset-provider": "latest",
28 | "babel-loader": "^7.1.2",
29 | "babel-plugin-transform-object-rest-spread": "^6.26.0",
30 | "babel-preset-es2015": "^6.24.1",
31 | "babel-preset-react": "^6.24.1",
32 | "babel-register": "^6.26.0",
33 | "babelify": "^8.0.0",
34 | "browserify": "^15.2.0",
35 | "memory-fs": "^0.4.1",
36 | "react": "^16.2.0",
37 | "react-dom": "^16.2.0",
38 | "webpack": "^4.0.0"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/packages/provider/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # CHANGELOG
2 |
3 | ### 4.2.1
4 |
5 | - Simplify array spread usage to avoid babel@7 issue [#7597](https://github.com/babel/babel/issues/7597)
6 |
7 | ### 4.2.0
8 |
9 | - Provide default `viewBox` to fallback image.
10 |
11 | ### 4.1.0
12 |
13 | - Allow for a custom asset fallback at the provider-level
14 |
15 | ### 4.0.0
16 |
17 | - Major: Upgraded to use the latest `@babel/*` 7.0 packages.
18 |
19 | ### 3.1.0
20 |
21 | - Fixed main/browser exports to point to ES5 builds
22 | - Various of fixes that caused usage with Next.js to fail.
23 |
24 | ### 2.0.0 - 3.0.0 (failed publish)
25 |
26 | - Fixed a race condition where fetching would still trigger setState when the
27 | component was unmounted already.
28 | - Removed React 15 support.
29 |
30 | ### 1.1.1
31 |
32 | - Allowed the `url` function that was added in 1.1.0 to access the provider
33 | instance through `this`.
34 |
35 | ### 1.1.0
36 |
37 | - Added support for specifying the `uri` as a function for dynamic URL
38 | generation.
39 |
40 | ### 1.0.0
41 |
42 | - Initial public release.
43 |
--------------------------------------------------------------------------------
/packages/webpack/loader.js:
--------------------------------------------------------------------------------
1 | import utils from 'loader-utils';
2 |
3 | /**
4 | * The smallest loader we could get away with.
5 | *
6 | * @param {Content} content The content that needs to be loaded.
7 | * @returns {String} Name of the file in the svg bundle.
8 | */
9 | module.exports = function svgLoader(content) {
10 | const options = utils.getOptions(this) || {};
11 | const context = options.context || this.rootContext || this.options && this.options.context;
12 | const opts = { context, content };
13 |
14 | //
15 | // Create internal and external names:
16 | //
17 | // Internal: How it ends up in the bundle so can be used as name prop.
18 | // External: Simple name to identify it during the WebPack plugin phase.
19 | //
20 | const external = utils.interpolateName(this, options.external, opts);
21 | const internal = utils.interpolateName(this, options.internal, opts);
22 |
23 | //
24 | // Ensures that these custom files end-up in `optimize-assets` event of
25 | // WebPack so we can intercept them.
26 | //
27 | this.emitFile(external, content);
28 | return `module.exports = ${JSON.stringify(internal)};`;
29 | };
30 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 GoDaddy Operating Company, LLC.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/packages/provider/fallback/index.js:
--------------------------------------------------------------------------------
1 | import diagnostics from 'diagnostics';
2 | import Svg, { G, Path } from 'svgs';
3 | import React from 'react';
4 |
5 | //
6 | // Setup our debug util.
7 | //
8 | const debug = diagnostics('asset:provider:wrapper');
9 |
10 | /**
11 | * Renders a default fallback SVG.
12 | *
13 | * @returns {React.Element} Fallback SVG.
14 | * @public
15 | */
16 | export default function Fallback() {
17 | debug('rendering the fallback');
18 |
19 | /*eslint-disable */
20 | return (
21 |
27 | );
28 | /* eslint-enable */
29 | }
30 |
--------------------------------------------------------------------------------
/packages/bundle/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 GoDaddy Operating Company, LLC.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/packages/list/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 GoDaddy Operating Company, LLC.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/packages/parser/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 GoDaddy Operating Company, LLC.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/packages/test/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 GoDaddy Operating Company, LLC.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/packages/webpack/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 GoDaddy Operating Company, LLC.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/packages/dimensions/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2019 GoDaddy Operating Company, LLC.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/packages/provider/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 GoDaddy Operating Company, LLC.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/examples/reactnative/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
12 |
13 |
19 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/packages/test/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "asset-test",
3 | "version": "1.0.0",
4 | "description": "Test fixtures for the asset-system",
5 | "main": "./lib",
6 | "homepage": "https://github.com/godaddy/asset-system/tree/master/packages/test",
7 | "repository": {
8 | "type": "git",
9 | "url": "git@github.com:godaddy/asset-system.git"
10 | },
11 | "scripts": {
12 | "prepublishOnly": "npm run build",
13 | "build": "rm -rf ./lib && babel ./src/*.js -d ./lib"
14 | },
15 | "keywords": [
16 | "Asset",
17 | "SVG",
18 | "test",
19 | "tests"
20 | ],
21 | "babel": {
22 | "plugins": [
23 | "@babel/plugin-proposal-object-rest-spread"
24 | ],
25 | "presets": [
26 | "@babel/preset-env",
27 | "@babel/preset-react"
28 | ]
29 | },
30 | "browserify": {
31 | "transform": [
32 | "babelify"
33 | ]
34 | },
35 | "author": "GoDaddy.com Operating Company, LLC",
36 | "contributors": [
37 | "Arnout Kazemier "
38 | ],
39 | "license": "MIT",
40 | "devDependencies": {
41 | "@babel/cli": "^7.1.2",
42 | "@babel/core": "^7.1.2",
43 | "@babel/plugin-proposal-object-rest-spread": "^7.0.0",
44 | "@babel/preset-env": "^7.1.0",
45 | "@babel/preset-react": "^7.0.0",
46 | "@babel/register": "^7.0.0"
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/examples/reactnative/android/app/src/main/java/com/reactnative/MainApplication.java:
--------------------------------------------------------------------------------
1 | package com.reactnative;
2 |
3 | import android.app.Application;
4 |
5 | import com.facebook.react.ReactApplication;
6 | import com.horcrux.svg.SvgPackage;
7 | import com.facebook.react.ReactNativeHost;
8 | import com.facebook.react.ReactPackage;
9 | import com.facebook.react.shell.MainReactPackage;
10 | import com.facebook.soloader.SoLoader;
11 |
12 | import java.util.Arrays;
13 | import java.util.List;
14 |
15 | public class MainApplication extends Application implements ReactApplication {
16 |
17 | private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
18 | @Override
19 | public boolean getUseDeveloperSupport() {
20 | return BuildConfig.DEBUG;
21 | }
22 |
23 | @Override
24 | protected List getPackages() {
25 | return Arrays.asList(
26 | new MainReactPackage(),
27 | new SvgPackage()
28 | );
29 | }
30 |
31 | @Override
32 | protected String getJSMainModuleName() {
33 | return "index";
34 | }
35 | };
36 |
37 | @Override
38 | public ReactNativeHost getReactNativeHost() {
39 | return mReactNativeHost;
40 | }
41 |
42 | @Override
43 | public void onCreate() {
44 | super.onCreate();
45 | SoLoader.init(this, /* native exopackage */ false);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/packages/bundle/test/walker.test.js:
--------------------------------------------------------------------------------
1 | import { describe, it } from 'mocha';
2 | import * as walker from '../walker';
3 | import assume from 'assume';
4 |
5 | describe('walker', function () {
6 | describe('#componentName', function () {
7 | it('transforms svg elements to svgs component names', function () {
8 | assume(walker.componentName('tspan')).equals('TSpan');
9 | assume(walker.componentName('path')).equals('Path');
10 | assume(walker.componentName('radialGradient')).equals('RadialGradient');
11 | });
12 | });
13 |
14 | describe('#attributes', function () {
15 | it('camelCases the attributes', function () {
16 | const result = walker.attributes({
17 | 'stroke-width': '10px'
18 | });
19 |
20 | assume(result).has.length(1);
21 | assume(result.strokeWidth).equals('10px');
22 | });
23 |
24 | it('renames properties if needed', function () {
25 | const result = walker.attributes({
26 | class: 'blue'
27 | });
28 |
29 | assume(result).has.length(1);
30 | assume(result.className).equals('blue');
31 | });
32 |
33 | it('transforms values to number when possible', function () {
34 | const result = walker.attributes({
35 | height: '10'
36 | });
37 |
38 | assume(result).has.length(1);
39 | assume(result.height).equals(10);
40 | });
41 | });
42 | });
43 |
--------------------------------------------------------------------------------
/examples/web/index.js:
--------------------------------------------------------------------------------
1 | import Provider, { Asset, parser } from 'asset-provider';
2 | import React, { Component } from 'react';
3 | import { render } from 'react-dom';
4 |
5 | //
6 | // Add a small modifier for the assets, each time we see the `pants` property
7 | // on an this parser will be called for all paths, circles and what
8 | // not that was used to create the svg.
9 | //
10 | // We know that homer's pants is #669BC7 so we can target that fill color
11 | // and override it with the given value.
12 | //
13 | parser.modify('pants', function (attr, prop, child) {
14 | if (attr.fill !== '#669BC7') return;
15 |
16 | attr.fill = prop.pants;
17 | });
18 |
19 | class Example extends Component {
20 | render() {
21 | return (
22 |
23 |
37 |
38 | );
39 | }
40 | }
41 |
42 | render(, document.getElementById('example'))
43 |
--------------------------------------------------------------------------------
/packages/parser/asset.js:
--------------------------------------------------------------------------------
1 | import { Pass } from 'passing-through';
2 | import diagnostics from 'diagnostics';
3 | import transform from './transform';
4 | import React from 'react';
5 | import { G } from 'svgs';
6 |
7 | //
8 | // Setup our debug util.
9 | //
10 | const debug = diagnostics('asset:parser:asset');
11 |
12 | /**
13 | * Representation of a single Asset of an bundle.
14 | *
15 | * @constructor
16 | * @param {Object} data The data structure.
17 | * @param {Object} hooks Methods that alter the SVG on the fly.
18 | * @param {String} version Version number of the specification.
19 | * @public
20 | */
21 | export default class Asset {
22 | constructor(data, hooks = {}, version) {
23 | this.version = version;
24 | this.hooks = hooks;
25 | this.data = data;
26 |
27 | this.parsed = null;
28 | }
29 |
30 | /**
31 | * Complete the transformation and render asset into a SVG.
32 | *
33 | * @param {Object} changes Optional changes that need to be applied.
34 | * @returns {Object} Svg element and props.
35 | * @returns {React.Element} SVG content that can be displayed.
36 | * @public
37 | */
38 | render(changes = {}) {
39 | if (!this.parsed) {
40 | debug('first time we parse/transform the data');
41 | this.parsed = transform(this.data, this.version);
42 | }
43 |
44 | return {
45 | props: this.parsed.props,
46 | svg: (
47 |
48 | { this.parsed.svg }
49 |
50 | )
51 | };
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/packages/parser/packer.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Our "unique" indentifier that signals the end of the specification version
3 | * number and the start of the actual encoded payload for that given version
4 | * number.
5 | *
6 | * @type {String}
7 | * @private
8 | */
9 | const identifier = '§';
10 |
11 | /**
12 | * Decode the data structure.
13 | *
14 | * @param {String} str String that needs to be decoded.
15 | * @param {Function} fn Error first completion callback.
16 | * @returns {undefined} Nope.
17 | * @public
18 | */
19 | export function decode(str, fn) {
20 | let data;
21 |
22 | //
23 | // The bundle will be prefixed with the version of the bundle specification
24 | // that we follow, so we need to extract that version number before we can
25 | // parse the payload.
26 | //
27 | const end = str.indexOf(identifier);
28 | const version = str.slice(0, end);
29 | const payload = str.slice(end + identifier.length);
30 |
31 | try { data = JSON.parse(payload); } catch (e) { return fn(e); }
32 |
33 | fn(null, { data, version });
34 | }
35 |
36 | /**
37 | * Pack the data structure.
38 | *
39 | * @param {String} spec Specification number.
40 | * @param {Object} data Object structurethat needs to be encoded.
41 | * @param {Function} fn Error first completion callback.
42 | * @returns {undefined} Nope.
43 | * @public
44 | */
45 | export function encode(spec, data, fn) {
46 | let result;
47 |
48 | try { result = JSON.stringify(data); } catch (e) { return fn(e); }
49 |
50 | fn(null, `${spec}${identifier}${result}`);
51 | }
52 |
--------------------------------------------------------------------------------
/examples/reactnative/ios/reactnative/AppDelegate.m:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | #import "AppDelegate.h"
11 |
12 | #import
13 | #import
14 |
15 | @implementation AppDelegate
16 |
17 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
18 | {
19 | NSURL *jsCodeLocation;
20 |
21 | jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
22 |
23 | RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
24 | moduleName:@"reactnative"
25 | initialProperties:nil
26 | launchOptions:launchOptions];
27 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
28 |
29 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
30 | UIViewController *rootViewController = [UIViewController new];
31 | rootViewController.view = rootView;
32 | self.window.rootViewController = rootViewController;
33 | [self.window makeKeyAndVisible];
34 | return YES;
35 | }
36 |
37 | @end
38 |
--------------------------------------------------------------------------------
/packages/dimensions/test.js:
--------------------------------------------------------------------------------
1 | import { fixtures } from 'asset-test';
2 | import { describe, it } from 'mocha';
3 | import dimensions from './index.js';
4 | import { load } from 'cheerio';
5 | import assume from 'assume';
6 | import path from 'path';
7 | import fs from 'fs';
8 |
9 | describe('dimensions', function () {
10 | function prepare(file) {
11 |
12 | // eslint-disable-next-line
13 | const source = fs.readFileSync(file, 'utf-8');
14 | const tree = load(source, { decodeEntities: false });
15 |
16 | return { file, source, tree };
17 | }
18 |
19 | it('extracts the viewBox from the svg', async function () {
20 | const godaddy = path.join(fixtures, 'godaddy.svg');
21 | const item = prepare(godaddy);
22 |
23 | const result = await dimensions(item);
24 |
25 | assume(result).is.a('object');
26 | assume(result.viewBox).equals('0 0 127 55.2');
27 | assume(result.x).equals(0);
28 | assume(result.y).equals(0);
29 | assume(result.width).equals(127);
30 | assume(result.height).equals(55.2);
31 | });
32 |
33 | it('extracts the full viewBox by rendering headless', async function () {
34 | const tiger = path.join(fixtures, 'tiger.svg');
35 | const item = prepare(tiger);
36 |
37 | const result = await dimensions(item);
38 |
39 | assume(result.viewBox).equals('16.072998046875 55.626800537109375 493.87451171875 509.1741638183594');
40 | assume(result.x).equals(16.072998046875);
41 | assume(result.y).equals(55.626800537109375);
42 | assume(result.width).equals(493.87451171875);
43 | assume(result.height).equals(509.1741638183594);
44 | });
45 | });
46 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "asset-system",
3 | "version": "1.0.0",
4 | "description": "asset-system is a cross platform asset system for React and React-Native. This repo is the home for all asset- packages.",
5 | "main": "index.js",
6 | "scripts": {
7 | "publish:dimensions": "mono --publish dimensions",
8 | "publish:provider": "mono --publish provider",
9 | "publish:webpack": "mono --publish webpack",
10 | "publish:parser": "mono --publish parser",
11 | "publish:bundle": "mono --publish bundle",
12 | "publish:list": "mono --publish list",
13 | "test:dimensions": "mono --test dimensions",
14 | "test:provider": "mono --test provider",
15 | "test:webpack": "mono --test webpack",
16 | "test:parser": "mono --test parser",
17 | "test:bundle": "mono --test bundle",
18 | "test:list": "mono --test list",
19 | "test": "mono --test",
20 | "publish": "mono --publish",
21 | "install": "mono --install",
22 | "link": "mono --link"
23 | },
24 | "private": true,
25 | "repository": {
26 | "type": "git",
27 | "url": "git@github.com:godaddy/asset-system.git"
28 | },
29 | "keywords": [
30 | "asset"
31 | ],
32 | "babel": {
33 | "presets": [
34 | "@babel/preset-env",
35 | "@babel/preset-react"
36 | ]
37 | },
38 | "author": "GoDaddy Operating Company, LLC",
39 | "license": "MIT",
40 | "contributors": [
41 | "Arnout Kazemier "
42 | ],
43 | "devDependencies": {
44 | "@babel/core": "^7.1.2",
45 | "@babel/preset-env": "^7.1.0",
46 | "@babel/preset-react": "^7.0.0",
47 | "mono-repos": "^0.1.1"
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/examples/reactnative/App.js:
--------------------------------------------------------------------------------
1 | import Provider, { Asset } from 'asset-provider';
2 | import React, { Component } from 'react';
3 | import {
4 | Platform,
5 | StyleSheet,
6 | Text,
7 | View
8 | } from 'react-native';
9 |
10 | const instructions = Platform.select({
11 | ios: 'Press Cmd+R to reload,\n' +
12 | 'Cmd+D or shake for dev menu',
13 | android: 'Double tap R on your keyboard to reload,\n' +
14 | 'Shake or press menu button for dev menu',
15 | });
16 |
17 | export default class App extends Component<{}> {
18 | render() {
19 | return (
20 |
21 |
22 | {instructions}
23 |
24 |
25 |
26 |
27 |
28 | Loading Assets
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | );
38 | }
39 | }
40 |
41 | const styles = StyleSheet.create({
42 | container: {
43 | flex: 1,
44 | justifyContent: 'center',
45 | alignItems: 'center',
46 | backgroundColor: '#F5FCFF',
47 | },
48 | loading: {
49 | fontSize: 20,
50 | textAlign: 'center',
51 | margin: 10,
52 | },
53 | instructions: {
54 | textAlign: 'center',
55 | color: '#333333',
56 | marginBottom: 5,
57 | },
58 | });
59 |
--------------------------------------------------------------------------------
/packages/list/.npmignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # OSX
6 | .DS_Store
7 |
8 | # Xcode
9 | build/
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata
19 | *.xccheckout
20 | *.moved-aside
21 | DerivedData
22 | *.hmap
23 | *.ipa
24 | *.xcuserstate
25 | project.xcworkspace
26 |
27 | # Android/IntelliJ
28 | build/
29 | .idea
30 | .gradle
31 | local.properties
32 | *.iml
33 |
34 | # BUCK
35 | buck-out/
36 | \.buckd/
37 | *.keystore
38 |
39 | # fastlane
40 | #
41 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
42 | # screenshots whenever they are needed.
43 | # For more information about the recommended setup visit:
44 | # https://docs.fastlane.tools/best-practices/source-control/
45 |
46 | */fastlane/report.xml
47 | */fastlane/Preview.html
48 | */fastlane/screenshots
49 |
50 | # Runtime data
51 | pids
52 | *.pid
53 | *.seed
54 |
55 | # Directory for instrumented libs generated by jscoverage/JSCover
56 | lib-cov
57 |
58 | # Coverage directory used by tools like istanbul/nyc
59 | coverage
60 | .nyc_output
61 |
62 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
63 | .grunt
64 |
65 | # node-waf configuration
66 | .lock-wscript
67 |
68 | # Compiled binary addons (http://nodejs.org/api/addons.html)
69 | build/Release
70 |
71 | # Dependency directory and Node.js specific files
72 | node_modules
73 | npm-debug.log
74 | yarn-error.log
75 |
76 | # IDE
77 | .idea
78 | *.iml
79 |
80 | # Ignore build directories
81 | dist
82 |
83 | # Compiled source
84 | !lib
85 |
--------------------------------------------------------------------------------
/packages/test/.npmignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # OSX
6 | .DS_Store
7 |
8 | # Xcode
9 | build/
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata
19 | *.xccheckout
20 | *.moved-aside
21 | DerivedData
22 | *.hmap
23 | *.ipa
24 | *.xcuserstate
25 | project.xcworkspace
26 |
27 | # Android/IntelliJ
28 | build/
29 | .idea
30 | .gradle
31 | local.properties
32 | *.iml
33 |
34 | # BUCK
35 | buck-out/
36 | \.buckd/
37 | *.keystore
38 |
39 | # fastlane
40 | #
41 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
42 | # screenshots whenever they are needed.
43 | # For more information about the recommended setup visit:
44 | # https://docs.fastlane.tools/best-practices/source-control/
45 |
46 | */fastlane/report.xml
47 | */fastlane/Preview.html
48 | */fastlane/screenshots
49 |
50 | # Runtime data
51 | pids
52 | *.pid
53 | *.seed
54 |
55 | # Directory for instrumented libs generated by jscoverage/JSCover
56 | lib-cov
57 |
58 | # Coverage directory used by tools like istanbul/nyc
59 | coverage
60 | .nyc_output
61 |
62 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
63 | .grunt
64 |
65 | # node-waf configuration
66 | .lock-wscript
67 |
68 | # Compiled binary addons (http://nodejs.org/api/addons.html)
69 | build/Release
70 |
71 | # Dependency directory and Node.js specific files
72 | node_modules
73 | npm-debug.log
74 | yarn-error.log
75 |
76 | # IDE
77 | .idea
78 | *.iml
79 |
80 | # Ignore build directories
81 | dist
82 |
83 | # Compiled source
84 | !lib
85 |
--------------------------------------------------------------------------------
/packages/bundle/.npmignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # OSX
6 | .DS_Store
7 |
8 | # Xcode
9 | build/
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata
19 | *.xccheckout
20 | *.moved-aside
21 | DerivedData
22 | *.hmap
23 | *.ipa
24 | *.xcuserstate
25 | project.xcworkspace
26 |
27 | # Android/IntelliJ
28 | build/
29 | .idea
30 | .gradle
31 | local.properties
32 | *.iml
33 |
34 | # BUCK
35 | buck-out/
36 | \.buckd/
37 | *.keystore
38 |
39 | # fastlane
40 | #
41 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
42 | # screenshots whenever they are needed.
43 | # For more information about the recommended setup visit:
44 | # https://docs.fastlane.tools/best-practices/source-control/
45 |
46 | */fastlane/report.xml
47 | */fastlane/Preview.html
48 | */fastlane/screenshots
49 |
50 | # Runtime data
51 | pids
52 | *.pid
53 | *.seed
54 |
55 | # Directory for instrumented libs generated by jscoverage/JSCover
56 | lib-cov
57 |
58 | # Coverage directory used by tools like istanbul/nyc
59 | coverage
60 | .nyc_output
61 |
62 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
63 | .grunt
64 |
65 | # node-waf configuration
66 | .lock-wscript
67 |
68 | # Compiled binary addons (http://nodejs.org/api/addons.html)
69 | build/Release
70 |
71 | # Dependency directory and Node.js specific files
72 | node_modules
73 | npm-debug.log
74 | yarn-error.log
75 |
76 | # IDE
77 | .idea
78 | *.iml
79 |
80 | # Ignore build directories
81 | dist
82 |
83 | # Compiled source
84 | !lib
85 |
--------------------------------------------------------------------------------
/packages/parser/.npmignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # OSX
6 | .DS_Store
7 |
8 | # Xcode
9 | build/
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata
19 | *.xccheckout
20 | *.moved-aside
21 | DerivedData
22 | *.hmap
23 | *.ipa
24 | *.xcuserstate
25 | project.xcworkspace
26 |
27 | # Android/IntelliJ
28 | build/
29 | .idea
30 | .gradle
31 | local.properties
32 | *.iml
33 |
34 | # BUCK
35 | buck-out/
36 | \.buckd/
37 | *.keystore
38 |
39 | # fastlane
40 | #
41 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
42 | # screenshots whenever they are needed.
43 | # For more information about the recommended setup visit:
44 | # https://docs.fastlane.tools/best-practices/source-control/
45 |
46 | */fastlane/report.xml
47 | */fastlane/Preview.html
48 | */fastlane/screenshots
49 |
50 | # Runtime data
51 | pids
52 | *.pid
53 | *.seed
54 |
55 | # Directory for instrumented libs generated by jscoverage/JSCover
56 | lib-cov
57 |
58 | # Coverage directory used by tools like istanbul/nyc
59 | coverage
60 | .nyc_output
61 |
62 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
63 | .grunt
64 |
65 | # node-waf configuration
66 | .lock-wscript
67 |
68 | # Compiled binary addons (http://nodejs.org/api/addons.html)
69 | build/Release
70 |
71 | # Dependency directory and Node.js specific files
72 | node_modules
73 | npm-debug.log
74 | yarn-error.log
75 |
76 | # IDE
77 | .idea
78 | *.iml
79 |
80 | # Ignore build directories
81 | dist
82 |
83 | # Compiled source
84 | !lib
85 |
--------------------------------------------------------------------------------
/packages/provider/.npmignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # OSX
6 | .DS_Store
7 |
8 | # Xcode
9 | build/
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata
19 | *.xccheckout
20 | *.moved-aside
21 | DerivedData
22 | *.hmap
23 | *.ipa
24 | *.xcuserstate
25 | project.xcworkspace
26 |
27 | # Android/IntelliJ
28 | build/
29 | .idea
30 | .gradle
31 | local.properties
32 | *.iml
33 |
34 | # BUCK
35 | buck-out/
36 | \.buckd/
37 | *.keystore
38 |
39 | # fastlane
40 | #
41 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
42 | # screenshots whenever they are needed.
43 | # For more information about the recommended setup visit:
44 | # https://docs.fastlane.tools/best-practices/source-control/
45 |
46 | */fastlane/report.xml
47 | */fastlane/Preview.html
48 | */fastlane/screenshots
49 |
50 | # Runtime data
51 | pids
52 | *.pid
53 | *.seed
54 |
55 | # Directory for instrumented libs generated by jscoverage/JSCover
56 | lib-cov
57 |
58 | # Coverage directory used by tools like istanbul/nyc
59 | coverage
60 | .nyc_output
61 |
62 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
63 | .grunt
64 |
65 | # node-waf configuration
66 | .lock-wscript
67 |
68 | # Compiled binary addons (http://nodejs.org/api/addons.html)
69 | build/Release
70 |
71 | # Dependency directory and Node.js specific files
72 | node_modules
73 | npm-debug.log
74 | yarn-error.log
75 |
76 | # IDE
77 | .idea
78 | *.iml
79 |
80 | # Ignore build directories
81 | dist
82 |
83 | # Compiled source
84 | !lib
85 |
--------------------------------------------------------------------------------
/packages/webpack/.npmignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # OSX
6 | .DS_Store
7 |
8 | # Xcode
9 | build/
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata
19 | *.xccheckout
20 | *.moved-aside
21 | DerivedData
22 | *.hmap
23 | *.ipa
24 | *.xcuserstate
25 | project.xcworkspace
26 |
27 | # Android/IntelliJ
28 | build/
29 | .idea
30 | .gradle
31 | local.properties
32 | *.iml
33 |
34 | # BUCK
35 | buck-out/
36 | \.buckd/
37 | *.keystore
38 |
39 | # fastlane
40 | #
41 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
42 | # screenshots whenever they are needed.
43 | # For more information about the recommended setup visit:
44 | # https://docs.fastlane.tools/best-practices/source-control/
45 |
46 | */fastlane/report.xml
47 | */fastlane/Preview.html
48 | */fastlane/screenshots
49 |
50 | # Runtime data
51 | pids
52 | *.pid
53 | *.seed
54 |
55 | # Directory for instrumented libs generated by jscoverage/JSCover
56 | lib-cov
57 |
58 | # Coverage directory used by tools like istanbul/nyc
59 | coverage
60 | .nyc_output
61 |
62 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
63 | .grunt
64 |
65 | # node-waf configuration
66 | .lock-wscript
67 |
68 | # Compiled binary addons (http://nodejs.org/api/addons.html)
69 | build/Release
70 |
71 | # Dependency directory and Node.js specific files
72 | node_modules
73 | npm-debug.log
74 | yarn-error.log
75 |
76 | # IDE
77 | .idea
78 | *.iml
79 |
80 | # Ignore build directories
81 | dist
82 |
83 | # Compiled source
84 | !lib
85 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # OSX
6 | .DS_Store
7 |
8 | # Xcode
9 | build/
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata
19 | *.xccheckout
20 | *.moved-aside
21 | DerivedData
22 | *.hmap
23 | *.ipa
24 | *.xcuserstate
25 | project.xcworkspace
26 |
27 | # Android/IntelliJ
28 | build/
29 | .idea
30 | .gradle
31 | local.properties
32 | *.iml
33 |
34 | # BUCK
35 | buck-out/
36 | \.buckd/
37 | *.keystore
38 |
39 | # fastlane
40 | #
41 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
42 | # screenshots whenever they are needed.
43 | # For more information about the recommended setup visit:
44 | # https://docs.fastlane.tools/best-practices/source-control/
45 |
46 | */fastlane/report.xml
47 | */fastlane/Preview.html
48 | */fastlane/screenshots
49 |
50 | # Runtime data
51 | pids
52 | *.pid
53 | *.seed
54 |
55 | # Directory for instrumented libs generated by jscoverage/JSCover
56 | lib-cov
57 |
58 | # Coverage directory used by tools like istanbul/nyc
59 | coverage
60 | .nyc_output
61 |
62 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
63 | .grunt
64 |
65 | # node-waf configuration
66 | .lock-wscript
67 |
68 | # Compiled binary addons (http://nodejs.org/api/addons.html)
69 | build/Release
70 |
71 | # Dependency directory and Node.js specific files
72 | node_modules
73 | npm-debug.log
74 | yarn-error.log
75 |
76 | # IDE
77 | .idea
78 | *.iml
79 |
80 | # Ignore build directories
81 | dist
82 |
83 | # Compiled source
84 | lib
85 | package-lock.json
86 |
--------------------------------------------------------------------------------
/packages/dimensions/.npmignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # OSX
6 | .DS_Store
7 |
8 | # Xcode
9 | build/
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata
19 | *.xccheckout
20 | *.moved-aside
21 | DerivedData
22 | *.hmap
23 | *.ipa
24 | *.xcuserstate
25 | project.xcworkspace
26 |
27 | # Android/IntelliJ
28 | build/
29 | .idea
30 | .gradle
31 | local.properties
32 | *.iml
33 |
34 | # BUCK
35 | buck-out/
36 | \.buckd/
37 | *.keystore
38 |
39 | # fastlane
40 | #
41 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
42 | # screenshots whenever they are needed.
43 | # For more information about the recommended setup visit:
44 | # https://docs.fastlane.tools/best-practices/source-control/
45 |
46 | */fastlane/report.xml
47 | */fastlane/Preview.html
48 | */fastlane/screenshots
49 |
50 | # Runtime data
51 | pids
52 | *.pid
53 | *.seed
54 |
55 | # Directory for instrumented libs generated by jscoverage/JSCover
56 | lib-cov
57 |
58 | # Coverage directory used by tools like istanbul/nyc
59 | coverage
60 | .nyc_output
61 |
62 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
63 | .grunt
64 |
65 | # node-waf configuration
66 | .lock-wscript
67 |
68 | # Compiled binary addons (http://nodejs.org/api/addons.html)
69 | build/Release
70 |
71 | # Dependency directory and Node.js specific files
72 | node_modules
73 | npm-debug.log
74 | yarn-error.log
75 |
76 | # IDE
77 | .idea
78 | *.iml
79 |
80 | # Ignore build directories
81 | dist
82 |
83 | # Compiled source
84 | !lib
85 |
--------------------------------------------------------------------------------
/examples/reactnative/ios/reactnative/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | reactnative
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | LSRequiresIPhoneOS
26 |
27 | UILaunchStoryboardName
28 | LaunchScreen
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 | UIViewControllerBasedStatusBarAppearance
40 |
41 | NSLocationWhenInUseUsageDescription
42 |
43 | NSAppTransportSecurity
44 |
45 | NSAllowsLocalNetworking
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/packages/parser/test/packer.test.js:
--------------------------------------------------------------------------------
1 | /* eslint max-nested-callbacks: ["error", 10]*/
2 | import { encode, decode, version as specification } from '../index.js';
3 | import { describe, it } from 'mocha';
4 | import assume from 'assume';
5 |
6 | describe('packer', function () {
7 | describe('#encode', function () {
8 | it('packs an object into a string that can be decoded again', function (next) {
9 | const example = { foo: 'bar' };
10 |
11 | encode(specification, example, function (err, str) {
12 | assume(err).is.a('null');
13 | assume(str).is.a('string');
14 |
15 | decode(str, function (error, payload) {
16 | assume(error).is.a('null');
17 | assume(payload).is.a('object');
18 |
19 | const { version, data } = payload;
20 |
21 | assume(data).deep.equals(example);
22 | assume(version).equals(specification);
23 |
24 | next();
25 | });
26 | });
27 | });
28 |
29 | it('will call the error first on encode error', function (next) {
30 | const example = { foo: 'bar' };
31 | example.example = example; // Circular ref, explode.
32 |
33 | encode(specification, example, function (err, str) {
34 | assume(err).is.a('error');
35 | assume(str).is.a('undefined');
36 |
37 | next();
38 | });
39 | });
40 | });
41 |
42 | describe('#decode', function () {
43 | it('will call the callback with error first on decode error', function (next) {
44 | decode(`${specification}§{ not really: "data" }`, function (err, data) {
45 | assume(err).is.a('error');
46 | assume(data).is.a('undefined');
47 |
48 | next();
49 | });
50 | });
51 | });
52 | });
53 |
--------------------------------------------------------------------------------
/packages/provider/wrapper/index.js:
--------------------------------------------------------------------------------
1 | import diagnostics from 'diagnostics';
2 | import PropTypes from 'prop-types';
3 | import React from 'react';
4 | import Svg from 'svgs';
5 |
6 | //
7 | // Setup our debug util.
8 | //
9 | const debug = diagnostics('asset:provider:wrapper');
10 |
11 | /**
12 | * Wraps svg content with some default Svg properties.
13 | *
14 | * @param {Object} props Properties.
15 | * @returns {Svg} The wrapped Svg.
16 | * @private
17 | */
18 | export default function SvgWrapper(props) {
19 | const attributes = { ...props };
20 |
21 | //
22 | // If we're given a viewBox we want to make sure that we preserveAspectRatio
23 | // correctly so set it to `meet`.
24 | //
25 | if (props.viewBox) {
26 | debug('props have viewBox, adding preserveAspectRatio');
27 | attributes.viewBox = props.viewBox;
28 | attributes.preserveAspectRatio = 'meet';
29 | }
30 |
31 | return (
32 |
35 | );
36 | }
37 |
38 | /**
39 | * We don't want a pure number, a string value that represents a number
40 | * is fine as well
41 | *
42 | * @type {PropTypes}
43 | * @private
44 | */
45 | const numeric = PropTypes.oneOfType([
46 | PropTypes.string,
47 | PropTypes.number
48 | ]).isRequired;
49 |
50 | /**
51 | * Force validation for some default properties that will be required to render
52 | * assets.
53 | *
54 | * Width and Height are required because we to prevent layout changes, so a pre
55 | * existing height/width needs to be known.
56 | *
57 | * @type {Object}
58 | * @private
59 | */
60 | SvgWrapper.propTypes = {
61 | width: numeric,
62 | height: numeric,
63 | viewBox: PropTypes.string,
64 | children: PropTypes.element,
65 | title: PropTypes.string
66 | };
67 |
--------------------------------------------------------------------------------
/packages/dimensions/render.js:
--------------------------------------------------------------------------------
1 | let puppeteer;
2 | try {
3 | puppeteer = require('puppeteer');
4 | } catch (ex) {
5 | //
6 | // Ignore errors here since the consumer is notified
7 | // at run-time only in ./index.js
8 | //
9 | }
10 |
11 | /**
12 | * Extract height and width from an SVG by rendering it and extracting
13 | * the bounding box information.
14 | *
15 | * @param {String} svg The svg we want to render.
16 | * @returns {Object} Calculated dimensions for the boundingbox.
17 | * @public
18 | */
19 | export default async function render(svg) {
20 | const html = `${svg}`;
21 | const browser = await puppeteer.launch({ headless: true });
22 | const page = await browser.newPage();
23 | const loaded = page.waitForNavigation({ waitUntil: 'load' });
24 |
25 | await page.setContent(html);
26 | await loaded;
27 |
28 | //
29 | // Extract the bounding box information from the loaded SVG. The istanbul
30 | // ignore is of vital importance because the `evaluate` code is executed
31 | // in the headless chrome, not in this node process so it cannot access the
32 | // injected `cov_2feitg0dis` references.
33 | //
34 | /* istanbul ignore next */
35 | const dimensions = await page.evaluate(() => {
36 | //
37 | // Hacks part II, the sequel.
38 | //
39 | // Apparently you cannot directly return the bouding box information, no,
40 | // you need to extract the information from the resulting boundingBox
41 | // object, and then return it again. Because, serialization of data is hard
42 | // I guess.
43 | //
44 | const { width, height, x, y } = document.getElementsByTagName('svg')[0].getBBox();
45 | return { width, height, x, y };
46 | });
47 |
48 | await browser.close();
49 |
50 | return dimensions;
51 | }
52 |
--------------------------------------------------------------------------------
/packages/bundle/test/snapshots.test.js:
--------------------------------------------------------------------------------
1 | import { decode } from 'asset-parser';
2 | import { fixtures } from 'asset-test';
3 | import { describe, it } from 'mocha';
4 | import Bundle from '../index';
5 | import assume from 'assume';
6 | import path from 'path';
7 | import fs from 'fs';
8 |
9 | /**
10 | * Small helper function to finding all the fixtures.
11 | *
12 | * @param {String} ext Extension name
13 | * @param {String} name File name
14 | * @returns {String} Absolute location
15 | * @private
16 | */
17 | function find(ext, name) {
18 | return path.join(fixtures, name + '.' + ext);
19 | }
20 |
21 | /**
22 | * List of all the fixtures we're testing.
23 | *
24 | * @type {Array}
25 | * @private
26 | */
27 | const tests = [
28 | 'tiger',
29 | 'homer',
30 | 'homer-no-viewbox',
31 | 'godaddy'
32 | ];
33 |
34 | describe('snapshots', function () {
35 | this.timeout(10 * 1000);
36 |
37 | let bundle;
38 | let svgs;
39 |
40 | before(function (next) {
41 | bundle = new Bundle(tests.map(find.bind(find, 'svg')));
42 |
43 | bundle.run(function run(err, str) {
44 | if (err) return next(err);
45 |
46 | decode(str, function (fail, payload) {
47 | if (fail) return next(fail);
48 |
49 | svgs = payload.data;
50 |
51 | next();
52 | });
53 | });
54 | });
55 |
56 | tests.forEach(function each(name) {
57 | it(`correctly transforms the ${name} fixture`, function () {
58 | const item = svgs[name];
59 | const output = JSON.parse(fs.readFileSync(find('json', name), 'utf-8'));
60 |
61 | assume(item).is.a('array');
62 | assume(item).deep.equals(output);
63 |
64 | //
65 | // Uncomment the following line if you want to change the new snapshot:
66 | //
67 | // - fs.writeFileSync(find('json', name), JSON.stringify(item), 'utf-8');
68 | });
69 | });
70 | });
71 |
--------------------------------------------------------------------------------
/examples/reactnative/ios/reactnative-tvOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UIViewControllerBasedStatusBarAppearance
38 |
39 | NSLocationWhenInUseUsageDescription
40 |
41 | NSAppTransportSecurity
42 |
43 |
44 | NSExceptionDomains
45 |
46 | localhost
47 |
48 | NSExceptionAllowsInsecureHTTPLoads
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/examples/reactnative/android/app/BUCK:
--------------------------------------------------------------------------------
1 | # To learn about Buck see [Docs](https://buckbuild.com/).
2 | # To run your application with Buck:
3 | # - install Buck
4 | # - `npm start` - to start the packager
5 | # - `cd android`
6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"`
7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
8 | # - `buck install -r android/app` - compile, install and run application
9 | #
10 |
11 | lib_deps = []
12 |
13 | for jarfile in glob(['libs/*.jar']):
14 | name = 'jars__' + jarfile[jarfile.rindex('/') + 1: jarfile.rindex('.jar')]
15 | lib_deps.append(':' + name)
16 | prebuilt_jar(
17 | name = name,
18 | binary_jar = jarfile,
19 | )
20 |
21 | for aarfile in glob(['libs/*.aar']):
22 | name = 'aars__' + aarfile[aarfile.rindex('/') + 1: aarfile.rindex('.aar')]
23 | lib_deps.append(':' + name)
24 | android_prebuilt_aar(
25 | name = name,
26 | aar = aarfile,
27 | )
28 |
29 | android_library(
30 | name = "all-libs",
31 | exported_deps = lib_deps,
32 | )
33 |
34 | android_library(
35 | name = "app-code",
36 | srcs = glob([
37 | "src/main/java/**/*.java",
38 | ]),
39 | deps = [
40 | ":all-libs",
41 | ":build_config",
42 | ":res",
43 | ],
44 | )
45 |
46 | android_build_config(
47 | name = "build_config",
48 | package = "com.reactnative",
49 | )
50 |
51 | android_resource(
52 | name = "res",
53 | package = "com.reactnative",
54 | res = "src/main/res",
55 | )
56 |
57 | android_binary(
58 | name = "app",
59 | keystore = "//android/keystores:debug",
60 | manifest = "src/main/AndroidManifest.xml",
61 | package_type = "debug",
62 | deps = [
63 | ":app-code",
64 | ],
65 | )
66 |
--------------------------------------------------------------------------------
/packages/list/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "asset-list",
3 | "version": "2.0.0",
4 | "description": "Automatically generate documentation for your generated asset-bundle's",
5 | "main": "./lib",
6 | "browser": "./lib",
7 | "module": "./index",
8 | "react-native": "./index",
9 | "scripts": {
10 | "test:web": "mocha --colors --require setup-env test/*.test.js",
11 | "test": "nyc --reporter=text --reporter=lcov npm run test:web",
12 | "prepublishOnly": "npm run build",
13 | "build": "rm -rf ./lib && babel ./index.js -d ./lib",
14 | "lint": "eslint-godaddy *.js ./test/*.js"
15 | },
16 | "dependencies": {
17 | "bytes": "^3.0.0",
18 | "diagnostics": "^1.1.0",
19 | "markdown-table": "^1.1.1",
20 | "mkdirp": "^0.5.1"
21 | },
22 | "devDependencies": {
23 | "@babel/cli": "^7.1.2",
24 | "@babel/core": "^7.1.2",
25 | "@babel/plugin-proposal-object-rest-spread": "^7.0.0",
26 | "@babel/preset-env": "^7.1.0",
27 | "@babel/register": "^7.0.0",
28 | "asset-bundle": "latest",
29 | "asset-test": "latest",
30 | "assume": "^1.5.2",
31 | "clone": "^2.1.1",
32 | "eslint": "^4.14.0",
33 | "eslint-config-godaddy": "^2.1.0",
34 | "eslint-plugin-json": "^1.2.0",
35 | "eslint-plugin-mocha": "^4.11.0",
36 | "mocha": "^4.1.0",
37 | "nyc": "^11.4.1",
38 | "puppeteer": "^1.9.0",
39 | "setup-env": "^1.2.1"
40 | },
41 | "babel": {
42 | "plugins": [
43 | "@babel/plugin-proposal-object-rest-spread"
44 | ],
45 | "presets": [
46 | "@babel/preset-env"
47 | ]
48 | },
49 | "browserify": {
50 | "transform": [
51 | "babelify"
52 | ]
53 | },
54 | "homepage": "https://github.com/godaddy/asset-system/tree/master/packages/list",
55 | "repository": {
56 | "type": "git",
57 | "url": "git@github.com:godaddy/asset-system.git"
58 | },
59 | "author": "GoDaddy.com Operating Company, LLC",
60 | "contributors": [
61 | "Arnout Kazemier "
62 | ],
63 | "license": "MIT"
64 | }
65 |
--------------------------------------------------------------------------------
/examples/reactnative/README.md:
--------------------------------------------------------------------------------
1 | # react-native
2 |
3 | A small demo that implements the `asset-provider` in a React-Native
4 | application.
5 |
6 | ## Starting the demo
7 |
8 | Make sure that all dependencies are installed (we do assume that you already
9 | have your machine setup for React-Native development):
10 |
11 | ```
12 | npm install .
13 | ```
14 |
15 | In addition to the dependencies of this repository you also need to install
16 | the dependencies of the `web` example as we will use that web server to
17 | serve the svg bundle to the React-Native application.
18 |
19 | ```
20 | cd .. && cd web && npm install .
21 | ```
22 |
23 | Once all dependencies are installed we need to start the web server of the `web`
24 | example. So navigate back to `web` folder and run:
25 |
26 | ```
27 | npm start
28 | ```
29 |
30 | Once the application is started we can boot up our React-Native application:
31 |
32 | ```
33 | react-native run-ios
34 | react-native run-android
35 | ```
36 |
37 | ## How is the demo setup
38 |
39 | ### App.js
40 |
41 | This is the entry point of the application and where we've implemented the
42 | `asset-provider`. So how is it build up?
43 |
44 | - The first and basically only notable change here is that we needed to install
45 | `react-native-svg` as a dependency of the project so we can render SVG
46 | on the devices. The rest is the same as on the web.
47 | - The `` and `` components are imported from the
48 | `asset-provider` module.
49 | - We create a `` component that downloads the `homer`, `godaddy`
50 | and `tiger` svg from the generated bundle.
51 | - We add ``'s as child components of the `` and reference the
52 | assets using the `name` property of the ``.
53 | - One of the ``s has a `` component as child node. This will
54 | be visible while we are download the asset from our server and will be
55 | replaced with the actual asset once the bundle is downloaded.
56 |
57 | ### Server
58 |
59 | The server aspect of the example is documented at the `web` example.
60 |
--------------------------------------------------------------------------------
/packages/provider/context/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component, createContext } from 'react';
2 | import Fallback from '../fallback';
3 |
4 | const { Provider, Consumer } = createContext({
5 | modifiers: () => ([]),
6 | getItem: [],
7 | Fallback
8 | });
9 |
10 | /**
11 | * Flatten the consumer and receiver data into a single array.
12 | *
13 | * @param {Array|Function} consumer
14 | * @param {Array|Function} receiver
15 | * @returns {Array}
16 | * @public
17 | */
18 | function flatten(consumer, receiver) {
19 | return [].concat(consumer).concat(receiver).filter((value, index, all) => {
20 | return value && all.indexOf(value) === index;
21 | });
22 | }
23 |
24 | /**
25 | * Prosumer is a provider combined with a consumer, so you can inherit from
26 | * for your provider.
27 | *
28 | * @param {Object} props The props.
29 | * @public
30 | */
31 | function ProSumer({ children, fallback, getItem, modifiers }) {
32 | return (
33 |
34 | {
35 | (context) => (
36 |
41 | { children }
42 |
43 | )
44 | }
45 |
46 | );
47 | }
48 |
49 | /**
50 | * Wraps the a given component with the Consumer and applies the Context as
51 | * props.
52 | *
53 | * @param {Component} Component The component that needs to receive the context
54 | * @returns {Component} The Consumer wrapped component.
55 | * @public
56 | */
57 | function withContext(Component) {
58 | const forward = React.forwardRef((props, ref) => (
59 |
60 | {
61 | (context) => (
62 |
63 | )
64 | }
65 |
66 | ));
67 |
68 | forward.displayName = `${Component.name}(consumer)`;
69 | return forward;
70 | }
71 |
72 | export {
73 | withContext,
74 | ProSumer,
75 | Provider,
76 | Consumer
77 | }
78 |
--------------------------------------------------------------------------------
/packages/parser/test/asset.test.js:
--------------------------------------------------------------------------------
1 | import { create } from 'asset-test';
2 | import { describe, it } from 'mocha';
3 | import { mount } from 'enzyme';
4 | import * as svgs from 'svgs';
5 | import Asset from '../asset';
6 | import assume from 'assume';
7 | import React from 'react';
8 |
9 | const fixture = create(svgs, React);
10 | const Svg = svgs.Svg;
11 |
12 | describe('Asset', function () {
13 | let asset;
14 |
15 | function setup(name, hooks) {
16 | asset = new Asset(fixture[name].structure, hooks);
17 | }
18 |
19 | it('is exported as a function', function () {
20 | assume(Asset).is.a('function');
21 | });
22 |
23 | it('does not transform the asset by default', function () {
24 | setup('complex');
25 |
26 | assume(asset.data).equals(fixture.complex.structure);
27 | assume(asset.parsed).is.a('null');
28 | });
29 |
30 | describe('#render', function () {
31 | it('parses the data if its not parsed before', function () {
32 | setup('complex');
33 |
34 | asset.render();
35 | const parsed = asset.parsed;
36 |
37 | assume(parsed).is.not.a('null');
38 |
39 | asset.data = fixture.g.structure;
40 | asset.render();
41 |
42 | assume(asset.parsed).equals(parsed);
43 | });
44 |
45 | it('returns a component', function () {
46 | setup('childs');
47 |
48 | const result = asset.render();
49 | const wrapper = mount();
50 |
51 | assume(mount(fixture.childs.output).html()).contains(wrapper.html());
52 | });
53 |
54 | it('passes the changes to the component', function () {
55 | setup('green', {
56 | 'color': [function modify(attributes, props) {
57 | if (!attributes.fill) return;
58 |
59 | attributes.fill = props.color;
60 | }]
61 | });
62 |
63 | const result = asset.render({ color: 'red' });
64 | const wrapper = mount();
65 |
66 | assume(wrapper.html()).to.contain('');
67 | });
68 | });
69 | });
70 |
--------------------------------------------------------------------------------
/packages/webpack/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "asset-webpack",
3 | "version": "6.0.0",
4 | "description": "asset-bundle integration for WebPack",
5 | "main": "./lib",
6 | "browser": "./lib",
7 | "module": "./index",
8 | "react-native": "./index",
9 | "scripts": {
10 | "test:web": "mocha --colors --require setup-env test/*.test.js",
11 | "test": "npm run build && nyc --reporter=text --reporter=lcov npm run test:web",
12 | "prepublish": "npm run build",
13 | "build": "babel ./index.js ./loader.js -d ./lib",
14 | "lint": "eslint-godaddy *.js ./test/*.js"
15 | },
16 | "homepage": "https://github.com/godaddy/asset-system/tree/master/packages/webpack",
17 | "repository": {
18 | "type": "git",
19 | "url": "git@github.com:godaddy/asset-system.git"
20 | },
21 | "author": "GoDaddy.com Operating Company, LLC",
22 | "contributors": [
23 | "Arnout Kazemier "
24 | ],
25 | "license": "MIT",
26 | "babel": {
27 | "plugins": [
28 | "@babel/plugin-proposal-object-rest-spread"
29 | ],
30 | "presets": [
31 | "@babel/preset-env",
32 | "@babel/preset-react"
33 | ]
34 | },
35 | "browserify": {
36 | "transform": [
37 | "babelify"
38 | ]
39 | },
40 | "nyc": {
41 | "exclude": [
42 | "lib"
43 | ]
44 | },
45 | "devDependencies": {
46 | "@babel/cli": "^7.1.2",
47 | "@babel/core": "^7.1.2",
48 | "@babel/plugin-proposal-object-rest-spread": "^7.0.0",
49 | "@babel/preset-env": "^7.1.0",
50 | "@babel/preset-react": "^7.0.0",
51 | "@babel/register": "^7.0.0",
52 | "asset-test": "^1.0.0",
53 | "assume": "^1.5.2",
54 | "eslint": "^4.14.0",
55 | "eslint-config-godaddy": "^2.1.0",
56 | "eslint-plugin-json": "^1.2.0",
57 | "eslint-plugin-mocha": "^4.11.0",
58 | "eslint-plugin-react": "^7.5.1",
59 | "mocha": "^4.1.0",
60 | "nyc": "^11.4.1",
61 | "puppeteer": "^1.9.0",
62 | "setup-env": "^1.2.1",
63 | "webpack": "^4.20.2"
64 | },
65 | "dependencies": {
66 | "asset-bundle": "^4.1.0",
67 | "async": "^2.6.0",
68 | "loader-utils": "^1.1.0"
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/RELEASING.md:
--------------------------------------------------------------------------------
1 | # Releasing
2 |
3 | Some of the packages are tightly coupled and need to be released in a specific
4 | order. This file documents the order and release process of all the packages
5 | that are included in the Asset-System project.
6 |
7 | Releases are done using the `mono-repos` module:
8 |
9 | ```
10 | npm install -g mono-repos
11 | ```
12 |
13 | ## test
14 |
15 | This is the bundle that includes all test fixtures that are shared between
16 | the various of packages. This is probably the first package that you want to
17 | bump to latest and ensure that every sub-package receives the latest and
18 | greatest version:
19 |
20 | ```
21 | mono --publish test --version x.x.x
22 | ```
23 |
24 | Once released, bump version in _every_ package.
25 |
26 | ## parser
27 |
28 | If there are `asset-parser` changes, update the version in the `CHANGELOG.md`
29 | and release a new version:
30 |
31 | ```
32 | mono --publish parser --version x.x.x
33 | ```
34 |
35 | - Bump released version in `asset-provider`
36 | - Bump released version in `asset-bundle`
37 |
38 | ## provider
39 |
40 | If there are `asset-provider` changes, update the version in the `CHANGELOG.md`
41 | and release a new version:
42 |
43 | ```
44 | mono --publish provider --version x.x.x
45 | ```
46 |
47 | ## dimensions
48 |
49 | If there are `asset-dimensions` changes, update the version in the `CHANGELOG.md`
50 | and release a new version:
51 |
52 | ```
53 | mono --publish dimensions --version x.x.x
54 | ```
55 |
56 | - Bump released version in `asset-bundle`
57 |
58 | ## bundle
59 |
60 | If there are `asset-bundle` changes, update the version in the `CHANGELOG.md`
61 | and release a new version:
62 |
63 | ```
64 | mono --publish bundle --version x.x.x
65 | ```
66 |
67 | - Bump released version in `asset-webpack`
68 |
69 | ## webpack
70 |
71 | If there are `asset-webpack` changes, update the version in the `CHANGELOG.md`
72 | and release a new version:
73 |
74 | ```
75 | mono --publish webpack --version x.x.x
76 | ```
77 |
78 | ## list
79 |
80 | If there are `asset-list` changes, update the version in the `CHANGELOG.md`
81 | and release a new version:
82 |
83 | ```
84 | mono --publish webpack --list x.x.x
85 | ```
86 |
--------------------------------------------------------------------------------
/packages/dimensions/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "asset-dimensions",
3 | "version": "1.0.0",
4 | "description": "Get the size of your asset in width and height",
5 | "main": "./lib",
6 | "module": "./index",
7 | "scripts": {
8 | "build": "rm -rf ./lib && babel ./index.js -d ./lib && babel ./render.js -d ./lib",
9 | "test:runner": "mocha --colors --require setup-env test.js",
10 | "test": "npm run build && nyc --reporter=text --reporter=lcov npm run test:runner",
11 | "lint": "eslint-godaddy *.js"
12 | },
13 | "repository": {
14 | "type": "git",
15 | "url": "git+ssh://git@github.com/godaddy/asset-system.git"
16 | },
17 | "keywords": [
18 | "asset",
19 | "size",
20 | "svg",
21 | "dimensions",
22 | "width",
23 | "height",
24 | "calculate",
25 | "parse"
26 | ],
27 | "babel": {
28 | "plugins": [
29 | "@babel/plugin-proposal-object-rest-spread"
30 | ],
31 | "presets": [
32 | [
33 | "@babel/preset-env",
34 | {
35 | "targets": {
36 | "node": 9
37 | }
38 | }
39 | ],
40 | "@babel/preset-react"
41 | ]
42 | },
43 | "author": "GoDaddy.com Operating Company, LLC",
44 | "contributors": [
45 | "Arnout Kazemier "
46 | ],
47 | "license": "MIT",
48 | "bugs": {
49 | "url": "https://github.com/godaddy/asset-system/issues"
50 | },
51 | "homepage": "https://github.com/godaddy/asset-system/tree/master/packages/dimensions",
52 | "devDependencies": {
53 | "@babel/cli": "^7.1.2",
54 | "@babel/core": "^7.1.2",
55 | "@babel/plugin-proposal-object-rest-spread": "^7.0.0",
56 | "@babel/preset-env": "^7.1.0",
57 | "@babel/preset-react": "^7.0.0",
58 | "@babel/register": "^7.0.0",
59 | "asset-test": "^1.0.0",
60 | "assume": "^1.5.2",
61 | "cheerio": "^1.0.0-rc.3",
62 | "eslint": "^4.14.0",
63 | "eslint-config-godaddy": "^2.1.0",
64 | "eslint-plugin-json": "^1.2.0",
65 | "eslint-plugin-mocha": "^4.11.0",
66 | "eslint-plugin-react": "^7.5.1",
67 | "mocha": "^5.0.1",
68 | "nyc": "^11.4.1",
69 | "puppeteer": "^1.1.0",
70 | "setup-env": "^1.2.1"
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/examples/reactnative/ios/reactnativeTests/reactnativeTests.m:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | #import
11 | #import
12 |
13 | #import
14 | #import
15 |
16 | #define TIMEOUT_SECONDS 600
17 | #define TEXT_TO_LOOK_FOR @"Welcome to React Native!"
18 |
19 | @interface reactnativeTests : XCTestCase
20 |
21 | @end
22 |
23 | @implementation reactnativeTests
24 |
25 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test
26 | {
27 | if (test(view)) {
28 | return YES;
29 | }
30 | for (UIView *subview in [view subviews]) {
31 | if ([self findSubviewInView:subview matching:test]) {
32 | return YES;
33 | }
34 | }
35 | return NO;
36 | }
37 |
38 | - (void)testRendersWelcomeScreen
39 | {
40 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController];
41 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
42 | BOOL foundElement = NO;
43 |
44 | __block NSString *redboxError = nil;
45 | RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
46 | if (level >= RCTLogLevelError) {
47 | redboxError = message;
48 | }
49 | });
50 |
51 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
52 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
53 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
54 |
55 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) {
56 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
57 | return YES;
58 | }
59 | return NO;
60 | }];
61 | }
62 |
63 | RCTSetLogFunction(RCTDefaultLogFunction);
64 |
65 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
66 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
67 | }
68 |
69 |
70 | @end
71 |
--------------------------------------------------------------------------------
/packages/parser/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "asset-parser",
3 | "version": "3.0.0",
4 | "description": "Parse SVG asset bundles",
5 | "main": "./lib",
6 | "browser": "./lib",
7 | "module": "./index",
8 | "react-native": "./index",
9 | "scripts": {
10 | "test:web": "mocha --colors --require setup-env test/*.test.js",
11 | "test": "nyc --reporter=text --reporter=lcov npm run test:web",
12 | "prepublishOnly": "npm run build",
13 | "build": "rm -rf ./lib && babel ./asset.js ./index.js ./packer.js ./transform.js -d ./lib",
14 | "lint": "eslint-godaddy-react *.js packer/*.js passthrough/*.js ./test/*.js"
15 | },
16 | "homepage": "https://github.com/godaddy/asset-system/tree/master/packages/parser",
17 | "repository": {
18 | "type": "git",
19 | "url": "git@github.com:godaddy/asset-system.git"
20 | },
21 | "keywords": [
22 | "Asset",
23 | "SVG",
24 | "parser"
25 | ],
26 | "babel": {
27 | "plugins": [
28 | "@babel/plugin-proposal-object-rest-spread"
29 | ],
30 | "presets": [
31 | "@babel/preset-env",
32 | "@babel/preset-react"
33 | ]
34 | },
35 | "browserify": {
36 | "transform": [
37 | "babelify"
38 | ]
39 | },
40 | "author": "GoDaddy.com Operating Company, LLC",
41 | "contributors": [
42 | "Arnout Kazemier "
43 | ],
44 | "license": "MIT",
45 | "devDependencies": {
46 | "@babel/cli": "^7.1.2",
47 | "@babel/core": "^7.1.2",
48 | "@babel/plugin-proposal-object-rest-spread": "^7.0.0",
49 | "@babel/preset-env": "^7.1.0",
50 | "@babel/preset-react": "^7.0.0",
51 | "@babel/register": "^7.0.0",
52 | "asset-test": "^1.0.0",
53 | "assume": "^1.5.2",
54 | "assume-enzyme": "^0.0.1",
55 | "enzyme": "^3.9.0",
56 | "enzyme-adapter-react-16": "^1.13.2",
57 | "eslint": "^4.14.0",
58 | "eslint-config-godaddy-react": "^2.1.0",
59 | "eslint-plugin-json": "^1.2.0",
60 | "eslint-plugin-mocha": "^4.11.0",
61 | "eslint-plugin-react": "^7.5.1",
62 | "jsdom": "^11.5.1",
63 | "mocha": "^5.0.1",
64 | "nyc": "^11.4.1",
65 | "prop-types": "^15.6.0",
66 | "react": "^16.8.6",
67 | "react-dom": "^16.8.6",
68 | "react-test-renderer": "^16.2.0",
69 | "setup-env": "^1.2.1"
70 | },
71 | "dependencies": {
72 | "diagnostics": "^1.1.0",
73 | "passing-through": "^1.0.0",
74 | "rip-out": "^1.0.0",
75 | "svgs": "^4.0.0"
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/packages/parser/test/transform.test.js:
--------------------------------------------------------------------------------
1 | import { Pass } from 'passing-through';
2 | import transform from '../transform';
3 | import { describe, it } from 'mocha';
4 | import { create } from 'asset-test';
5 | import { mount } from 'enzyme';
6 | import * as svgs from 'svgs';
7 | import assume from 'assume';
8 | import React from 'react';
9 |
10 | const fixture = create(svgs, React);
11 | const Text = svgs.Text;
12 | const Svg = svgs.Svg;
13 |
14 | describe('transform', function () {
15 | let wrapper;
16 | let output;
17 |
18 | function setup(data, hooks) {
19 | const { svg, props } = transform(data, hooks);
20 | wrapper = mount();
21 | output = wrapper.html();
22 | }
23 |
24 | it('is exported as a function', function () {
25 | assume(transform).is.a('function');
26 | });
27 |
28 | it('transforms the first element of an array to component', function () {
29 | setup(fixture.g.structure);
30 |
31 | assume(wrapper).to.contain(fixture.g.output);
32 | assume(wrapper).to.not.contain(); // sanity check
33 | });
34 |
35 | it('applies the second element of the array as properties', function () {
36 | setup(fixture.green.structure);
37 |
38 | assume(wrapper).to.contain(fixture.green.output);
39 | });
40 |
41 | it('adds child components when an array is encountered', function () {
42 | setup(fixture.childs.structure);
43 |
44 | assume(output).to.contain(mount(fixture.childs.output).html());
45 | });
46 |
47 | it('complex deeply tested svgs', function () {
48 | setup(fixture.complex.structure);
49 |
50 | assume(output).to.contain(mount(fixture.complex.output).html());
51 | });
52 |
53 | it('returns props even when no svg with props is found in structure', function () {
54 | const result = transform([['Text', ['Hello']]]);
55 |
56 | assume(result.props).is.a('object');
57 | assume(result.props).has.length(0);
58 | });
59 |
60 | it('returns text when a component cannot be found', function () {
61 | const result = transform([['what']]).svg;
62 | assume(result).deep.equals(['what']);
63 | });
64 |
65 | it('extracts the Svg element from the structure and adds its props to props', function () {
66 | const result = transform(fixture.json.godaddy);
67 |
68 | assume(result.props).is.a('object');
69 | assume(result.props).has.length(1);
70 | assume(result.props.viewBox).equals('0 0 127 55.2');
71 | });
72 | });
73 |
--------------------------------------------------------------------------------
/packages/bundle/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "asset-bundle",
3 | "version": "4.1.0",
4 | "description": "Build process that transforms (multiple) SVG assets into a asset-parser compatible bundle",
5 | "main": "./lib",
6 | "browser": "./lib",
7 | "module": "./index",
8 | "react-native": "./index",
9 | "scripts": {
10 | "test:web": "mocha --colors --require setup-env test/*.test.js",
11 | "test": "npm run build && nyc --reporter=text --reporter=lcov npm run test:web",
12 | "prepublishOnly": "npm run build",
13 | "build": "rm -rf ./lib && babel ./index.js -d ./lib && babel ./walker/*.js -d ./lib/walker",
14 | "lint": "eslint-godaddy *.js ./test/*.js"
15 | },
16 | "dependencies": {
17 | "asset-dimensions": "^1.0.0",
18 | "asset-parser": "^3.0.0",
19 | "async": "^2.6.0",
20 | "camel-case": "^3.0.0",
21 | "cheerio": "^1.0.0-rc.2",
22 | "diagnostics": "^1.1.0",
23 | "react": "^16.2.0",
24 | "svgo": "^1.0.3"
25 | },
26 | "devDependencies": {
27 | "@babel/cli": "^7.1.2",
28 | "@babel/core": "^7.1.2",
29 | "@babel/plugin-proposal-object-rest-spread": "^7.0.0",
30 | "@babel/preset-env": "^7.1.0",
31 | "@babel/preset-react": "^7.0.0",
32 | "@babel/register": "^7.0.0",
33 | "asset-test": "^1.0.0",
34 | "assume": "^1.5.2",
35 | "eslint": "^4.14.0",
36 | "eslint-config-godaddy": "^2.1.0",
37 | "eslint-plugin-json": "^1.2.0",
38 | "eslint-plugin-mocha": "^4.11.0",
39 | "eslint-plugin-react": "^7.5.1",
40 | "mocha": "^5.0.1",
41 | "nyc": "^11.4.1",
42 | "puppeteer": "^1.1.0",
43 | "setup-env": "^1.2.1"
44 | },
45 | "babel": {
46 | "plugins": [
47 | "@babel/plugin-proposal-object-rest-spread"
48 | ],
49 | "presets": [
50 | [
51 | "@babel/preset-env",
52 | {
53 | "targets": {
54 | "node": 9
55 | }
56 | }
57 | ],
58 | "@babel/preset-react"
59 | ]
60 | },
61 | "browserify": {
62 | "transform": [
63 | "babelify"
64 | ]
65 | },
66 | "nyc": {
67 | "exclude": [
68 | "lib"
69 | ]
70 | },
71 | "homepage": "https://github.com/godaddy/asset-system/tree/master/packages/bundle",
72 | "repository": {
73 | "type": "git",
74 | "url": "git@github.com:godaddy/asset-system.git"
75 | },
76 | "keywords": [
77 | "SVG",
78 | "asset",
79 | "bundle"
80 | ],
81 | "author": "GoDaddy.com Operating Company, LLC",
82 | "contributors": [
83 | "Arnout Kazemier "
84 | ],
85 | "license": "MIT"
86 | }
87 |
--------------------------------------------------------------------------------
/packages/dimensions/README.md:
--------------------------------------------------------------------------------
1 | # asset-dimensions
2 |
3 | Extract the dimensions of a given SVG image. When no information can be
4 | extracted from the `viewBox` or `width` and `height` properties it will be
5 | rendered in a headless browser and the Bounding Box will be extracted from
6 | the rendered image and returned instead for guaranteed sizing information.
7 |
8 | ## Installation
9 |
10 | ```
11 | npm install --save asset-dimensions
12 | ```
13 |
14 | The module has an **optional** dependency on [`puppeteer`][puppeteer]. This
15 | module is used to resolve the `viewBox` of a given `svg` asset if there is no
16 | `viewBox` or `height/width` combination available on the asset.
17 |
18 | If these properties are missing on some of your assets you will print a warning
19 | and can decide to either manually update them, or install `puppeteer` and it
20 | will automatically extract the correct viewBox from your svg.
21 |
22 | ```
23 | npm install --save puppeteer
24 | ```
25 |
26 | This dependency is not listed as `optionalDependency` in the package.json so
27 | it needs to be manually installed. The reason for this is so we do not download
28 | the headless chrome browser by default when it's not needed for our users.
29 |
30 | ## Usage
31 |
32 | The module exposes as `async function` as default interface. This function
33 | expects an object as first argument with the following properties:
34 |
35 | - `file` The path to the svg that we're extracting information from. This will
36 | be used in the debug output when we fail to extract the dimensions so you know
37 | which file needs manual updating, or why `puppeteer` is required.
38 | - `source` The contents of the file as plain text.
39 | - `tree` DOM (`cheerio`) of the SVG.
40 |
41 | ```js
42 | import dimensions from 'asset-dimensions';
43 | import { readFileSync } from 'fs';
44 | import { load } from 'cheerio';
45 | import { join } from 'path';
46 |
47 | const file = join(__dirname, 'assets', 'file.svg');
48 | const source = readFileSync(file, 'utf-8');
49 |
50 | const result = await dimensions({
51 | tree: load(content, { decodeEntities: false }),
52 | content,
53 | file,
54 | });
55 |
56 | console.log(result);
57 | ```
58 |
59 | The returned `result` is an `object` that will have the following keys:
60 |
61 | - `width` Width of the asset.
62 | - `height` Height of the asset.
63 | - `x` y of the asset.
64 | - `y` x of the asset.
65 | - `viewBox` The viewBox constructed with the `height`, `width`, `x`, `y` props.
66 |
67 | ## License
68 |
69 | [MIT](LICENSE)
70 |
71 | [puppeteer]: https://github.com/GoogleChrome/puppeteer
72 |
--------------------------------------------------------------------------------
/packages/provider/provider/remote.js:
--------------------------------------------------------------------------------
1 | import diagnostics from 'diagnostics';
2 | import Queue from 'queueback';
3 |
4 | //
5 | // Setup our debug util.
6 | //
7 | const debug = diagnostics('asset:provider:remote');
8 |
9 | //
10 | // Cache and Queue setup to prevent duplicate HTTP requests.
11 | //
12 | const queue = new Queue();
13 | const cache = {};
14 |
15 | /**
16 | * Fetch a given resource and parse it's outcome, store it, and send it to
17 | * all other requests that were waiting for the same response.
18 | *
19 | * @param {Object} options Request options.
20 | * @param {AssetParser} parser AssetParser instance
21 | * @param {Function} fn Error first completion callback
22 | * @returns {Undefined|Boolean} Indication of cached, queued or loaded response.
23 | * @public
24 | */
25 | function remote(options, parser, fn) {
26 | const { url, format } = options;
27 | const id = queue.id('GET', url);
28 | const item = cache[id];
29 |
30 | //
31 | // Fastest option first, it's already cached, or we already fetching the
32 | // exact same URI.
33 | //
34 | if (item) {
35 | debug(`the requested url(${url}) was already requested and cached`);
36 | return fn(null, item);
37 | }
38 |
39 | if (queue.add('GET', url, fn)) {
40 | debug(`the requested url(${url}) was already requested, waiting for callback`);
41 | return true;
42 | }
43 |
44 | /**
45 | * Generic processing function for parser and loader responses.
46 | *
47 | * @param {Error} err Optional error.
48 | * @param {Object} data Parsed data.
49 | * @private
50 | */
51 | const loaded = (err, data) => {
52 | const error = err || null;
53 | const svgs = data || {};
54 |
55 | //
56 | // Worth noting, we don't want to cache errors even if it means that
57 | // multiple requests will be send. In unexpected slowness or downtime of
58 | // a CDN we might be able to fetch a resource in the end. Especially
59 | // important for native devices!
60 | //
61 | if (!error) cache[id] = svgs;
62 | queue.run('GET', url, error, svgs);
63 | };
64 |
65 | debug(`first time requesting url(${url})`);
66 | fetch(url)
67 | .then(function status(response) {
68 | if (response.status >= 200 && response.status < 300) {
69 | return Promise.resolve(response);
70 | } else {
71 | return Promise.reject(new Error(response.statusText));
72 | }
73 | })
74 | .then(function parse(response) {
75 | return response.text();
76 | })
77 | .then(function fetched(data) {
78 | parser.parse(format, data, loaded);
79 | })
80 | .catch(loaded);
81 |
82 | return false;
83 | }
84 |
85 | export {
86 | remote as default,
87 | remote,
88 | queue,
89 | cache
90 | }
91 |
--------------------------------------------------------------------------------
/packages/provider/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "asset-provider",
3 | "version": "4.2.1",
4 | "description": "Provides the SVG assets through React Context",
5 | "main": "./lib",
6 | "browser": "./lib",
7 | "module": "./index",
8 | "react-native": "./index",
9 | "scripts": {
10 | "test:web": "mocha --colors --require setup-env --require test/nock.js --require cross-fetch/polyfill test/*.test.js",
11 | "test": "nyc --reporter=text --reporter=lcov npm run test:web",
12 | "prepublish": "npm run build",
13 | "build": "rm -rf ./lib && babel ./index.js -d ./lib && babel ./asset/*.js -d ./lib/asset && babel ./fallback/*.js -d ./lib/fallback && babel ./provider/*.js -d ./lib/provider && babel ./wrapper/*.js -d ./lib/wrapper",
14 | "lint": "eslint-godaddy-react *.js ./provider/*.js ./fallback/*.js ./asset/*.js ./test/*.js"
15 | },
16 | "homepage": "https://github.com/godaddy/asset-system/tree/master/packages/provider",
17 | "repository": {
18 | "type": "git",
19 | "url": "git@github.com:godaddy/asset-system.git"
20 | },
21 | "keywords": [
22 | "svg",
23 | "asset",
24 | "react",
25 | "react-native",
26 | "assets",
27 | "provider"
28 | ],
29 | "babel": {
30 | "plugins": [
31 | "@babel/plugin-proposal-object-rest-spread"
32 | ],
33 | "presets": [
34 | "@babel/preset-env",
35 | "@babel/preset-react"
36 | ]
37 | },
38 | "browserify": {
39 | "transform": [
40 | "babelify"
41 | ]
42 | },
43 | "author": "GoDaddy.com Operating Company, LLC",
44 | "contributors": [
45 | "Arnout Kazemier "
46 | ],
47 | "license": "MIT",
48 | "devDependencies": {
49 | "@babel/cli": "^7.1.2",
50 | "@babel/core": "^7.1.2",
51 | "@babel/plugin-proposal-object-rest-spread": "^7.0.0",
52 | "@babel/preset-env": "^7.1.0",
53 | "@babel/preset-react": "^7.0.0",
54 | "@babel/register": "^7.0.0",
55 | "assume": "^1.5.2",
56 | "cross-fetch": "^3.0.3",
57 | "enzyme": "^3.10.0",
58 | "enzyme-adapter-react-16": "^1.14.0",
59 | "eslint": "^4.14.0",
60 | "eslint-config-godaddy-react": "^2.1.0",
61 | "eslint-plugin-json": "^1.2.0",
62 | "eslint-plugin-mocha": "^4.11.0",
63 | "eslint-plugin-react": "^7.5.1",
64 | "jsdom": "^11.5.1",
65 | "mocha": "^4.1.0",
66 | "nock": "^9.1.6",
67 | "nock-knock": "^1.1.0",
68 | "nyc": "^14.1.1",
69 | "prop-types": "^15.6.0",
70 | "react": "^16.8.6",
71 | "react-dom": "^16.8.6",
72 | "react-test-renderer": "^16.8.6",
73 | "setup-env": "^1.2.1"
74 | },
75 | "dependencies": {
76 | "asset-parser": "^3.0.0",
77 | "diagnostics": "^1.1.0",
78 | "queueback": "^1.2.0",
79 | "rip-out": "^1.0.0",
80 | "svgs": "^3.2.0"
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/examples/web/server.js:
--------------------------------------------------------------------------------
1 | import assets from '../../test/fixtures/index.js';
2 | import config from './webpack.config.js';
3 | import Bundle from 'asset-bundle';
4 | import MemoryFS from 'memory-fs';
5 | import webpack from 'webpack';
6 | import http from 'http';
7 | import path from 'path';
8 | import fs from 'fs';
9 |
10 | //
11 | // Setup fake file system for WebPack for the client code.
12 | //
13 | const fsys = new MemoryFS();
14 |
15 | /**
16 | * Serve the bundle.svgs.
17 | *
18 | * @param {Request} req HTTP request.
19 | * @param {Response} res HTTP response.
20 | * @private
21 | */
22 | function svgs(req, res) {
23 | const bundle = new Bundle(
24 | req.url.slice(1, -5).split('-').map(function map(name) {
25 | return assets[name];
26 | })
27 | );
28 |
29 | bundle.run(function (err, output) {
30 | if (err) throw err;
31 |
32 | res.setHeader('Content-Length', Buffer(output).length);
33 | res.writeHead(200, { 'Content-Type': 'text/plain' });
34 |
35 | res.end(output);
36 | });
37 | }
38 |
39 | /**
40 | * Serve the index.html
41 | *
42 | * @param {Request} req HTTP request.
43 | * @param {Response} res HTTP response.
44 | * @private
45 | */
46 | function html(req, res) {
47 | fs.readFile(path.join(__dirname, 'index.html'), function read(err, file) {
48 | if (err) throw err;
49 |
50 | res.setHeader('Content-Length', file.length);
51 | res.writeHead(200, { 'Content-Type': 'text/html' });
52 |
53 | res.end(file);
54 | });
55 | }
56 |
57 | /**
58 | * Serve the index.js client bundle.
59 | *
60 | * @param {Request} req HTTP request.
61 | * @param {Response} res HTTP response.
62 | * @private
63 | */
64 | function client(req, res) {
65 | const compiler = webpack(config);
66 | compiler.outputFileSystem = fsys;
67 |
68 | compiler.run((err, stats) => {
69 | const file = fsys.readFileSync(path.join(__dirname, 'dist', 'client.js'));
70 |
71 | res.setHeader('Content-Length', file.length);
72 | res.writeHead(200, { 'Content-Type': 'text/javascript' });
73 |
74 | res.end(file);
75 | });
76 | }
77 |
78 | //
79 | // Poor or lazy man's HTTP file server. Don't do this, it's bad.
80 | //
81 | const server = http.createServer((req, res) => {
82 | console.log('received request for url', req.url);
83 | const ext = path.extname(req.url);
84 |
85 | switch(ext) {
86 | case '.svgs':
87 | svgs(req, res);
88 | break;
89 |
90 | case '.js':
91 | client(req, res);
92 | break;
93 |
94 | default:
95 | html(req, res);
96 | }
97 | }).listen(8080);
98 |
99 | //
100 | // Output some information that we're live, ready to go.
101 | //
102 | console.log('Example server is running on http://localhost:8080');
103 |
--------------------------------------------------------------------------------
/examples/reactnative/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/examples/web/README.md:
--------------------------------------------------------------------------------
1 | # Web
2 |
3 | A small demo that illustrates how you could use the asset provider in your
4 | own web application.
5 |
6 | ## Starting the demo
7 |
8 | Make sure you have the dependencies installed for this demo:
9 |
10 | ```
11 | npm install .
12 | ```
13 |
14 | Once all dependencies are installed you can run the server using:
15 |
16 | ```
17 | npm start
18 | ```
19 |
20 | Once the server is started you can navigate your browser to:
21 |
22 | - [`http://localhost:8080`](http://localhost:8080)
23 |
24 | ## How is the demo setup
25 |
26 | There are 3 core files that drive this demo:
27 |
28 | ### index.js
29 |
30 | This is the actual file that implements the `assets-provider`. This file
31 | is converted to ES5 by the `server.js`. The application it self is rather
32 | simple:
33 |
34 | - Imports `asset-provider`, and it's `` and `` components.
35 | - Specify a modification hook for the `pants` property, this will be used to
36 | change the color of homer's pants on the fly.
37 | - Creates a wrapping `` that will load our `godaddy.svg` bundle. This
38 | bundle will only contain a single asset which is the GoDaddy logo.
39 | - Render the asset by adding `` as child node of the
40 | ``
41 | - To make things interesting we've added another `` as child which
42 | will load another bundle that contains the `homer` and `tiger` svgs.
43 | - Add 3 more `` as child elements of the
44 | extra ``. While `godaddy` is not available in this bundle, it
45 | will still render as the `` is aware of it's own context and
46 | will request the asset from the wrapping ``.
47 | - Set the property `pants=red` on of the `homer` assets to change the color of
48 | his pants from light blue to red.
49 | - Renders the Example component in the `example` container.
50 |
51 | ### server.js
52 |
53 | The server is in charge of serving the `html`, `js` and the `svgs` asset bundle.
54 |
55 | It comes with a dedicated API for generating bundles using the `asset-bundle`
56 | library. The URL structure is a following:
57 |
58 | - `http://localhost:8080/[lowercase names of the asset, separated by -].svgs`
59 |
60 | It uses the assets that are available in the `asset` folder that is in the
61 | root of this repository. So if you wish to generate a bundle containing just
62 | the GoDaddy.svg logo you would request:
63 |
64 | - http://localhost:8080/godaddy.svgs
65 |
66 | And if you wanted to include 3 svgs in your bundle you could request:
67 |
68 | - http://localhost:8080/godaddy-homer-tiger.svgs
69 |
70 | This gives you some insight on the bundles, and what they contain.
71 |
72 | ### index.html
73 |
74 | This is the default HTML page that gets loaded when you visit the URL. It's only
75 | use is to load the `index.js` so it starts the React application.
76 |
--------------------------------------------------------------------------------
/examples/reactnative/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Disabling obfuscation is useful if you collect stack traces from production crashes
20 | # (unless you are using a system that supports de-obfuscate the stack traces).
21 | -dontobfuscate
22 |
23 | # React Native
24 |
25 | # Keep our interfaces so they can be used by other ProGuard rules.
26 | # See http://sourceforge.net/p/proguard/bugs/466/
27 | -keep,allowobfuscation @interface com.facebook.proguard.annotations.DoNotStrip
28 | -keep,allowobfuscation @interface com.facebook.proguard.annotations.KeepGettersAndSetters
29 | -keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip
30 |
31 | # Do not strip any method/class that is annotated with @DoNotStrip
32 | -keep @com.facebook.proguard.annotations.DoNotStrip class *
33 | -keep @com.facebook.common.internal.DoNotStrip class *
34 | -keepclassmembers class * {
35 | @com.facebook.proguard.annotations.DoNotStrip *;
36 | @com.facebook.common.internal.DoNotStrip *;
37 | }
38 |
39 | -keepclassmembers @com.facebook.proguard.annotations.KeepGettersAndSetters class * {
40 | void set*(***);
41 | *** get*();
42 | }
43 |
44 | -keep class * extends com.facebook.react.bridge.JavaScriptModule { *; }
45 | -keep class * extends com.facebook.react.bridge.NativeModule { *; }
46 | -keepclassmembers,includedescriptorclasses class * { native ; }
47 | -keepclassmembers class * { @com.facebook.react.uimanager.UIProp ; }
48 | -keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactProp ; }
49 | -keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactPropGroup ; }
50 |
51 | -dontwarn com.facebook.react.**
52 |
53 | # TextLayoutBuilder uses a non-public Android constructor within StaticLayout.
54 | # See libs/proxy/src/main/java/com/facebook/fbui/textlayoutbuilder/proxy for details.
55 | -dontwarn android.text.StaticLayout
56 |
57 | # okhttp
58 |
59 | -keepattributes Signature
60 | -keepattributes *Annotation*
61 | -keep class okhttp3.** { *; }
62 | -keep interface okhttp3.** { *; }
63 | -dontwarn okhttp3.**
64 |
65 | # okio
66 |
67 | -keep class sun.misc.Unsafe { *; }
68 | -dontwarn java.nio.file.*
69 | -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
70 | -dontwarn okio.**
71 |
--------------------------------------------------------------------------------
/packages/parser/transform.js:
--------------------------------------------------------------------------------
1 | import { Through } from 'passing-through';
2 | import diagnostics from 'diagnostics';
3 | import * as svgs from 'svgs';
4 | import React from 'react';
5 |
6 | //
7 | // Setup our debug util.
8 | //
9 | const debug = diagnostics('asset:parser:transform');
10 |
11 | /**
12 | * Figure out the type of what.
13 | *
14 | * @param {Mixed} what Thing we need figure the type of.
15 | * @returns {String} The type of what.
16 | * @private
17 | */
18 | function type(what) {
19 | return Object.prototype.toString.call(what).slice(8, -1).toLowerCase();
20 | }
21 |
22 | /**
23 | * Transforms the SVG data in to actual Svgs SVG elements.
24 | *
25 | * @param {Object} data The SVG data for a single asset.
26 | * @param {String} version Version number of the specification.
27 | * @returns {Array} Array containing the new React elements.
28 | * @public
29 | */
30 | export default function transform(data, version) {
31 | let props = {};
32 | let key = 0;
33 |
34 | /**
35 | * Transform a row in to an actual component.
36 | *
37 | * @param {Array} row Row that needs to be transformed.
38 | * @returns {React.Element|null} Actual component.
39 | * @private
40 | */
41 | function create(row = []) {
42 | const Component = svgs[row[0]];
43 | let attributes = {};
44 | let children;
45 |
46 | if (!Component) return row[0];
47 |
48 | //
49 | // Figure out if the 2nd row is attributes. If not it should be
50 | // considered as children instead.
51 | //
52 | if (row[1]) {
53 | switch (type(row[1])) {
54 | case 'array':
55 | children = row[1].map(create);
56 | break;
57 |
58 | case 'object':
59 | attributes = row[1];
60 | break;
61 |
62 | default:
63 | children = row[1];
64 | }
65 | }
66 |
67 | if (!children && row[2]) {
68 | if (Array.isArray(row[2])) children = row[2].map(create);
69 | else children = row[2];
70 | }
71 |
72 | //
73 | // Note: The attributes that we spread on the Component are **not**
74 | // used as the Through component will clone the child component and
75 | // override the properties. If we do not spread the properties we can
76 | // get prop-type warnings because required props as missing when we
77 | // **create** the component initially, but before it's rendered it does
78 | // receive all props.
79 | //
80 | return (
81 |
82 |
83 | { children }
84 |
85 |
86 | );
87 | }
88 |
89 | //
90 | // Optimization: If we're given an SVG element, we need to extract it and
91 | //
92 | if (data[0] === 'Svg') {
93 | props = data[1];
94 |
95 | if (Array.isArray(props)) {
96 | data = props;
97 | props = {};
98 | } else {
99 | data = data[2];
100 | }
101 |
102 | debug('extracted props for Svg', props);
103 | }
104 |
105 | debug(`transforming payload according to specification(${version})`);
106 | return {
107 | svg: data.map(create),
108 | props
109 | };
110 | }
111 |
--------------------------------------------------------------------------------
/packages/test/src/index.js:
--------------------------------------------------------------------------------
1 | import godaddy from '../godaddy.json';
2 | import path from 'path';
3 |
4 | /**
5 | * Location of the svgs.
6 | *
7 | * @type {Object}
8 | * @public
9 | */
10 | const svgs = {
11 | godaddy: path.join(__dirname, '..', 'godaddy.svg'),
12 | homer: path.join(__dirname, '..', 'homer.svg'),
13 | tiger: path.join(__dirname, '..', 'tiger.svg'),
14 | };
15 |
16 | /**
17 | * Location of the fixtures.
18 | *
19 | * @type {String}
20 | * @public
21 | */
22 | const fixtures = path.join(__dirname, '..');
23 |
24 | /**
25 | * Create fixtures, because we really don't different dependencies for
26 | * React and Svgs as that will make `instanceOf` checks unreliable as they
27 | * might be imported from different locations.
28 | *
29 | * @param {Object} svgs The svgs library.
30 | * @param {React} React React
31 | * @returns {Object} Fixtures.
32 | * @public
33 | */
34 | function create(svgs, React) {
35 | const { Svg, G, Text, Rect, Circle, TSpan } = svgs;
36 |
37 | return {
38 | json: { godaddy },
39 | g: {
40 | structure: [
41 | ['G']
42 | ],
43 | output: (
44 |
45 | )
46 | },
47 | green: {
48 | structure: [
49 | ['G', { fill: 'green' }]
50 | ],
51 | output: (
52 |
53 | )
54 | },
55 | childs: {
56 | structure: [
57 | ['G', [
58 | ['Rect', { dy: 0, dx: 0 }],
59 | ['Circle', { dy: 0, dx: 0, radius: 0 }]
60 | ]
61 | ]],
62 | output: (
63 |
69 | )
70 | },
71 | complex: {
72 | structure: [
73 | ['G',
74 | [
75 | ['Text', { y: 20, dx: '5 5' }, [
76 | ['TSpan', { x: 10 }, 'tspan line 1'],
77 | ['TSpan', { x: 10, dy: 15 }, 'tspan line 2'],
78 | ['TSpan', { x: 10, dy: 15, dx: 10 }, 'tspan line 3']
79 | ]],
80 | ['Text', { x: 10, y: 60, fill: 'red', fontSize: 14 }, [
81 | ['TSpan', { dy: '5 10 20' }, '12345'],
82 | ['TSpan', { fill: 'blue', dy: 15, dx: '0 5 5' }, [
83 | ['TSpan', '6'],
84 | ['TSpan', '7']
85 | ]],
86 | ['TSpan', { dx: '0 10 20', dy: '0 20', fontWeight: 'bold', fontSize: 12 }, '89a']
87 | ]],
88 | ['Text', { y: 140, dx: '0 5 5', dy: '0 -5 -5' }, 'delta on text']
89 | ]
90 | ]
91 | ],
92 | output: (
93 |
111 | )
112 | }
113 | };
114 | }
115 |
116 | export {
117 | create,
118 | fixtures,
119 | svgs as default
120 | }
121 |
--------------------------------------------------------------------------------
/packages/parser/index.js:
--------------------------------------------------------------------------------
1 | import { encode, decode } from './packer';
2 | import diagnostics from 'diagnostics';
3 | import Asset from './asset';
4 |
5 | //
6 | // Setup our debug util.
7 | //
8 | const debug = diagnostics('asset:parser:transform');
9 |
10 | /**
11 | * The version of the specification that we currently follow.
12 | *
13 | * @type {String}
14 | * @public
15 | */
16 | export const version = '0.1.0';
17 |
18 | /**
19 | * Defines the parser function.
20 | *
21 | * @constructor
22 | * @public
23 | */
24 | export default class Parser {
25 | constructor() {
26 | this.version = version; // Version number of the spec we follow.
27 | this.hooks = {}; // Stores our modifer functions.
28 | }
29 |
30 | /**
31 | * Register a new modification hook.
32 | *
33 | * @param {String} name Name property the transformer should trigger on.
34 | * @param {Function} fn Callback that transforms.
35 | * @public
36 | */
37 | modify(name, fn) {
38 | debug(`registered a new tranform hook(${name})`);
39 |
40 | if (!(name in this.hooks)) this.hooks[name] = [];
41 | if (!~this.hooks[name].indexOf(fn)) this.hooks[name].push(fn);
42 | }
43 |
44 | /**
45 | * Returns an array of properties that we have modifiers registered for.
46 | *
47 | * @returns {Array} List of properties.
48 | * @public
49 | */
50 | modifiers() {
51 | return Object.keys(this.hooks);
52 | }
53 |
54 | /**
55 | * Parse the received data.
56 | *
57 | * @param {String} format How is the data supplied.
58 | * @param {String} str Input that needs to be parsed to individual assets.
59 | * @param {Function} fn Error first completion callback.
60 | * @public
61 | */
62 | parse(format, str, fn) {
63 | /**
64 | * Transforms the data structure into a format that can be used by the
65 | * React SVG Asset Provider.
66 | *
67 | * @param {Object} data Object where key is name, and value is an array.
68 | * @param {String} spec Specification version in which the data is encoded.
69 | * @private
70 | */
71 | const transform = (data, spec) => {
72 | const assets = Object.keys(data).reduce((memo, key) => {
73 | if (Array.isArray(data[key])) {
74 | debug(`transforming ${key} in to an Asset`);
75 | memo[key] = new Asset(data[key], this.hooks, spec);
76 | }
77 |
78 | return memo;
79 | }, {});
80 |
81 | fn(null, assets);
82 | };
83 |
84 | /**
85 | * Handle the decoded data and process it into Assets.
86 | *
87 | * @param {Error} err Optional error that happend during decoding.
88 | * @param {Object} payload Data structure containing the svg names, data.
89 | * @returns {Undefined} Nope.
90 | * @private
91 | */
92 | const decoded = (err, payload) => {
93 | if (err) {
94 | debug('failed to decode the supplied string, most likely invalid JSON', err);
95 | return fn(err, {});
96 | }
97 |
98 | const data = payload.data;
99 | const spec = payload.version;
100 |
101 | if (typeof data === 'object' && !Array.isArray(data)) {
102 | debug(`received correct payload, encoded in spec(${spec})`);
103 | return transform(data, spec);
104 | }
105 |
106 | debug('incorrect payload structure', data, spec);
107 | fn(new Error(`Failed to decode payload, spec(${spec})`), {});
108 | };
109 |
110 | decode(str, decoded);
111 | }
112 | }
113 |
114 | //
115 | // Export all the components, parsers and utilities.
116 | //
117 | export {
118 | encode,
119 | decode,
120 | Asset
121 | };
122 |
--------------------------------------------------------------------------------
/packages/provider/test/index.test.js:
--------------------------------------------------------------------------------
1 | import Provider, { Asset, Fallback, Context, parser } from '../index';
2 | import { describe, it } from 'mocha';
3 | import Parser from 'asset-parser';
4 | import { mount } from 'enzyme';
5 | import assume from 'assume';
6 | import React from 'react';
7 |
8 | describe('Asset Provider', function () {
9 | /**
10 | * Assert that the complex fixture is present in the output.
11 | *
12 | * @param {String} html HTML output
13 | * @private
14 | */
15 | function complex(html) {
16 | /*eslint-disable */
17 | assume(html).to.contain('tspan line 1tspan line 2tspan line 3');
18 | assume(html).to.contain('123456789a');
19 | assume(html).to.contain('delta on text');
20 | /* eslint-enable */
21 | }
22 |
23 | /**
24 | * Assert that the godaddy fixture is present in the output.
25 | *
26 | * @param {String} html HTML output
27 | * @private
28 | */
29 | function godaddy(html) {
30 | assume(html).to.contain('viewBox="0 0 127 55.2"');
31 | assume(html).to.contain('viewBox="0 0 127 55.2"');
32 | assume(html).to.contain('');
33 | }
34 |
35 | it('exposes all core components', function () {
36 | assume(parser).is.instanceOf(Parser);
37 |
38 | assume(Asset).exists();
39 | assume(Provider).exists();
40 | assume(Fallback).is.a('function');
41 |
42 | assume(Context).is.a('object');
43 | assume(Context.withContext).is.a('function');
44 | assume(Context.Provider).exists();
45 | assume(Context.Consumer).exists();
46 | });
47 |
48 | it('renders assets', function (next) {
49 | const wrapper = mount(
50 |
51 |
52 |
53 | );
54 |
55 | setTimeout(function () {
56 | const html = wrapper.html();
57 | complex(html);
58 |
59 | next();
60 | }, 100);
61 | });
62 |
63 | it('correctly resolves the `uri` function', function (next) {
64 | function uri(resolved) {
65 | setTimeout(function () {
66 | resolved(null, 'http://example.com/complex/bundle.svgs');
67 | }, 10);
68 | }
69 |
70 | const wrapper = mount(
71 |
72 |
73 |
74 | );
75 |
76 | setTimeout(function () {
77 | const html = wrapper.html();
78 | complex(html);
79 |
80 | next();
81 | }, 100);
82 | })
83 |
84 | it('renders through nested context', function (next) {
85 | const wrapper = mount(
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | );
95 |
96 | setTimeout(function () {
97 | const html = wrapper.html();
98 |
99 | complex(html);
100 | godaddy(html);
101 |
102 | next();
103 | }, 100);
104 | });
105 | });
106 |
--------------------------------------------------------------------------------
/examples/reactnative/ios/reactnative/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/packages/bundle/walker/index.js:
--------------------------------------------------------------------------------
1 | import diagnostics from 'diagnostics';
2 | import camelCase from 'camel-case';
3 |
4 | //
5 | // Setup our debug util.
6 | //
7 | const debug = diagnostics('asset:bundle:walker');
8 |
9 | /**
10 | * Weird component names from svgs/react-native-svg that can't really be
11 | * transformed automatically using the componentName function.
12 | *
13 | * Naming things is hard..
14 | *
15 | * @type {Object}
16 | * @private
17 | */
18 | const names = {
19 | tspan: 'TSpan' // Not judging here but LOL WAT ARE YOU DOING.
20 | };
21 |
22 | /**
23 | * Transforms a given tagName to a `svgs` and `react-native-svg` compatible
24 | * component name.
25 | *
26 | * @param {String} tagName The node's tagName.
27 | * @returns {String} The transformed string.
28 | * @private
29 | */
30 | export function componentName(tagName) {
31 | if (names[tagName]) return names[tagName];
32 |
33 | const first = tagName.charAt(0).toUpperCase();
34 | return first + tagName.slice(1);
35 | }
36 |
37 | /**
38 | * List of properties that need to be renamed in order to be compatible in
39 | * React.
40 | *
41 | * @type {Object}
42 | * @private
43 | */
44 | const rename = {
45 | 'class': 'className'
46 | };
47 |
48 | /**
49 | * Transform attribute names to their correct JavaScript equivs.
50 | *
51 | * @param {Object} attr Attributes that needs to be transformed
52 | * @returns {Object} Transformed attributes.
53 | * @private
54 | */
55 | export function attributes(attr) {
56 | return Object.keys(attr).reduce(function reduce(memo, key) {
57 | const name = rename[key] ? rename[key] : camelCase(key);
58 | let value = attr[key];
59 |
60 | if (!isNaN(+value)) value = +value;
61 |
62 | memo[name] = value;
63 | return memo;
64 | }, {});
65 | }
66 |
67 | /**
68 | * Walk the DOM tree and generate the required structures.
69 | *
70 | * @param {Object} svg Information of a single SVG asset.
71 | * @param {Object} modify Additional modification hooks.
72 | * @param {Function} fn Error first completion callback.
73 | * @private
74 | */
75 | export default function walker(svg, modify, fn) {
76 | const { tree } = svg;
77 |
78 | /**
79 | * Iterate over all the children and transform them into the required
80 | * structure.
81 | *
82 | * @param {Object} root DOM root node.
83 | * @returns {Array} Parsed structure.
84 | * @private
85 | */
86 | function iterate(root) {
87 | const node = [];
88 | const element = tree(root);
89 | const attr = element.attr();
90 | const children = element.children();
91 |
92 | //
93 | // Transform the name of the tag to be a component.
94 | //
95 | let name = componentName(root.tagName);
96 | let attrs = {};
97 |
98 | //
99 | // Transform attributes to actual DOM properties.
100 | //
101 | if (attr && Object.keys(attr).length) {
102 | attrs = attributes(attr);
103 | }
104 |
105 | //
106 | // Edge case for the svg element, we want to NUKE all the Attributes
107 | // and introduce our new viewBox property if it exists.
108 | //
109 | if (name === 'Svg' && svg.viewBox) {
110 | debug(`introducing viewBox(${svg.viewBox}) on svg(${svg.name})`);
111 | attrs = { viewBox: svg.viewBox };
112 | }
113 |
114 | //
115 | // Process the modification hooks. So they can alter attributes or even
116 | // complete components.
117 | //
118 | Object.keys(modify).forEach((key) => {
119 | name = modify[key](attrs, element, name) || name;
120 | });
121 |
122 | //
123 | // All transformation have been completed, we can start assembling the
124 | // required structure:
125 | //
126 | // [ComponentName, { optional attributes }, [ optional children ]]
127 | //
128 | node.push(name);
129 | if (Object.keys(attrs).length) node.push(attrs)
130 | if (children.length) node.push(children.get().map(iterate));
131 |
132 | return node;
133 | }
134 |
135 | svg.struc = tree('svg').get().map(iterate)[0];
136 | fn(null, svg);
137 | }
138 |
--------------------------------------------------------------------------------
/SPECIFICATION.md:
--------------------------------------------------------------------------------
1 | # Specification
2 |
3 | **Current spec version: 0.1.0**
4 |
5 | This documentation contains instructions how to transform SVG asset(s) in to
6 | readable format for this module. There are various of transformation steps
7 | that need to happen before an SVG can be consumed by this library. These exist
8 | for the following reason:
9 |
10 | - Reduce the data format so less bytes have to be send over the wire.
11 | - The client side code should be as small and dumb as possible.
12 | - Pre-transform SVG in easy format so less CPU cycles have to spend in the browser.
13 |
14 | ## Table of Contents
15 |
16 | - [Specification](#specification)
17 | - [Structure](#structure)
18 | - [Bundle](#bundle)
19 | - [Serialization](#serialization)
20 |
21 | ### Structure
22 |
23 | A SVG file needs to be transformed in a correct bundle file, in order for that
24 | you need to transform the SVG elements in to JavaScript compatible syntax. This
25 | should be done before uploading the asset so the computation for this happens
26 | during the build process on your own machine, instead of on the client devices
27 | that load these assets. If we imagine having a SVG with the following contents:
28 |
29 | ```html
30 |
38 | ```
39 |
40 | We want to end up with the following "optimized" structure.
41 |
42 | ```json
43 | [
44 | [
45 | "Svg",
46 | { "viewBox": "0 0 300 600" },
47 | [
48 | [
49 | "G",
50 | [
51 | ["Path", { "fill": "#000", "d":"13.508 n0180-149 ..."}],
52 | ["Path", { "fill": "#FFF", "strokeOpacity":"0.1", "d":"13.508 n0180-149 ..."}]
53 | ]
54 | ]
55 | ]
56 | ]
57 | ]
58 | ```
59 |
60 | You might notice that the following transformations has occurred:
61 |
62 | - The `svg` element has all it's properties removed except for `viewBox`. If no
63 | `viewBox` property is present, it should be calculated and added.
64 | - Tag names are transformed to be uppercase first, so they match `svgs`
65 | component names.
66 | - Attributes are transformed to be camelCase and then combined in to an objects
67 | which should be compatible with `react-native-svg` attributes.
68 | - Colors are optimized to small HEX codes if possible.
69 | - Child components are wrapped in an array [].
70 |
71 | Each element is transformed in to an array where the first item of the Array
72 | is the name of the tagName of the element which is transformed to be uppercase
73 | first to match the components from the `svgs` library. The second item of the
74 | array will either be:
75 |
76 | - An object with attributes that should be applied to the tag.
77 | - An array, that contains child elements for the given tag.
78 | - A string, which will be content for the element in the case of `Text` tags.
79 | - Nothing, no child elements or attributes are needed.
80 |
81 | See the `test/fixtures/index.js` file for more examples of the bundle structure
82 | and their resulting output.
83 |
84 | ### Bundle
85 |
86 | Creating a bundle of SVG assets is a straight forward process. The
87 | [structure](#structure) for assets is already known. The only thing it needs is
88 | an identifier for each asset. This should be a unique id as it will be used as
89 | `key` in the overall JSON structure and structure will be the value. A good
90 | practise is to use the filename of the asset key. So if you have a file with the
91 | name `example.svg` and `another.svg` you should end up with following bundle
92 | structure.
93 |
94 | ```json
95 | {
96 | "example": [
97 | ["Text", "Generated structure"]
98 | ],
99 | "another": [
100 | ["G", ["Text", { "stroke": 1 }, "Another"]]
101 | ]
102 | }
103 | ```
104 |
105 | ### Serialization
106 |
107 | The current implementation assumes that JSON is used serialization format. Run
108 | the resulting bundle through your JSON encoder and upload it to the cloud.
109 |
--------------------------------------------------------------------------------
/packages/webpack/README.md:
--------------------------------------------------------------------------------
1 | # asset-webpack
2 |
3 | A WebPack plugin that combines all your SVG assets into a `asset-provider`
4 | compatible bundle.
5 |
6 | ## Table of Contents
7 |
8 | - [Install](#install)
9 | - [Usage](#usage)
10 | - [Specify the `file-loader` for .svg extensions](#specify-the-file-loader-for-svg-extensions)
11 | - [Configure plugin](#configure-plugin)
12 | - [Producing a bundle](#producing-a-bundle)
13 | - [License](#license)
14 |
15 | ## Install
16 |
17 | ```
18 | npm install --save asset-webpack
19 | ```
20 |
21 | ## Usage
22 |
23 | Import the loader in to your `webpack.config.js`:
24 |
25 | ```js
26 | import SVGBundler from 'asset-webpack';
27 |
28 | const bundle = new SVGBundler('bundle.svgs', { /* opts */ });
29 | ```
30 |
31 | The first argument is the name the bundle. It should be single file name, and
32 | it will be placed in the output directory that you specified in the WebPack
33 | configuration. The filename supports the following (template) replacements:
34 |
35 | - `[hash]` Will be replaced with a MD5 hash of the resulting bundle.
36 |
37 | The second argument is an **options** object that allows you to further
38 | configure the plugin, and the bundle system. The following options are
39 | supported:
40 |
41 | - `namespace` Should we use the folder structure of the assets as namespaces,
42 | defaults to `false`.
43 | - `root` Location of the root directory that used to generate the namespaces.
44 | - `bundler` Options that will be passed in to the `asset-bundle` constructor.
45 | - `modify` An object where the key is the name of the modifer and the value the
46 | function that does the modification. This will be passed in to `bundle#modify`.
47 | - `plugins` Plugins that need to be assigned to the `asset-bundle` instance.
48 | The plugins option should be an `Array` of arrays which is spread on the
49 | `bundle#plugin` method.
50 |
51 | ```js
52 | ...
53 | namespace: true,
54 | bundler: {
55 | multipass: true,
56 | },
57 | modify: {
58 | color: function () { .. }
59 | },
60 | plugins: [
61 | [Constructor, { options }, args, etc],
62 | [Constructor, { options }, args, etc]
63 | ]
64 | ...
65 | ```
66 |
67 | ### Configure the loader
68 |
69 | First we need to ensure that `.svg` files are handled by the bundle. Update the
70 | module rules/loaders to contain the following:
71 |
72 | ```js
73 | module: {
74 | rules: [
75 | { test: /\.svg$/, use: bundle.loader() }
76 | ]
77 | }
78 | ```
79 |
80 | The `bundle.loader()` will return a correctly pre-configured loader so we can
81 | replace the contents of the file, and introduce it into the svgs bundle.
82 |
83 | ### Insert the bundle instance as `plugin`
84 |
85 | Last but not least, pass the created `bundle` instance into the `plugin` array
86 | of your `webpack.config.js`:
87 |
88 | ```js
89 | {
90 | ...,
91 | plugins: [ bundle ]
92 | }
93 | ```
94 |
95 | And done, you've completed the following steps:
96 |
97 | - Created a new Bundle instance
98 | - Used it's loader method to configure the correct loader
99 | - Passed the instance into the `plugin` array
100 |
101 | ### Producing a bundle
102 |
103 | Create the `entry` file that requires the SVG assets:
104 |
105 | ```js
106 | require('./file.svg');
107 | require('./another.svg');
108 | require('./more.svg');
109 | ```
110 |
111 | In addition to producing the bundled SVG, we've also rewritten the contents of
112 | the required file. The file will now return the `name` of your SVG how it's
113 | stored inside the bundle.
114 |
115 | ```js
116 | import Provider, { Asset } from 'asset-provider';
117 | import React, { Component } from 'react';
118 | import upload from './upload.svg';
119 | import file from './file.svg';
120 |
121 | export default class Example extends Component {
122 | render() {
123 | return (
124 |
125 |
126 |
Upload
127 |
128 |
131 |
132 |
133 |
134 |
135 | );
136 | }
137 | }
138 | ```
139 |
140 | ## License
141 |
142 | [MIT](LICENSE)
143 |
--------------------------------------------------------------------------------
/packages/parser/test/index.test.js:
--------------------------------------------------------------------------------
1 | import AssetParser, { encode, decode, Asset, version } from '../index.js';
2 | import { describe, it, before } from 'mocha';
3 | import { create } from 'asset-test';
4 | import * as svgs from 'svgs';
5 | import assume from 'assume';
6 | import React from 'react';
7 |
8 | const { complex } = create(svgs, React);
9 |
10 | describe('asset-parser', function () {
11 | it('exports all utilties', function () {
12 | assume(version).is.a('string');
13 | assume(encode).is.a('function');
14 | assume(decode).is.a('function');
15 | assume(Asset).is.a('function');
16 | assume(AssetParser).is.a('function');
17 | });
18 |
19 | describe('AssetParser', function () {
20 | let asset;
21 |
22 | function setup() {
23 | asset = new AssetParser();
24 | }
25 |
26 | describe('#modify', function () {
27 | it('registers a new hook', function () {
28 | setup();
29 |
30 | assume(asset.hooks).to.have.length(0);
31 |
32 | const what = () => {};
33 | asset.modify('what', what);
34 |
35 | assume(asset.hooks).to.have.length(1);
36 | assume(asset.hooks.what).is.a('array');
37 | assume(asset.hooks.what).to.have.length(1);
38 | assume(asset.hooks.what[0]).equals(what);
39 | });
40 |
41 | it('can register multiple modifiers for a given property', function () {
42 | setup();
43 |
44 | const one = () => {};
45 | const two = () => {};
46 |
47 | asset.modify('color', one);
48 | asset.modify('color', two);
49 |
50 | assume(asset.hooks).to.have.length(1);
51 | assume(asset.hooks.color).is.a('array');
52 | assume(asset.hooks.color).to.have.length(2);
53 | assume(asset.hooks.color[0]).equals(one);
54 | assume(asset.hooks.color[1]).equals(two);
55 | });
56 |
57 | it('ignores duplicates for a given prop', function () {
58 | setup();
59 |
60 | const one = () => {};
61 | const two = () => {};
62 |
63 | asset.modify('color', one);
64 | asset.modify('color', two);
65 | asset.modify('color', two);
66 |
67 | assume(asset.hooks).to.have.length(1);
68 | assume(asset.hooks.color).is.a('array');
69 | assume(asset.hooks.color).to.have.length(2);
70 | assume(asset.hooks.color[0]).equals(one);
71 | assume(asset.hooks.color[1]).equals(two);
72 | });
73 | });
74 |
75 | describe('#modifiers', function () {
76 | it('returns an array with the names of the modifiers', function () {
77 | setup();
78 |
79 | asset.modify('foo', () => {});
80 | asset.modify('bar', () => {});
81 | asset.modify('bar', () => {});
82 |
83 | assume(asset.modifiers()).is.a('array');
84 | assume(asset.modifiers()).deep.equals(['foo', 'bar']);
85 | });
86 | });
87 |
88 | describe('#parse', function () {
89 | let str;
90 |
91 | before((next) => {
92 | setup();
93 |
94 | encode(version, { complex: complex.structure }, (err, data) => {
95 | if (err) return next(err);
96 |
97 | str = data;
98 | next();
99 | });
100 | });
101 |
102 | it('decodes the playload and returns a list of Asset instances', function (next) {
103 | asset.parse('bundle', str, (err, svgs) => {
104 | if (err) return next(err);
105 |
106 | assume(err).is.a('null');
107 | assume(svgs).is.a('object');
108 |
109 | assume(svgs.complex).is.instanceOf(Asset);
110 | next();
111 | });
112 | });
113 |
114 | it('passes pass errors in to callback', function (next) {
115 | asset.parse('bundle', `${version}§l{}`, (err, svgs) => {
116 | assume(err).is.a('error');
117 | assume(err.message).to.contain('Unexpected token');
118 |
119 | assume(svgs).is.a('object');
120 | assume(svgs).to.have.length(0);
121 |
122 | next();
123 | });
124 | });
125 |
126 | it('returns error on invalid data structure', function (next) {
127 | asset.parse('bundle', `${version}§[{"foo":"bar"}]`, (err, svgs) => {
128 | assume(err).is.a('error');
129 | assume(err.message).equals(`Failed to decode payload, spec(${version})`);
130 |
131 | assume(svgs).is.a('object');
132 | assume(svgs).to.have.length(0);
133 |
134 | next();
135 | });
136 | });
137 | });
138 | });
139 | });
140 |
--------------------------------------------------------------------------------
/packages/provider/test/remote.test.js:
--------------------------------------------------------------------------------
1 | import { describe, it, beforeEach } from 'mocha';
2 | import { remote, cache, queue } from '../provider/remote';
3 | import { decode } from 'asset-parser';
4 | import { complex } from './fixtures';
5 | import assume from 'assume';
6 |
7 | describe('remote', function () {
8 | const url = 'http://example.com/complex/bundle.svg';
9 | const format = 'bundle';
10 | const method = 'GET';
11 |
12 | function parse(form, data, fn) {
13 | if (typeof data === 'string') {
14 | return decode(data, function (err, payload) {
15 | if (err) return fn(err);
16 |
17 | return fn(null, payload.data);
18 |
19 | });
20 | }
21 |
22 | fn(null, {});
23 | }
24 |
25 | function nukeCache() {
26 | for (let key in cache) delete cache[key];
27 | }
28 |
29 | beforeEach(nukeCache);
30 | afterEach(nukeCache);
31 |
32 | it('returns items from cache', function (next) {
33 | const item = queue.id(method, url);
34 | const mock = { hello: 'world' };
35 |
36 | cache[item] = mock;
37 |
38 | remote({ format, url }, { parse }, (err, data) => {
39 | assume(err).is.a('null');
40 | assume(data).equals(mock);
41 |
42 | next();
43 | });
44 | });
45 |
46 | it('returns `undefined` when a response is cached', function () {
47 | const item = queue.id(method, url);
48 | const mock = { hello: 'world' };
49 |
50 | cache[item] = mock;
51 |
52 | assume(remote({ format, url }, { parse }, () => {})).is.a('undefined');
53 | });
54 |
55 | it('returns `true` when a request for the same URL is progress', function () {
56 | assume(remote({ format, url }, { parse }, () => {})).is.false();
57 | assume(remote({ format, url }, { parse }, () => {})).is.true();
58 | assume(remote({ format, url }, { parse }, () => {})).is.true();
59 | assume(remote({ format, url }, { parse }, () => {})).is.true();
60 | });
61 |
62 | [404, 500].forEach(function each(status) {
63 | it(`does not store items in cache on ${status} error`, function (next) {
64 | assume(cache).is.length(0);
65 |
66 | /*eslint-disable */
67 | remote({
68 | url: `http://example.com/${status}`,
69 | format
70 | }, { parse }, (err, data) => {
71 | assume(err.message).is.a('string');
72 | assume(data).is.a('object');
73 |
74 | assume(cache).is.length(0);
75 |
76 | next();
77 | });
78 | /* eslint-enable */
79 | });
80 | });
81 |
82 | it(`does not store items in cache on error`, function (next) {
83 | assume(cache).is.length(0);
84 | remote({
85 | url: `http://example-non-existing-nobody-buy-this-domain-plx.lol/`,
86 | format
87 | }, { parse }, (err, data) => {
88 | assume(err.message).is.a('string');
89 | assume(data).is.a('object');
90 | assume(cache['GET:http://example-non-existing-nobody-buy-this-domain-plx.lol/']).is.a('undefined');
91 |
92 | next();
93 | });
94 | });
95 |
96 | it('calls the parser when data is received correctly', function (next) {
97 | remote({ format, url }, { parse: (form, data, fn) => {
98 | assume(form).equals(format);
99 | assume(data).is.a('string');
100 | assume(fn).is.a('function');
101 |
102 | decode(data, function (err, payload) {
103 | if (err) return fn(err);
104 |
105 | assume(payload.version).is.a('string');
106 | assume(payload.data).is.a('object');
107 | assume(payload.data).deep.equals(complex);
108 |
109 | fn(null, { what: 'lol' });
110 | });
111 | } }, (err, data) => {
112 | assume(data).deep.equals({ what: 'lol' });
113 |
114 | next(err);
115 | });
116 | });
117 |
118 | it('caches the correctly parsed data', function (next) {
119 | const item = queue.id(method, url);
120 | const mock = { hello: 'world' };
121 |
122 | assume(cache).is.length(0);
123 |
124 | remote({ format, url }, { parse: (form, data, fn) => {
125 | fn(null, mock);
126 | } }, (err, data) => {
127 | assume(data).equals(mock);
128 | assume(cache).is.length(1);
129 | assume(cache[item]).equals(mock);
130 |
131 | next(err);
132 | });
133 | });
134 |
135 | it('broadcasts the parsed and cached data to all queued fns', function (next) {
136 | next = assume.wait(3, next);
137 |
138 | ['green', 'green', 'green'].forEach(function (name) {
139 | remote({
140 | url: `http://example.com/${name}/bundle.svgs`,
141 | format
142 | }, { parse }, (err, svgs) => {
143 | assume(svgs).is.a('object');
144 | next(err);
145 | });
146 | });
147 | });
148 | });
149 |
--------------------------------------------------------------------------------
/packages/dimensions/index.js:
--------------------------------------------------------------------------------
1 | import render from './render';
2 |
3 | /**
4 | * Really stupid simple warning output.
5 | *
6 | * @param {Array} lines The messages that needs to be spammed.
7 | * @private
8 | */
9 | function warning(lines) {
10 | lines.unshift(''); // Extra whitespace at the start.
11 | lines.push(''); // Extra whitespace at the end.
12 |
13 | lines.forEach(function each(line) {
14 | console.error('asset-dimensions:warning', line);
15 | });
16 | }
17 |
18 | /**
19 | * Compile a viewBox from the given.
20 | *
21 | * @param {Object} details The width/height for the viewBox.
22 | * @returns {Object} Dimensions, and viewbox of the svg asset.
23 | * @private
24 | */
25 | function viewBox({ width, height, x = 0, y = 0 }) {
26 | return {
27 | viewBox: `${x} ${y} ${width} ${height}`,
28 | height: +height,
29 | width: +width,
30 | x: +x,
31 | y: +y
32 | };
33 | }
34 |
35 | /**
36 | * Ensure that we have dimension information from the read SVG so we can generate
37 | * a valid viewBox for the SVG.
38 | *
39 | * @param {Object} svg Our internal SVG object.
40 | * @returns {Object} Bounding box, and viewBox information of the asset.
41 | * @public
42 | */
43 | export default async function dimensions({ file, source, tree }) {
44 | const root = tree('svg');
45 |
46 | //
47 | // If we already have a valid viewBox attribute, we can just continue and
48 | // mind our own business.. This should satisfy 99% of the cases when designers
49 | // provide us with SVG exports from applications such as Illustrator, Sketch.
50 | //
51 | if (root.attr('viewBox')) {
52 | const parsed = root.attr('viewBox').split(/[ ,]+/g);
53 |
54 | return viewBox({
55 | x: parseFloat(parsed[0], 10),
56 | y: parseFloat(parsed[1], 10),
57 | width: parseFloat(parsed[2], 10),
58 | height: parseFloat(parsed[3], 10)
59 | });
60 | }
61 |
62 | //
63 | // While we have `svg.info` that can contain height and width, these values
64 | // are extracted directly from the svg width/height attributes are should
65 | // not be considered valid. For example, our homer.svg in fixtures is
66 | // actually: width: 457.2821960449219, height: 490.2278747558594 but the
67 | // info object (that originates from svgo) said 500x500.
68 | //
69 | // In all these cases, the best thing we can do is extract the bounding box
70 | // from the browser.
71 | //
72 | // In order to get the best render result we need to strip the whole