ts_assets 0.0.0 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
[](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
|