ts_assets 0.0.0 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +74 -0
- data/.gitignore +12 -40
- data/CHANGELOG.md +6 -0
- data/Gemfile +4 -0
- data/LICENSE +1 -24
- data/README.md +134 -1
- data/Rakefile +13 -0
- data/__tests__/assets/images/svg/ruby-icon.svg +1 -0
- data/__tests__/assets/images/webhook/slack_icon@1x.png +0 -0
- data/__tests__/assets/images/webhook/slack_icon@2x.png +0 -0
- data/__tests__/build/.gitkeep +0 -0
- data/__tests__/ts_assets_spec.tsx +39 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/ts_assets/application_generator.rb +58 -0
- data/lib/ts_assets/generators/const_generator.rb +29 -0
- data/lib/ts_assets/generators/react_generator.rb +88 -0
- data/lib/ts_assets/models/asset_meta_info.rb +85 -0
- data/lib/ts_assets/models/content.rb +19 -0
- data/lib/ts_assets/version.rb +3 -0
- data/lib/ts_assets.rb +27 -0
- data/package-lock.json +3026 -0
- data/package.json +53 -0
- data/ts_assets.gemspec +32 -0
- data/tsconfig.json +16 -0
- data/tslint.json +12 -0
- metadata +75 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5aa69bcfd907932ff761f68dbc57fe6ab753a5ac
|
4
|
+
data.tar.gz: bfc02d04c4a26c84ef4c6fce8e3d5431a157255c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2725a42259d3752423beda929cb291ac0fcfa9cc27bd34e9ec2b7b19e94886d370988f08adbc24c5365a62df6dd6c7dff468466b09ed241245b14e0410e64a44
|
7
|
+
data.tar.gz: d019fc93f82c95b4b860c78474d0b65fd2153fbb103249fa4ff8c3a90fd49ed308c4dfd58c4d1645fdf747132ad8aa52b98c32a7b54a9957756b481bfcc16b7d
|
@@ -0,0 +1,74 @@
|
|
1
|
+
version: 2
|
2
|
+
jobs:
|
3
|
+
build:
|
4
|
+
docker:
|
5
|
+
- image: ruby:latest
|
6
|
+
environment:
|
7
|
+
BUNDLE_DIR: vendor/bundle
|
8
|
+
|
9
|
+
working_directory: src
|
10
|
+
|
11
|
+
steps:
|
12
|
+
- checkout
|
13
|
+
|
14
|
+
- restore_cache:
|
15
|
+
name: "[Node.js] Restore Cache"
|
16
|
+
keys:
|
17
|
+
- nodejs-6.10.2
|
18
|
+
- nodejs-
|
19
|
+
|
20
|
+
- run:
|
21
|
+
name: "[Node.js] Install"
|
22
|
+
command: |
|
23
|
+
if [[ ! -e /usr/local/bin/node || $(node --version) != "v${NODEJS_VERSION}" ]]; then
|
24
|
+
# https://nodejs.org/ja/download/package-manager/#debian-and-ubuntu-based-linux-distributions-debian-ubuntu-linux
|
25
|
+
curl -sL https://deb.nodesource.com/setup_6.x | bash -
|
26
|
+
apt-get update -qq
|
27
|
+
apt-get install -y nodejs
|
28
|
+
ln -s /usr/local/bin/node /usr/local/bin/nodejs
|
29
|
+
fi
|
30
|
+
|
31
|
+
- save_cache:
|
32
|
+
name: "[Node.js] Save Cache"
|
33
|
+
key: nodejs-6.10.2
|
34
|
+
paths:
|
35
|
+
- /usr/local/bin/node
|
36
|
+
|
37
|
+
- run:
|
38
|
+
name: Check Runtime Information
|
39
|
+
command: |
|
40
|
+
cat << EOF
|
41
|
+
bundler : `bundle -v`
|
42
|
+
Node.js : `node -v`
|
43
|
+
EOF
|
44
|
+
|
45
|
+
- restore_cache:
|
46
|
+
name: "[Ruby] Restore Cache"
|
47
|
+
keys:
|
48
|
+
- gems-{{ checksum "ts_assets.gemspec" }}
|
49
|
+
- gems-
|
50
|
+
|
51
|
+
- run: bundle check --path=$BUNDLE_DIR || bundle install --path=$BUNDLE_DIR --jobs=4 --retry=3 --without=production
|
52
|
+
|
53
|
+
- save_cache:
|
54
|
+
name: "[Ruby] Save Cache"
|
55
|
+
key: gems-{{ checksum "ts_assets.gemspec" }}
|
56
|
+
paths:
|
57
|
+
- vendor/bundle/
|
58
|
+
|
59
|
+
- restore_cache:
|
60
|
+
name: "[JavaScript] Restore Cache"
|
61
|
+
keys:
|
62
|
+
- js-packages-{{ checksum "package-lock.json" }}
|
63
|
+
- js-packages-
|
64
|
+
|
65
|
+
- run: npm install
|
66
|
+
|
67
|
+
- save_cache:
|
68
|
+
name: "[JavaScript] Save Cache"
|
69
|
+
key: js-packages-{{ checksum "package-lock.json" }}
|
70
|
+
paths:
|
71
|
+
- node_modules/
|
72
|
+
|
73
|
+
- run: npm test
|
74
|
+
- run: npm run lint
|
data/.gitignore
CHANGED
@@ -1,44 +1,16 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
.
|
4
|
-
/
|
5
|
-
/tmp
|
6
|
-
/db/*.sqlite3
|
7
|
-
/db/*.sqlite3-journal
|
8
|
-
/public/system
|
1
|
+
/.bundle/
|
2
|
+
/.yardoc
|
3
|
+
/Gemfile.lock
|
4
|
+
/_yardoc/
|
9
5
|
/coverage/
|
10
|
-
/
|
11
|
-
|
12
|
-
|
13
|
-
|
6
|
+
/doc/
|
7
|
+
/pkg/
|
8
|
+
/spec/reports/
|
9
|
+
/tmp/
|
14
10
|
|
15
|
-
#
|
16
|
-
|
11
|
+
# rspec failure tracking
|
12
|
+
.rspec_status
|
17
13
|
|
18
|
-
|
19
|
-
# config/secrets.yml
|
14
|
+
*/build/assets.tsx
|
20
15
|
|
21
|
-
|
22
|
-
# TODO Comment out this rule if environment variables can be committed
|
23
|
-
.env
|
24
|
-
|
25
|
-
## Environment normalization:
|
26
|
-
/.bundle
|
27
|
-
/vendor/bundle
|
28
|
-
|
29
|
-
# these should all be checked in to normalize the environment:
|
30
|
-
# Gemfile.lock, .ruby-version, .ruby-gemset
|
31
|
-
|
32
|
-
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
33
|
-
.rvmrc
|
34
|
-
|
35
|
-
# if using bower-rails ignore default bower_components path bower.json files
|
36
|
-
/vendor/assets/bower_components
|
37
|
-
*.bowerrc
|
38
|
-
bower.json
|
39
|
-
|
40
|
-
# Ignore pow environment settings
|
41
|
-
.powenv
|
42
|
-
|
43
|
-
# Ignore Byebug command history file.
|
44
|
-
.byebug_history
|
16
|
+
node_modules/
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
|
1
2
|
Apache License
|
2
3
|
Version 2.0, January 2004
|
3
4
|
http://www.apache.org/licenses/
|
@@ -175,27 +176,3 @@
|
|
175
176
|
|
176
177
|
END OF TERMS AND CONDITIONS
|
177
178
|
|
178
|
-
APPENDIX: How to apply the Apache License to your work.
|
179
|
-
|
180
|
-
To apply the Apache License to your work, attach the following
|
181
|
-
boilerplate notice, with the fields enclosed by brackets "{}"
|
182
|
-
replaced with your own identifying information. (Don't include
|
183
|
-
the brackets!) The text should be enclosed in the appropriate
|
184
|
-
comment syntax for the file format. We also recommend that a
|
185
|
-
file or class name and description of purpose be included on the
|
186
|
-
same "printed page" as the copyright notice for easier
|
187
|
-
identification within third-party archives.
|
188
|
-
|
189
|
-
Copyright {yyyy} {name of copyright owner}
|
190
|
-
|
191
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
192
|
-
you may not use this file except in compliance with the License.
|
193
|
-
You may obtain a copy of the License at
|
194
|
-
|
195
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
196
|
-
|
197
|
-
Unless required by applicable law or agreed to in writing, software
|
198
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
199
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
200
|
-
See the License for the specific language governing permissions and
|
201
|
-
limitations under the License.
|
data/README.md
CHANGED
@@ -1 +1,134 @@
|
|
1
|
-
#
|
1
|
+
# TsAssets
|
2
|
+
|
3
|
+
[![CircleCI](https://circleci.com/gh/bitjourney/ts_assets-rails.svg?style=svg)](https://circleci.com/gh/bitjourney/ts_assets-rails)
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'ts_assets'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install ts_assets
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
### Rake
|
24
|
+
|
25
|
+
Here is an example to generate an asset file via rake.
|
26
|
+
|
27
|
+
`lib/tasks/ts_assets.rake`:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
# rake ts_assets:generate
|
31
|
+
namespace :ts_assets do
|
32
|
+
task generate: :environment do
|
33
|
+
TS_ASSETS_FILENAME = "client/generated/assets.tsx"
|
34
|
+
File.write TS_ASSETS_FILENAME, TsAssets.generate(include: "app/assets/images")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
```
|
38
|
+
|
39
|
+
For example, if you have `app/assets/images/svg/ruby-icon.svg` in your asset path, the generated source would be like this:
|
40
|
+
|
41
|
+
`client/generated/assets.tsx`:
|
42
|
+
|
43
|
+
```typescript
|
44
|
+
/** svg/ruby-icon.svg */
|
45
|
+
const PATH_SVG_RUBY_ICON = "/assets/svg/ruby-icon-486fbe77b2fa535451a48ccd48587f8a1359fb373b7843e14fb5a84cb2697160.svg";
|
46
|
+
|
47
|
+
/** svg/ruby-icon */
|
48
|
+
export function ImageSvgRubyIcon(props: React.HTMLProps<HTMLImageElement>) {
|
49
|
+
return <img alt="ruby-icon"
|
50
|
+
width={128}
|
51
|
+
height={128}
|
52
|
+
src={PATH_SVG_RUBY_ICON}
|
53
|
+
srcSet={`${PATH_SVG_RUBY_ICON} 1x`}
|
54
|
+
{...props}
|
55
|
+
/>;
|
56
|
+
}
|
57
|
+
```
|
58
|
+
|
59
|
+
Then you can import `client/generated/assets.tsx` and use the imported components.
|
60
|
+
|
61
|
+
`client/components/MyComponent.tsx`:
|
62
|
+
|
63
|
+
```typescript
|
64
|
+
import * as React from 'react';
|
65
|
+
import * as Assets from '../../generated/assets';
|
66
|
+
|
67
|
+
class MyComponent extend React.Component<any, any> {
|
68
|
+
render() {
|
69
|
+
return (
|
70
|
+
<Assets.ImageSvgRubyIcon
|
71
|
+
alt='ruby'
|
72
|
+
className='svg icon'
|
73
|
+
/>
|
74
|
+
);
|
75
|
+
}
|
76
|
+
}
|
77
|
+
```
|
78
|
+
|
79
|
+
### Options
|
80
|
+
|
81
|
+
All you need to do is to call `TsAssets.generate` class method with supported options.
|
82
|
+
|
83
|
+
Currently supported options are:
|
84
|
+
|
85
|
+
- `include`: the path to the assets. e.g.) "app/assets/images"
|
86
|
+
|
87
|
+
### React Components
|
88
|
+
|
89
|
+
#### `width`, `height`
|
90
|
+
|
91
|
+
The `width` and `height` attribute is automatically set via https://github.com/sdsykes/fastimage gem.
|
92
|
+
|
93
|
+
#### `srcSet`
|
94
|
+
|
95
|
+
If you have files named like `*@1x.png` or `*@2x.png`, the `srcSet` attribute will be automatically set.
|
96
|
+
|
97
|
+
For example, if there are those images in your `include` path:
|
98
|
+
|
99
|
+
```
|
100
|
+
app/assets/images
|
101
|
+
/webhook
|
102
|
+
slack_icon@1x.png
|
103
|
+
slack_icon@2x.png
|
104
|
+
```
|
105
|
+
|
106
|
+
Then the generated components looks like:
|
107
|
+
|
108
|
+
```typescript
|
109
|
+
/** webhook/slack_icon@1x.png */
|
110
|
+
const PATH_WEBHOOK_SLACK_ICON_1X = "/assets/webhook/slack_icon@1x-dd316f78fb005e28fb960482d5972fc58ab33da6836c684c1b61e7cb1b60d1e0.png";
|
111
|
+
|
112
|
+
/** webhook/slack_icon@2x.png */
|
113
|
+
const PATH_WEBHOOK_SLACK_ICON_2X = "/assets/webhook/slack_icon@2x-4f5daeae796f89bb5590bae233226cacd092c1c4e911a12061bfe12c597cc885.png";
|
114
|
+
|
115
|
+
/** webhook/slack_icon */
|
116
|
+
export function ImageWebhookSlackIcon(props: React.HTMLProps<HTMLImageElement>) {
|
117
|
+
return <img alt="slack_icon"
|
118
|
+
width={20}
|
119
|
+
src={PATH_WEBHOOK_SLACK_ICON_1X}
|
120
|
+
srcSet={`${PATH_WEBHOOK_SLACK_ICON_1X} 1x,${PATH_WEBHOOK_SLACK_ICON_2X} 2x`}
|
121
|
+
{...props}
|
122
|
+
/>;
|
123
|
+
}
|
124
|
+
```
|
125
|
+
|
126
|
+
## Development
|
127
|
+
|
128
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
129
|
+
|
130
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
131
|
+
|
132
|
+
## Contributing
|
133
|
+
|
134
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/bitjourney/ts_assets-rails.
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
require "ts_assets"
|
4
|
+
|
5
|
+
RSpec::Core::RakeTask.new(:spec)
|
6
|
+
|
7
|
+
task :generate do
|
8
|
+
TS_ASSETS_FILENAME = "__tests__/build/assets.tsx"
|
9
|
+
source = TsAssets.generate(include: "__tests__/assets/images")
|
10
|
+
File.write TS_ASSETS_FILENAME, source
|
11
|
+
end
|
12
|
+
|
13
|
+
task :default => :spec
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"><path fill-rule="evenodd" clip-rule="evenodd" fill="#D91404" d="M35.971 111.33c27.466 3.75 54.444 7.433 81.958 11.188-9.374-15.606-18.507-30.813-27.713-46.144l-54.245 34.956zM125.681 24.947c-2.421 3.636-4.847 7.269-7.265 10.907-8.304 12.493-16.607 24.986-24.903 37.485-.462.696-1.061 1.248-.41 2.321 8.016 13.237 15.969 26.513 23.942 39.777 1.258 2.095 2.53 4.182 4.157 6.192 1.612-32.193 3.223-64.387 4.834-96.58l-.355-.102zM16.252 66.22c.375.355 1.311.562 1.747.347 7.689-3.779 15.427-7.474 22.948-11.564 2.453-1.333 4.339-3.723 6.452-5.661 6.997-6.417 13.983-12.847 20.966-19.278.427-.395.933-.777 1.188-1.275 2.508-4.902 4.973-9.829 7.525-14.898-3.043-1.144-5.928-2.263-8.849-3.281-.396-.138-1.02.136-1.449.375-6.761 3.777-13.649 7.353-20.195 11.472-3.275 2.061-5.943 5.098-8.843 7.743-4.674 4.266-9.342 8.542-13.948 12.882-1.222 1.152-2.336 2.468-3.288 3.854-3.15 4.587-6.206 9.24-9.402 14.025 1.786 1.847 3.41 3.613 5.148 5.259zM44.354 59.949c-3.825 16.159-7.627 32.227-11.556 48.823 18.423-11.871 36.421-23.468 54.3-34.987-14.228-4.605-28.41-9.196-42.744-13.836zM120.985 25.103c-15.566 2.601-30.76 5.139-46.15 7.71 5.242 12.751 10.379 25.246 15.662 38.096 10.221-15.359 20.24-30.41 30.488-45.806zM44.996 56.644c14.017 4.55 27.755 9.01 41.892 13.6-5.25-12.79-10.32-25.133-15.495-37.737-8.815 8.059-17.498 15.999-26.397 24.137zM16.831 75.643c-4.971 11.883-9.773 23.362-14.662 35.048 9.396-.278 18.504-.547 27.925-.825-4.423-11.412-8.759-22.6-13.263-34.223zM30.424 101.739l.346-.076c3.353-13.941 6.754-27.786 10.177-42.272-7.636 3.969-14.92 7.754-22.403 11.644 3.819 9.926 7.891 20.397 11.88 30.704zM115.351 22.842c-4.459-1.181-8.918-2.366-13.379-3.539-6.412-1.686-12.829-3.351-19.237-5.052-.801-.213-1.38-.352-1.851.613-2.265 4.64-4.6 9.245-6.901 13.868-.071.143-.056.328-.111.687 13.886-2.104 27.679-4.195 41.47-6.285l.009-.292zM89.482 12.288l36.343 10.054c-2.084-5.939-4.017-11.446-6.005-17.11l-30.285 6.715-.053.341zM33.505 114.007c-4.501-.519-9.122-.042-13.687.037-3.75.063-7.5.206-11.25.323-.386.012-.771.09-1.156.506 31.003 2.866 62.005 5.732 93.007 8.6l.063-.414c-9.938-1.357-19.877-2.714-29.815-4.07-12.384-1.691-24.747-3.551-37.162-4.982zM2.782 99.994c3.995-9.27 7.973-18.546 11.984-27.809.401-.929.37-1.56-.415-2.308-1.678-1.597-3.237-3.318-5.071-5.226-2.479 12.24-4.897 24.177-7.317 36.113l.271.127c.185-.297.411-.578.548-.897zM81.522 9.841c6.737-1.738 13.572-3.097 20.367-4.613.44-.099.87-.244 1.303-.368l-.067-.332c-9.571 1.287-19.141 2.575-29.194 3.928 2.741 1.197 4.853 2.091 7.591 1.385z"/></svg>
|
Binary file
|
Binary file
|
File without changes
|
@@ -0,0 +1,39 @@
|
|
1
|
+
import { shallow } from "enzyme";
|
2
|
+
import * as React from "react";
|
3
|
+
import { renderToString } from "react-dom/server";
|
4
|
+
|
5
|
+
import * as Assets from "./build/assets";
|
6
|
+
|
7
|
+
describe("TsAssets Components", () => {
|
8
|
+
describe("with Server-Side Rendering", () => {
|
9
|
+
test("renders something", () => {
|
10
|
+
expect(renderToString(Assets.ImageSvgRubyIcon())).toBeTruthy();
|
11
|
+
expect(renderToString(Assets.ImageWebhookSlackIcon())).toBeTruthy();
|
12
|
+
});
|
13
|
+
});
|
14
|
+
|
15
|
+
describe("with Client-Side Rendering", () => {
|
16
|
+
test("renders something", () => {
|
17
|
+
const rubyIcon = shallow(
|
18
|
+
<Assets.ImageSvgRubyIcon
|
19
|
+
className="svg"
|
20
|
+
/>,
|
21
|
+
);
|
22
|
+
const slackIcon = shallow(
|
23
|
+
<Assets.ImageWebhookSlackIcon
|
24
|
+
className="webhook classname"
|
25
|
+
/>,
|
26
|
+
);
|
27
|
+
|
28
|
+
expect(rubyIcon.props().alt).toEqual("ruby-icon");
|
29
|
+
expect(rubyIcon.props().className).toEqual("svg");
|
30
|
+
expect(rubyIcon.props().src).toBeTruthy();
|
31
|
+
expect(rubyIcon.props().srcSet).toBeTruthy();
|
32
|
+
|
33
|
+
expect(slackIcon.props().alt).toEqual("slack_icon");
|
34
|
+
expect(slackIcon.props().className).toEqual("webhook classname");
|
35
|
+
expect(slackIcon.props().src).toBeTruthy();
|
36
|
+
expect(slackIcon.props().srcSet).toBeTruthy();
|
37
|
+
});
|
38
|
+
});
|
39
|
+
});
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "ts_assets"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'sprockets'
|
2
|
+
|
3
|
+
module TsAssets
|
4
|
+
class ApplicationGenerator
|
5
|
+
# @return [Hash] mapping
|
6
|
+
attr_reader :mapping
|
7
|
+
|
8
|
+
# @param [String] include
|
9
|
+
def initialize(include:)
|
10
|
+
@mapping = build_mapping(include)
|
11
|
+
|
12
|
+
environment.append_path(include)
|
13
|
+
end
|
14
|
+
|
15
|
+
# @return [Sprockets::Environment]
|
16
|
+
def environment
|
17
|
+
@environment ||= Sprockets::Environment.new
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [String]
|
21
|
+
def generate
|
22
|
+
[ # header
|
23
|
+
react_content.header,
|
24
|
+
|
25
|
+
# body
|
26
|
+
const_content.body,
|
27
|
+
react_content.body,
|
28
|
+
|
29
|
+
].join("\n")
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [TsAssets::Models::Content]
|
33
|
+
def const_content
|
34
|
+
@const_content ||= TsAssets::Generators::ConstGenerator.new(mapping).generate
|
35
|
+
end
|
36
|
+
|
37
|
+
# @return [TsAssets::Models::Content]
|
38
|
+
def react_content
|
39
|
+
@react_content ||= TsAssets::Generators::ReactGenerator.new(mapping).generate
|
40
|
+
end
|
41
|
+
|
42
|
+
# @param [String] include_path
|
43
|
+
# @return [Hash]
|
44
|
+
def build_mapping(include_path)
|
45
|
+
mapping = {}
|
46
|
+
|
47
|
+
Dir.glob("#{include_path}/**/*.*").each do |full_path|
|
48
|
+
mapping[full_path] = TsAssets::Models::AssetMetaInfo.new(
|
49
|
+
full_path: full_path,
|
50
|
+
include_path: include_path,
|
51
|
+
environment: environment,
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
55
|
+
mapping
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module TsAssets
|
2
|
+
module Generators
|
3
|
+
class ConstGenerator < TsAssets::ApplicationGenerator
|
4
|
+
|
5
|
+
# @return [Hash]
|
6
|
+
attr_reader :mapping
|
7
|
+
|
8
|
+
# @param [Hash] mapping
|
9
|
+
def initialize(mapping)
|
10
|
+
@mapping = mapping
|
11
|
+
end
|
12
|
+
|
13
|
+
# @return [TsAssets::Models::Content]
|
14
|
+
def generate
|
15
|
+
ts_paths = mapping.map { |full_path, asset_meta_info| constify(asset_meta_info) }
|
16
|
+
TsAssets::Models::Content.new(header: nil, body: ts_paths.join("\n"))
|
17
|
+
end
|
18
|
+
|
19
|
+
# @param [TsAssets::Models::AssetMetaInfo] meta_info
|
20
|
+
# @return [String]
|
21
|
+
def constify(meta_info)
|
22
|
+
<<~TS
|
23
|
+
/** #{meta_info.asset_path} */
|
24
|
+
const #{meta_info.normalised_path} = "/assets/#{meta_info.digest_path}";
|
25
|
+
TS
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'active_support/core_ext/string/inflections'
|
2
|
+
|
3
|
+
module TsAssets
|
4
|
+
module Generators
|
5
|
+
class ReactGenerator < TsAssets::ApplicationGenerator
|
6
|
+
|
7
|
+
# @return [Hash]
|
8
|
+
attr_reader :mapping
|
9
|
+
|
10
|
+
# @param [Hash] mapping
|
11
|
+
def initialize(mapping)
|
12
|
+
@mapping = merge_mapping_with_same_descriptors(mapping)
|
13
|
+
end
|
14
|
+
|
15
|
+
# @return [TsAssets::Models::Content]
|
16
|
+
def generate
|
17
|
+
components = mapping.map { |path, asset_meta_infos| reactify(path, asset_meta_infos) }
|
18
|
+
TsAssets::Models::Content.new(header: header, body: components.join("\n"))
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
# @param [Hash<String, TsAssets::Models::AssetMetaInfo>] mapping
|
24
|
+
# @return [Hash<String, [TsAssets::Models::AssetMetaInfo]>]
|
25
|
+
def merge_mapping_with_same_descriptors(mapping)
|
26
|
+
new_mapping = {}
|
27
|
+
|
28
|
+
mapping.map do |full_path, asset_meta_info|
|
29
|
+
path = asset_meta_info.asset_path_without_descriptor
|
30
|
+
|
31
|
+
if new_mapping[path].nil?
|
32
|
+
new_mapping[path] = [asset_meta_info]
|
33
|
+
else
|
34
|
+
new_mapping[path] << asset_meta_info
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
new_mapping
|
39
|
+
end
|
40
|
+
|
41
|
+
# @return [String]
|
42
|
+
def header
|
43
|
+
"import * as React from \"react\";\n"
|
44
|
+
end
|
45
|
+
|
46
|
+
# @param [String] path
|
47
|
+
# @param [Array<AssetMetaInfo>] asset_meta_infos
|
48
|
+
# @return [String]
|
49
|
+
def reactify(path, asset_meta_infos)
|
50
|
+
component_name = build_component_name(path)
|
51
|
+
|
52
|
+
alt = File.basename(path)
|
53
|
+
width = asset_meta_infos.first.width
|
54
|
+
height = asset_meta_infos.first.height
|
55
|
+
src = asset_meta_infos.first.normalised_path
|
56
|
+
src_set = build_src_set(asset_meta_infos)
|
57
|
+
|
58
|
+
<<~TS
|
59
|
+
/** #{path} */
|
60
|
+
export function #{component_name}(props?: React.HTMLProps<HTMLImageElement>) {
|
61
|
+
return <img alt="#{alt}"
|
62
|
+
width={#{width}}
|
63
|
+
height={#{height}}
|
64
|
+
src={#{src}}
|
65
|
+
srcSet={#{src_set}}
|
66
|
+
{...props}
|
67
|
+
/>;
|
68
|
+
}
|
69
|
+
TS
|
70
|
+
end
|
71
|
+
|
72
|
+
# @param [String] asset_path
|
73
|
+
# @return [String]
|
74
|
+
def build_component_name(asset_path)
|
75
|
+
"Image#{asset_path.gsub(/[^a-zA-Z0-9_]/, '_').camelize}"
|
76
|
+
end
|
77
|
+
|
78
|
+
# @param [Array<AssetMetaInfo>] asset_meta_infos
|
79
|
+
# @return [String]
|
80
|
+
def build_src_set(asset_meta_infos)
|
81
|
+
src_set = asset_meta_infos.map do |meta_info|
|
82
|
+
"${#{meta_info.normalised_path}} #{meta_info.descriptor}"
|
83
|
+
end.join(',')
|
84
|
+
"`#{src_set}`"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'fastimage'
|
2
|
+
|
3
|
+
module TsAssets
|
4
|
+
module Models
|
5
|
+
class AssetMetaInfo
|
6
|
+
# [String]
|
7
|
+
DESCRIPTOR_REGEX = /(.+?)@(\dx)./
|
8
|
+
|
9
|
+
# full_path is a path from the app root.
|
10
|
+
# ex) "app/assets/images/path/to/the/image.png"
|
11
|
+
# @return [String]
|
12
|
+
attr_reader :full_path
|
13
|
+
|
14
|
+
# include_path is the app asset path root.
|
15
|
+
# ex) "app/assets/images"
|
16
|
+
# @return [String]
|
17
|
+
attr_reader :include_path
|
18
|
+
|
19
|
+
# @return [Sprockets::Environment]
|
20
|
+
attr_reader :environment
|
21
|
+
|
22
|
+
# @return [String]
|
23
|
+
attr_reader :asset_path_without_descriptor
|
24
|
+
|
25
|
+
# @return [String]
|
26
|
+
attr_reader :descriptor
|
27
|
+
|
28
|
+
# @return [Numeric]
|
29
|
+
attr_reader :width
|
30
|
+
|
31
|
+
# @return [Numeric]
|
32
|
+
attr_reader :height
|
33
|
+
|
34
|
+
# @param [String] full_path
|
35
|
+
# @param [String] include_path
|
36
|
+
# @param [Sprockets::Environment] environment
|
37
|
+
def initialize(full_path:,
|
38
|
+
include_path:,
|
39
|
+
environment:)
|
40
|
+
|
41
|
+
@full_path = full_path
|
42
|
+
@include_path = include_path
|
43
|
+
@environment = environment
|
44
|
+
|
45
|
+
@width, @height = FastImage.size(full_path)
|
46
|
+
|
47
|
+
if has_descriptor?
|
48
|
+
# ex)
|
49
|
+
# dir/blog_feed.png -> #<MatchData "dir/blog_feed." 1:"dir/blog_feed">
|
50
|
+
# dir/blog_feed@2x.png -> #<MatchData "dir/blog_feed@2x." 1:"dir/blog_feed" 2:"2x">
|
51
|
+
match_data = asset_path.match(DESCRIPTOR_REGEX)
|
52
|
+
@asset_path_without_descriptor, @descriptor = match_data.captures
|
53
|
+
else
|
54
|
+
@asset_path_without_descriptor = asset_path_without_ext
|
55
|
+
@descriptor = '1x' # 1x as a default descriptor
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# @return [Boolean]
|
60
|
+
def has_descriptor?
|
61
|
+
!asset_path.match(DESCRIPTOR_REGEX).nil?
|
62
|
+
end
|
63
|
+
|
64
|
+
# @return [String]
|
65
|
+
def asset_path
|
66
|
+
full_path.gsub(%r{^#{include_path}/}, '')
|
67
|
+
end
|
68
|
+
|
69
|
+
# @return [String]
|
70
|
+
def asset_path_without_ext
|
71
|
+
asset_path.chomp(File.extname(asset_path))
|
72
|
+
end
|
73
|
+
|
74
|
+
# @return [String]
|
75
|
+
def digest_path
|
76
|
+
environment.find_asset(asset_path).digest_path
|
77
|
+
end
|
78
|
+
|
79
|
+
# @return [String]
|
80
|
+
def normalised_path
|
81
|
+
"PATH_#{asset_path_without_ext.gsub(/[^a-zA-Z0-9_]/, '_').upcase}"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|