システムエラーが発生しました
6 |下記のエラーが発生しました
8 |<%= @error_msg %>9 |
├── .dockerignore
├── .gitignore
├── .rspec
├── .travis.yml
├── Dockerfile
├── Gemfile
├── Gemfile.lock
├── LICENSE
├── README.md
├── app.rb
├── config.rb
├── docker-compose.yml
├── heroku.yml
├── lib
├── cv_maker.rb
├── txt2yaml.rb
└── util.rb
├── make_cv.rb
├── makefile
├── photo.png
├── public
├── .gitkeep
├── script.js
└── style.css
├── sample
├── README_origin.md
└── screen_pc.png
├── share
└── .gitkeep
├── spec
├── app_spec.rb
├── cv_maker_spec.rb
├── spec_helper.rb
└── txt2yaml_spec.rb
├── templates
├── academic.txt
├── academic.yaml
├── data.yaml
└── style.txt
├── views
├── error.erb
├── index.erb
├── layout.erb
└── partial
│ ├── cdn.erb
│ ├── footer.erb
│ ├── header.erb
│ └── seo.erb
└── yaml2txt.rb
/.dockerignore:
--------------------------------------------------------------------------------
1 | # git
2 | .git
3 | .gitignore
4 | LICENSE
5 | VERSION
6 | README.md
7 | Changelog.md
8 | # Makefile
9 | Dockerfile
10 | docker-compose.yml
11 | docs
12 |
13 | # production
14 | fonts
15 | *.pdf
16 | sample
17 | share
18 |
19 | # Created by https://www.gitignore.io/api/ruby
20 | # Edit at https://www.gitignore.io/?templates=ruby
21 |
22 | ### Ruby ###
23 | *.gem
24 | *.rbc
25 | /.config
26 | /coverage/
27 | /InstalledFiles
28 | /pkg/
29 | /spec/reports/
30 | /spec/examples.txt
31 | /test/tmp/
32 | /test/version_tmp/
33 | /tmp/
34 |
35 | # Used by dotenv library to load environment variables.
36 | # .env
37 |
38 | # Ignore Byebug command history file.
39 | .byebug_history
40 |
41 | ## Specific to RubyMotion:
42 | .dat*
43 | .repl_history
44 | build/
45 | *.bridgesupport
46 | build-iPhoneOS/
47 | build-iPhoneSimulator/
48 |
49 | ## Specific to RubyMotion (use of CocoaPods):
50 | #
51 | # We recommend against adding the Pods directory to your .gitignore. However
52 | # you should judge for yourself, the pros and cons are mentioned at:
53 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
54 | # vendor/Pods/
55 |
56 | ## Documentation cache and generated files:
57 | /.yardoc/
58 | /_yardoc/
59 | /doc/
60 | /rdoc/
61 |
62 | ## Environment normalization:
63 | /.bundle/
64 | /vendor/bundle
65 | /lib/bundler/man/
66 |
67 | # for a library or gem, you might want to ignore these files since the code is
68 | # intended to run in multiple environments; otherwise, check them in:
69 | # Gemfile.lock
70 | .ruby-version
71 | # .ruby-gemset
72 |
73 | # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
74 | .rvmrc
75 |
76 | # End of https://www.gitignore.io/api/ruby
77 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | fonts
2 | *.pdf
3 | share/*
4 | !share/.gitkeep
5 |
6 | # Created by https://www.gitignore.io/api/ruby
7 | # Edit at https://www.gitignore.io/?templates=ruby
8 |
9 | ### Ruby ###
10 | *.gem
11 | *.rbc
12 | /.config
13 | /coverage/
14 | /InstalledFiles
15 | /pkg/
16 | /spec/reports/
17 | /spec/examples.txt
18 | /test/tmp/
19 | /test/version_tmp/
20 | /tmp/
21 |
22 | # Used by dotenv library to load environment variables.
23 | # .env
24 |
25 | # Ignore Byebug command history file.
26 | .byebug_history
27 |
28 | ## Specific to RubyMotion:
29 | .dat*
30 | .repl_history
31 | build/
32 | *.bridgesupport
33 | build-iPhoneOS/
34 | build-iPhoneSimulator/
35 |
36 | ## Specific to RubyMotion (use of CocoaPods):
37 | #
38 | # We recommend against adding the Pods directory to your .gitignore. However
39 | # you should judge for yourself, the pros and cons are mentioned at:
40 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
41 | # vendor/Pods/
42 |
43 | ## Documentation cache and generated files:
44 | /.yardoc/
45 | /_yardoc/
46 | /doc/
47 | /rdoc/
48 |
49 | ## Environment normalization:
50 | /.bundle/
51 | /vendor/bundle
52 | /lib/bundler/man/
53 |
54 | # for a library or gem, you might want to ignore these files since the code is
55 | # intended to run in multiple environments; otherwise, check them in:
56 | # Gemfile.lock
57 | .ruby-version
58 | # .ruby-gemset
59 |
60 | # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
61 | .rvmrc
62 |
63 | # End of https://www.gitignore.io/api/ruby
64 |
--------------------------------------------------------------------------------
/.rspec:
--------------------------------------------------------------------------------
1 | --color
2 | --require spec_helper
3 | --format documentation
4 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: ruby
2 | rvm:
3 | - 2.7.2
4 | before_install:
5 | - gem install bundler -v '> 2'
6 | before_script:
7 | - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
8 | - chmod +x ./cc-test-reporter
9 | - ./cc-test-reporter before-build
10 | - curl https://moji.or.jp/wp-content/ipafont/IPAexfont/IPAexfont00401.zip > fonts.zip
11 | - unzip -oj fonts.zip -d fonts/ && rm -rf fonts.zip
12 | script:
13 | - bundle exec rspec
14 | after_script:
15 | - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
16 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ruby:2-alpine
2 |
3 | # Setup
4 | RUN set -x && apk update && apk upgrade && apk add --no-cache \
5 | gnupg gcc g++ make unzip curl openssh-client git bash imagemagick
6 | RUN gem install bundler
7 |
8 | WORKDIR /usr/src/
9 |
10 | # RUN git clone https://github.com/jerrywdlee/yaml_2_resume.git app
11 | ADD ./ /usr/src/app/
12 |
13 | WORKDIR /usr/src/app
14 |
15 | RUN bundle install
16 | RUN curl https://moji.or.jp/wp-content/ipafont/IPAexfont/IPAexfont00401.zip > fonts.zip && \
17 | unzip -oj fonts.zip -d fonts/ && rm -rf fonts.zip
18 |
19 | EXPOSE 4567
20 | CMD ["bundle", "exec", "ruby", "app.rb", "-o", "0.0.0.0", "-p", "4567"]
21 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | source "https://rubygems.org"
4 |
5 | git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
6 |
7 | gem 'prawn'
8 | gem 'rake'
9 | gem 'wareki'
10 | gem 'sinatra'
11 | gem 'sinatra-contrib', group: :development
12 | gem 'mini_magick'
13 |
14 | group :development, :test do
15 | gem 'rspec'
16 | gem 'simplecov'
17 | gem 'rack-test'
18 | end
19 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | backports (3.15.0)
5 | diff-lcs (1.3)
6 | docile (1.3.1)
7 | json (2.2.0)
8 | mini_magick (4.9.3)
9 | multi_json (1.13.1)
10 | mustermann (1.0.3)
11 | pdf-core (0.7.0)
12 | prawn (2.2.2)
13 | pdf-core (~> 0.7.0)
14 | ttfunk (~> 1.5)
15 | rack (2.0.7)
16 | rack-protection (2.0.5)
17 | rack
18 | rack-test (1.1.0)
19 | rack (>= 1.0, < 3)
20 | rake (12.3.2)
21 | rspec (3.8.0)
22 | rspec-core (~> 3.8.0)
23 | rspec-expectations (~> 3.8.0)
24 | rspec-mocks (~> 3.8.0)
25 | rspec-core (3.8.0)
26 | rspec-support (~> 3.8.0)
27 | rspec-expectations (3.8.3)
28 | diff-lcs (>= 1.2.0, < 2.0)
29 | rspec-support (~> 3.8.0)
30 | rspec-mocks (3.8.0)
31 | diff-lcs (>= 1.2.0, < 2.0)
32 | rspec-support (~> 3.8.0)
33 | rspec-support (3.8.0)
34 | simplecov (0.16.1)
35 | docile (~> 1.1)
36 | json (>= 1.8, < 3)
37 | simplecov-html (~> 0.10.0)
38 | simplecov-html (0.10.2)
39 | sinatra (2.0.5)
40 | mustermann (~> 1.0)
41 | rack (~> 2.0)
42 | rack-protection (= 2.0.5)
43 | tilt (~> 2.0)
44 | sinatra-contrib (2.0.5)
45 | backports (>= 2.8.2)
46 | multi_json
47 | mustermann (~> 1.0)
48 | rack-protection (= 2.0.5)
49 | sinatra (= 2.0.5)
50 | tilt (>= 1.3, < 3)
51 | tilt (2.0.9)
52 | ttfunk (1.5.1)
53 | wareki (1.0.0)
54 | ya_kansuji (> 0.0.9, < 2.0.0)
55 | ya_kansuji (0.2.0)
56 |
57 | PLATFORMS
58 | ruby
59 |
60 | DEPENDENCIES
61 | mini_magick
62 | prawn
63 | rack-test
64 | rake
65 | rspec
66 | simplecov
67 | sinatra
68 | sinatra-contrib
69 | wareki
70 |
71 | BUNDLED WITH
72 | 2.0.1
73 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 J. C. Augusta
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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | YAMLによる履歴書作成
2 | ===
3 |
4 | [](LICENSE)
5 | [](Ruby)
6 | [](https://travis-ci.com/jerrywdlee/yaml_2_resume)
7 | [](https://codeclimate.com/github/jerrywdlee/yaml_2_resume/test_coverage)
8 | [](https://codeclimate.com/github/jerrywdlee/yaml_2_resume/maintainability)
9 |
10 | [kaityo256氏が開発した `yaml_cv`](https://github.com/kaityo256/yaml_cv)のマイクロサービス版です。
11 | YAML形式で書かれたデータファイルと、
12 | YAMLもしくはテキストファイル形式で書かれた[スタイル](https://qiita.com/kaityo256/items/e3884d0109223c324baf)
13 | から履歴書PDFファイルを作成します。
14 | [Qiita記事はこちら](https://qiita.com/jerrywdlee/items/d0c36549136211937473)
15 |
16 | [](https://hub.docker.com/r/jerrywdlee/yaml_2_resume)
17 |
18 | # Application
19 | **DEMO: https://yaml-2-resume.herokuapp.com/**
20 |
21 | 
22 |
23 | # インストール&使用
24 | ## ローカルインストール
25 | ### 必要なライブラリ等
26 | * Ruby >= v2.3
27 | * bundler >= 2.0
28 | * [ImageMagick](https://imagemagick.org/index.php)
29 | * [IAPexフォント](https://moji.or.jp/ipafont/)
30 |
31 | ### MacOS
32 | #### 依存パケージのインストール
33 | ```sh
34 | $ brew install imagemagick
35 | $ gem install bundler
36 | $ bundle install
37 | ```
38 |
39 | #### フォントのダウンロード、バージョンは適宜に替えていいです
40 | ```sh
41 | $ curl https://moji.or.jp/wp-content/ipafont/IPAexfont/IPAexfont00401.zip > fonts.zip
42 | $ unzip -oj fonts.zip -d fonts/ && rm -rf fonts.zip
43 | ```
44 |
45 | 上記コマンドを使わなくても、[ここ](https://moji.or.jp/ipafont/)よりフォントを
46 | ダウンロードして、下記の配置になるよう解凍すればいい。
47 |
48 | ```
49 | ├── fonts
50 | │ ├── ipaexg.ttf
51 | │ └── ipaexm.ttf
52 | └── make_cv.rb
53 | ```
54 |
55 | #### アプリの起動
56 | ##### webアプリとして
57 |
58 | ```sh
59 | $ bundle exec ruby app.rb
60 | $ open http://localhost:4567
61 | ```
62 |
63 | ##### また、ローカルでは[kaityo256/yaml_cv](https://github.com/kaityo256/yaml_cv)が提供したコマンドも実行できる。
64 |
65 | ```sh
66 | $ ruby make_cv.rb -h
67 | Usage: make_cv [options]
68 | -i, --input [datafile]
69 | -s, --style [stylefile]
70 | -o, --output [output]
71 | -v, --version
72 | ```
73 |
74 | ```sh
75 | ruby make_cv.rb -i templates/data.yaml -s templates/style.txt -o output.pdf
76 | ```
77 |
78 | ##### テストの実行
79 | ```sh
80 | $ bundle exec rspec
81 | ```
82 |
83 | ## Dockerを使う
84 | ### 純Docker(Webアプリとして)
85 | #### ローカルでビルドする
86 |
87 | ```sh
88 | $ docker build -t my_yaml_2_resume .
89 | $ docker run --rm -p 14567:4567 my_yaml_2_resume
90 | $ open http://localhost:14567
91 | ```
92 |
93 | #### [Docker Hub](https://cloud.docker.com/repository/docker/jerrywdlee/yaml_2_resume)を利用する
94 |
95 | ```sh
96 | $ docker pull jerrywdlee/yaml_2_resume:latest
97 | $ docker run --rm -p 14567:4567 jerrywdlee/yaml_2_resume
98 | $ open http://localhost:14567
99 | ```
100 |
101 | ## Docker Composeを使う
102 | ### Webアプリ
103 | ```sh
104 | $ docker-compose build
105 | $ docker-compose up
106 | $ open http://localhost:14567
107 | ```
108 |
109 | ### CMDモード
110 | `share/`の配下にご自分のデータを置いて、`docker-compose.yml`の`command`フィールドを修正して使う。もちろん、`templates/`配下のサンプルデータも使える。
111 |
112 | ```diff
113 | version: '3.5'
114 | services:
115 | yaml_2_resume:
116 | container_name: yaml_2_resume
117 | build: .
118 | ports:
119 | - 14567:4567
120 | working_dir: /usr/src/app
121 | volumes:
122 | - ./share:/usr/src/app/share
123 | # web app mode
124 | - command: ruby app.rb -o 0.0.0.0
125 | # cmd mode
126 | + command: ruby make_cv.rb -i share/YOUR_DATA.yaml -s share/YOUR_STYLE.txt -o share/output.pdf
127 | ```
128 |
129 | ```sh
130 | $ docker-compose build
131 | $ docker-compose up
132 | $ open ./share/output.pdf
133 | ```
134 |
135 | ## HerokuでDeploy
136 |
137 | ```sh
138 | $ heroku create YOUR-APP-NAME
139 | $ heroku stack:set container
140 | $ git push heroku master
141 | ```
142 |
143 | # [kaityo256/yaml_cv](https://github.com/kaityo256/yaml_cv)との変更点
144 |
145 | - `data.yaml`の`photo`フィールドは、URLも使えることになった。
146 | - 提供された画像は向きを補正し、サイズも自動調節することになった。
147 | - コマンドモードを使う際、`data.yaml`と`style.txt`の中に、`erb`文法が書けるようになった。
148 | - `data.yaml`に`@date`で現在の年月日を出していて、[和暦](https://github.com/sugi/wareki)も使えることになった。
149 | - セキュリティの観点で、WEB版では`erb`文法の利用ができません。
150 | - `data.yaml`の `date: 令和2年1月14日現在` は空白の場合、和暦で本日の日付が入れられます。
151 | - `data.yaml`の `birth_day` Field「日付」はのみ記入した場合、年齢が自動で計算されます。
152 | - 「日付」の書式については、[和暦](https://github.com/sugi/wareki#%E3%83%91%E3%83%BC%E3%82%B9)または[西暦](https://docs.ruby-lang.org/ja/latest/class/Date.html#S_PARSE)が使えます。
153 | - サンプルデータとスタイルは`templates/`配下に置いた。
154 | - サンプルデータを当たり障りのない文章に再構成した。
155 | - サンプル写真を[StyleGAN](https://github.com/NVlabs/stylegan)で生成された偽の人物像を使用した。
156 |
--------------------------------------------------------------------------------
/app.rb:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 | require 'sinatra'
3 | require 'sinatra/reloader' if development?
4 |
5 | require './config'
6 | require './lib/cv_maker'
7 | require './lib/txt2yaml'
8 | require './lib/util'
9 |
10 | include Util
11 |
12 | get '/' do
13 | @title = "YAML to 履歴書"
14 | @date = Date.today
15 | @data_yml = load_as_erb("templates/data.yaml")
16 | @style_txt = load_as_erb("templates/style.txt")
17 | erb :index
18 | end
19 |
20 | post '/create' do
21 | begin
22 | @data = YAML.load(params[:data_yml])
23 | @style = TXT2YAMLConverter.new.convert(params[:style_txt])
24 |
25 | if !params[:photo].nil?
26 | @photo = params[:photo][:tempfile]
27 | @data["photo"] = @photo.path
28 | end
29 |
30 | @doc = CVMaker.new.generate(@data, @style)
31 | content_type 'application/pdf'
32 | @doc.render
33 | rescue => exception
34 | p exception
35 | @error_msg = exception.message
36 | status 403
37 | erb :error
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/config.rb:
--------------------------------------------------------------------------------
1 | class Config
2 | class << self
3 | @@settings = {
4 | VERSION: '0.4.0'
5 | }
6 |
7 | @@settings.each do |key, value|
8 | define_method key.to_sym do
9 | value.freeze
10 | end
11 | end
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.5'
2 | services:
3 | yaml_2_resume:
4 | container_name: yaml_2_resume
5 | build: .
6 | ports:
7 | - 14567:4567
8 | working_dir: /usr/src/app
9 | volumes:
10 | - ./share:/usr/src/app/share
11 | # web app mode
12 | command: ruby app.rb -o 0.0.0.0
13 | # cmd mode
14 | # command: ruby make_cv.rb -i templates/academic.yaml -s templates/academic.txt -o share/output.pdf
15 |
--------------------------------------------------------------------------------
/heroku.yml:
--------------------------------------------------------------------------------
1 | build:
2 | docker:
3 | web: Dockerfile
4 | run:
5 | web: ruby app.rb -o 0.0.0.0
6 |
--------------------------------------------------------------------------------
/lib/cv_maker.rb:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 | require "mini_magick"
3 | require "open-uri"
4 | require "prawn"
5 | require "wareki"
6 | require "yaml"
7 |
8 | require "./lib/txt2yaml"
9 | require "./lib/util"
10 |
11 | $font_faces = Hash.new
12 | $font_faces["mincho"] = "fonts/ipaexm.ttf"
13 | $font_faces["gothic"] = "fonts/ipaexg.ttf"
14 |
15 | DEFAULT_FONT_FACE = "mincho"
16 | DEFAULT_FONT_SIZE = 12
17 | DEFAULT_LINE_WIDTH = 0.5
18 |
19 | class CVMaker
20 | include TXT2YAML
21 | include Util
22 |
23 | def line_style(h)
24 | if h.has_key?("line_style")
25 | case h["line_style"]
26 | when "solid"
27 | undash
28 | when "dashed"
29 | d = DEFAULT_LINE_WIDTH
30 | @doc.dash([d, d])
31 | end
32 | else
33 | @doc.undash
34 | end
35 | if h.has_key?("line_width")
36 | @doc.line_width(h["line_width"])
37 | else
38 | @doc.line_width(DEFAULT_LINE_WIDTH)
39 | end
40 | end
41 |
42 | def get_value(h)
43 | value = h["value"]
44 | if value =~ /\$(.*)$/
45 | value = @data.fetch($1, "")
46 | end
47 | value
48 | end
49 |
50 | def get_font(h)
51 | font_size = h.fetch("font_size", DEFAULT_FONT_SIZE).to_f
52 | face = h.fetch("font_face", DEFAULT_FONT_FACE)
53 | font_face = ""
54 | if $font_faces.has_key?(face)
55 | font_face = $font_faces[face]
56 | else
57 | font_face = face
58 | end
59 | return font_size, font_face
60 | end
61 |
62 | def put_string(x, y, str, font_size, font_face)
63 | return if str == ""
64 | w = font_size * str.size
65 | h = font_size
66 | @doc.bounding_box([x, y], :width => w, :height => h) do
67 | @doc.font_size font_size
68 | @doc.font font_face
69 | @doc.text str
70 | end
71 | end
72 |
73 | def photo(h)
74 | return if !@data.has_key?("photo")
75 | x = size(h["x"])
76 | y = size(h["y"])
77 | width = size(h["width"])
78 | height = size(h["height"])
79 | file = @data["photo"]
80 | unless file.strip !~ /^https?|^ftp\:\/\//
81 | file = open(file).path
82 | end
83 | image = MiniMagick::Image.new(file)
84 | # 画像の向きを調整、切り抜き
85 | image.combine_options do |img|
86 | img.auto_orient
87 | img.strip # EXIF情報の除去
88 | img.gravity(:center)
89 | img.crop(resize_image_opt(image, width, height))
90 | end
91 | @doc.image(image.path, :at => [x, y], :width => width, :height => height)
92 | end
93 |
94 | def string(h)
95 | x = size(h["x"])
96 | y = size(h["y"])
97 | str = get_value(h)
98 | font_size, font_face = get_font(h)
99 | w = font_size * str.size
100 | h = font_size
101 | @doc.bounding_box([x, y], :width => w, :height => h) do
102 | @doc.font_size font_size
103 | @doc.font font_face
104 | @doc.text str
105 | end
106 | end
107 |
108 | def box(h)
109 | line_style(h)
110 | x = size(h["x"])
111 | y = size(h["y"])
112 | w = size(h["width"])
113 | h = size(h["height"])
114 | @doc.move_to(x, y)
115 | @doc.line_to(x + w, y)
116 | @doc.line_to(x + w, y + h)
117 | @doc.line_to(x, y + h)
118 | @doc.close_and_stroke
119 | end
120 |
121 | def line(h)
122 | line_style(h)
123 | x = size(h["x"])
124 | y = size(h["y"])
125 | dx = size(h["dx"])
126 | dy = size(h["dy"])
127 | @doc.move_to(x, y)
128 | @doc.line_to(x + dx, y + dy)
129 | @doc.stroke
130 | end
131 |
132 | def lines(h)
133 | line_style(h)
134 | points = h["points"]
135 | x = size(points[0]["x"])
136 | y = size(points[0]["y"])
137 | close = h.has_key?("close")
138 | @doc.move_to(x, y)
139 | points[1..(points.size - 1)].each do |i|
140 | if i.has_key?("dx")
141 | x = x + size(i["dx"])
142 | else
143 | x = size(i["x"])
144 | end
145 | if i.has_key?("dy")
146 | y = y + size(i["dy"])
147 | else
148 | y = size(i["y"])
149 | end
150 | @doc.line_to(x, y)
151 | end
152 | if close
153 | @doc.close_and_stroke
154 | else
155 | @doc.stroke
156 | end
157 | end
158 |
159 | def multi_lines(h)
160 | line_style(h)
161 | x = size(h["x"])
162 | y = size(h["y"])
163 | dx = size(h["dx"])
164 | dy = size(h["dy"])
165 | sx = size(h["sx"])
166 | sy = size(h["sy"])
167 | n = h["num"].to_i
168 | n.times do |i|
169 | @doc.move_to(x, y)
170 | @doc.line_to(x + dx, y + dy)
171 | @doc.stroke
172 | x = x + sx
173 | y = y + sy
174 | end
175 | end
176 |
177 | def puts_history(year_x, month_x, value_x, h)
178 | year = h.fetch("year", "").to_s
179 | month = h.fetch("month", "").to_s
180 | put_string(year_x, y, year, font_size, font_face)
181 | x = month_x - (month.size - 1) * font_size * 0.3
182 | put_string(x, y, month, font_size, font_face)
183 | put_string(value_x, y, h["value"].to_s, font_size, font_face)
184 | end
185 |
186 | # 学歴・職歴
187 | def education_experience(h)
188 | y = size(h["y"])
189 | year_x = size(h["year_x"])
190 | month_x = size(h["month_x"])
191 | value_x = size(h["value_x"])
192 | ijo_x = size(h["ijo_x"])
193 | dy = size(h["dy"])
194 | caption_x = size(h["caption_x"])
195 | font_size, font_face = get_font(h)
196 | put_string(caption_x, y, "学歴", font_size, font_face)
197 | y = y - dy
198 | education = @data["education"]
199 | education.each do |i|
200 | year = i.fetch("year", "").to_s
201 | month = i.fetch("month", "").to_s
202 | put_string(year_x, y, year, font_size, font_face)
203 | x = month_x - (month.size - 1) * font_size * 0.3
204 | put_string(x, y, month, font_size, font_face)
205 | put_string(value_x, y, i["value"].to_s, font_size, font_face)
206 | y = y - dy
207 | end
208 | put_string(caption_x, y, "職歴", font_size, font_face)
209 | y = y - dy
210 | experience = @data["experience"]
211 | experience.each do |i|
212 | year = i.fetch("year", "").to_s
213 | month = i.fetch("month", "").to_s
214 | put_string(year_x, y, year, font_size, font_face)
215 | x = month_x - (month.size - 1) * font_size * 0.3
216 | put_string(x, y, month, font_size, font_face)
217 | put_string(value_x, y, i["value"].to_s, font_size, font_face)
218 | y = y - dy
219 | end
220 | put_string(ijo_x, y, "以上", font_size, font_face)
221 | end
222 |
223 | def new_page(h)
224 | @doc.start_new_page
225 | end
226 |
227 | # 年・月・内容形式
228 | def history(h)
229 | y = size(h["y"])
230 | year_x = size(h["year_x"])
231 | month_x = size(h["month_x"])
232 | value_x = size(h["value_x"])
233 | font_size, font_face = get_font(h)
234 | data = get_value(h)
235 | dy = size(h["dy"])
236 | return if data == ""
237 | data.each do |i|
238 | year = i.fetch("year", "").to_s
239 | month = i.fetch("month", "").to_s
240 | put_string(year_x, y, year, font_size, font_face)
241 | x = month_x - (month.size - 1) * font_size * 0.3
242 | put_string(x, y, month, font_size, font_face)
243 | put_string(value_x, y, i["value"].to_s, font_size, font_face)
244 | y = y + dy
245 | end
246 | end
247 |
248 | def textbox(h)
249 | x = size(h["x"])
250 | y = size(h["y"])
251 | width = size(h["width"])
252 | height = size(h["height"])
253 | value = get_value(h)
254 | font_size, font_face = get_font(h)
255 | @doc.bounding_box([x, y], :width => width, :height => height) do
256 | @doc.font_size font_size
257 | @doc.font font_face
258 | @doc.text value
259 | end
260 | end
261 |
262 | def generate(data, style)
263 | @data = data
264 | # 今日の日付を入力
265 | @data['date'] ||= Date.today.strftime("%Jf") + "現在"
266 | # 年齢を計算、「平成7年1月13日 (満 25 歳)」のような入力であれば、
267 | # 故意にエラーを発生させて計算はしない
268 | begin
269 | current_date = Date.parse(@data['date'])
270 | birthday = Date.parse(@data['birth_day'])
271 | age = current_date.strftime('%Y%m%d').to_i
272 | age -= birthday.strftime('%Y%m%d').to_i
273 | age /= 10000
274 | @data['birth_day'] += " (満 #{age} 歳)"
275 | rescue => e
276 | puts e.message
277 | end
278 | @doc = Prawn::Document.new(:page_size => "A4")
279 | style.each do |i|
280 | send(i["type"], i)
281 | end
282 | @doc
283 | end
284 | end
285 |
--------------------------------------------------------------------------------
/lib/txt2yaml.rb:
--------------------------------------------------------------------------------
1 | require "yaml"
2 |
3 | module TXT2YAML
4 | def size(s, dpi = 75)
5 | if s =~ /\s*(\-?[0-9\.]+)\s*mm/
6 | $1.to_f / 25.4 * dpi
7 | elsif s =~ /\s*(-?[0-9\.]+)\s*cm/
8 | $1.to_f / 25.4 * dpi * 10
9 | elsif s =~ /\s*(-?[0-9\.]+)\s*px/
10 | $1.to_f
11 | else
12 | s.to_f
13 | end
14 | end
15 |
16 | def rest(a, h)
17 | a.each do |v|
18 | b = v.split(/=/)
19 | h[b[0]] = b[1]
20 | end
21 | end
22 |
23 | def string(a)
24 | h = Hash.new
25 | h["type"] = a.shift
26 | h["x"] = a.shift
27 | h["y"] = a.shift
28 | h["value"] = a.shift
29 | rest(a, h)
30 | h
31 | end
32 |
33 | def box(a)
34 | h = Hash.new
35 | h["type"] = a.shift
36 | h["x"] = a.shift
37 | h["y"] = a.shift
38 | h["width"] = a.shift
39 | h["height"] = a.shift
40 | rest(a, h)
41 | h
42 | end
43 |
44 | def photo(a)
45 | h = Hash.new
46 | h["type"] = a.shift
47 | h["x"] = a.shift
48 | h["y"] = a.shift
49 | h["width"] = a.shift
50 | h["height"] = a.shift
51 | h
52 | end
53 |
54 | def line(a)
55 | h = Hash.new
56 | h["type"] = a.shift
57 | h["x"] = a.shift
58 | h["y"] = a.shift
59 | h["dx"] = a.shift
60 | h["dy"] = a.shift
61 | if a.size != 0
62 | rest(a, h)
63 | end
64 | h
65 | end
66 |
67 | def lines(a)
68 | h = Hash.new
69 | h["type"] = a.shift
70 | n = a.shift.to_i
71 | points = []
72 | h["points"] = points
73 | points << {"x" => a.shift, "y" => a.shift}
74 | (n - 1).times do
75 | points << {"dx" => a.shift, "dy" => a.shift}
76 | end
77 | rest(a, h)
78 | h
79 | end
80 |
81 | def multi_lines(a)
82 | h = Hash.new
83 | h["type"] = a.shift
84 | h["x"] = a.shift
85 | h["y"] = a.shift
86 | h["dx"] = a.shift
87 | h["dy"] = a.shift
88 | h["num"] = a.shift
89 | h["sx"] = a.shift
90 | h["sy"] = a.shift
91 | h
92 | end
93 |
94 | def education_experience(a)
95 | h = Hash.new
96 | h["type"] = a.shift
97 | h["y"] = a.shift
98 | h["year_x"] = a.shift
99 | h["month_x"] = a.shift
100 | h["value_x"] = a.shift
101 | h["dy"] = a.shift
102 | h["caption_x"] = a.shift
103 | h["ijo_x"] = a.shift
104 | rest(a, h)
105 | h
106 | end
107 |
108 | def new_page(a)
109 | h = {"type" => "new_page"}
110 | h
111 | end
112 |
113 | def history(a)
114 | h = Hash.new
115 | h["type"] = a.shift
116 | h["y"] = a.shift
117 | h["year_x"] = a.shift
118 | h["month_x"] = a.shift
119 | h["value_x"] = a.shift
120 | h["dy"] = a.shift
121 | h["value"] = a.shift
122 | rest(a, h)
123 | h
124 | end
125 |
126 | def ymbox(a)
127 | a.shift
128 | name = a.shift
129 | y = size(a.shift)
130 | num = a.shift.to_i
131 | value = a.shift
132 | h = Hash[*a.map { |v| v.split(/=/) }.flatten]
133 | history_fontsize = h.fetch("font_size", 12)
134 | sy = size("7mm")
135 | dy = (num + 1) * sy
136 | namepos = 104 - name.length * 1.7
137 | r = Array.new
138 | r.push box("box,0,#{y},177mm,#{dy},line_width=2".split(","))
139 | r.push line("line,19mm,#{y + dy},0,#{-dy},line_style=dashed".split(","))
140 | r.push line("line,31mm,#{y + dy},0,#{-dy}".split(","))
141 | r.push multi_lines("multi_lines,0,#{y + dy - sy},177mm,0,#{num},0,-7mm".split(","))
142 | r.push history("history,#{y + dy - sy - size("2mm")},3mm,24mm,35mm,-7mm,#{value},font_size=#{history_fontsize}".split(","))
143 | r.push string("string,8mm,#{y + dy - size("2mm")},年,font_size=9".split(","))
144 | r.push string("string,24mm,#{y + dy - size("2mm")},月,font_size=9".split(","))
145 | r.push string("string,#{namepos}mm,#{y + dy - size("2mm")},#{name},font_size=9".split(","))
146 | return r
147 | end
148 |
149 | def miscbox(a)
150 | a.shift
151 | name = a.shift
152 | y = size(a.shift)
153 | height = size(a.shift)
154 | value = a.shift
155 | h = Hash[*a.map { |v| v.split(/=/) }.flatten]
156 | textbox_fontsize = h.fetch("font_size", 12)
157 | namepos = size((88.5 - name.length * 1.7).to_s + "mm")
158 | r = Array.new
159 | r.push string("string,#{namepos},#{y + height - size("2mm")},#{name},font_size=9".split(","))
160 | r.push line("line,0,#{y + height - size("7mm")},177mm,0".split(","))
161 | r.push textbox("textbox,2mm,#{y + height - size("9mm")},175mm,#{height - size("9mm")},#{value},font_size=#{textbox_fontsize}".split(","))
162 | r.push box("box,0,#{y},177mm,#{height},line_width=2".split(","))
163 | r
164 | end
165 |
166 | def textbox(a)
167 | h = Hash.new
168 | h["type"] = a.shift
169 | h["x"] = a.shift
170 | h["y"] = a.shift
171 | h["width"] = a.shift
172 | h["height"] = a.shift
173 | h["value"] = a.shift
174 | rest(a, h)
175 | h
176 | end
177 |
178 | def convert(style_txt)
179 | data = []
180 | style_txt.lines.each do |line|
181 | next if line =~ /^#/
182 | next if line.chomp == ""
183 | a = line.chomp.split(/,/)
184 | d = send(a[0], a)
185 | next if d == nil
186 | if d.kind_of?(Array)
187 | data = data + d
188 | else
189 | data.push d
190 | end
191 | end
192 | data
193 | end
194 |
195 | def load_file(file_path)
196 | style_txt = File.read(file_path)
197 | convert(style_txt)
198 | end
199 | end
200 |
201 | class TXT2YAMLConverter
202 | include TXT2YAML
203 | end
204 |
205 | if caller.length == 0
206 | if ARGV.size == 0
207 | puts "usage: input.txt"
208 | exit
209 | end
210 |
211 | filename = ARGV[0]
212 | data = TXT2YAMLConverter.new.convert(filename)
213 | YAML.dump(data, $stdout)
214 | end
215 |
--------------------------------------------------------------------------------
/lib/util.rb:
--------------------------------------------------------------------------------
1 | require 'erb'
2 | require 'date'
3 | require 'wareki'
4 |
5 | module Util
6 | def load_as_erb(file_path)
7 | ERB.new(File.read(file_path)).result(binding)
8 | end
9 |
10 | def resize_image_opt(img, w, h)
11 | w_ori = img[:width].to_f
12 | h_ori = img[:height].to_f
13 | w_f = w.to_f
14 | h_f = h.to_f
15 | w_tar = w_ori
16 | h_tar = h_ori
17 |
18 | len_max = [w_tar, h_tar].min
19 | if w_tar > h_tar
20 | h_tar = len_max
21 | w_tar = len_max * w_f / h_f
22 | else
23 | h_tar = len_max * h_f / w_f
24 | w_tar = len_max
25 | end
26 | "#{w_tar.to_i}x#{h_tar.to_i}+0+0!"
27 | end
28 |
29 | end
30 |
--------------------------------------------------------------------------------
/make_cv.rb:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 | require "optparse"
3 | require "prawn"
4 | require "yaml"
5 |
6 | require './config'
7 | require './lib/cv_maker'
8 | require './lib/txt2yaml'
9 | require './lib/util'
10 |
11 | include Util
12 |
13 | def parse_option
14 | args = {}
15 | OptionParser.new do |op|
16 | op.on("-i [datafile]", "--input [datafile]") { |v| args[:input] = v }
17 | op.on("-s [stylefile]", "--style [stylefile]") { |v| args[:style] = v }
18 | op.on("-o [output]", "--output [output]") { |v| args[:output] = v }
19 | op.on("-v", "--version") { |v| args[:version] = v }
20 | op.parse!(ARGV)
21 | end
22 | args
23 | end
24 |
25 | def check_fonts
26 | $font_faces.each do |k, v|
27 | if !File.exists?(v)
28 | puts <<-EOS
29 | Font files are not found.
30 | Please download IPAex fonts via
31 |
32 | https://ipafont.ipa.go.jp/node26
33 |
34 | and place them as
35 |
36 | ├── fonts
37 | │ ├── ipaexg.ttf
38 | │ └── ipaexm.ttf
39 | └── make_cv.rb
40 | EOS
41 |
42 | exit
43 | end
44 | end
45 | end
46 |
47 | def cerate_pdf(input_file, style_file, output_file)
48 | @date = Date.today
49 | @data = YAML.load(load_as_erb(input_file))
50 | if style_file =~ /\.txt$/
51 | @style = TXT2YAMLConverter.new.convert(load_as_erb(style_file))
52 | else
53 | @style = YAML.load(load_as_erb(style_file))
54 | end
55 |
56 | puts "input file: #{input_file}"
57 | puts "style file: #{style_file}"
58 | puts "output file: #{output_file}"
59 |
60 | @doc = CVMaker.new.generate(@data, @style)
61 | @doc.render_file output_file
62 | puts "Done."
63 | end
64 |
65 | check_fonts
66 |
67 | args = parse_option
68 | if args[:version]
69 | puts Config.VERSION
70 | exit(0)
71 | end
72 | input_file = args.fetch(:input, "templates/data.yaml")
73 | style_file = args.fetch(:style, "templates/style.txt")
74 | output_file = args.fetch(:output, "output.pdf")
75 |
76 | cerate_pdf(input_file, style_file, output_file)
77 |
--------------------------------------------------------------------------------
/makefile:
--------------------------------------------------------------------------------
1 | all: output.pdf academic.pdf
2 |
3 | output.pdf: style.txt data.yaml
4 | ruby make_cv.rb -i data.yaml -s style.txt -o $@
5 |
6 | academic.pdf: academic.txt data.yaml
7 | ruby make_cv.rb -i data.yaml -s academic.txt -o $@
8 |
9 | clean:
10 | rm -f output.pdf academic.pdf
11 |
--------------------------------------------------------------------------------
/photo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jerrywdlee/yaml_2_resume/70a14c94d6bdde66e8a645d3ff531ea9c3155ce9/photo.png
--------------------------------------------------------------------------------
/public/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jerrywdlee/yaml_2_resume/70a14c94d6bdde66e8a645d3ff531ea9c3155ce9/public/.gitkeep
--------------------------------------------------------------------------------
/public/script.js:
--------------------------------------------------------------------------------
1 | ($ => {
2 | const FILE_SIZE_LIMIT = 2 // 2mega
3 | $(() => {
4 | initEditor()
5 | initPhotoBtn()
6 |
7 | $(document)
8 | .on('click', '#photoBtn', () => {
9 | $('#photoInput').click()
10 | })
11 | .on('change', '#photoInput', ev => {
12 | const el = ev.currentTarget
13 | const file = el.files[0]
14 | if (file) {
15 | const fileSize = file.size
16 | if (fileSize > 1024 * 1024 * FILE_SIZE_LIMIT) {
17 | alert(`写真データを ${FILE_SIZE_LIMIT}m 以下にしてください!`)
18 | el.value = ''
19 | } else {
20 | setPhotoBtn(file)
21 | }
22 | } else {
23 | $('#photoBtn').text('写真をアップ')
24 | }
25 | })
26 | })
27 | })(jQuery)
28 |
29 | function initEditor() {
30 | const [dataYamlArea, styleTxtArea] = ['data_yml', 'style_txt'].map(id => {
31 | return document.getElementById(id)
32 | })
33 | if (!dataYamlArea || !styleTxtArea) {
34 | return
35 | }
36 | const editorOpt = {
37 | mode: "yaml",
38 | theme: 'eclipse',
39 | lineNumbers: true,
40 | indentUnit: 4
41 | }
42 | window.dataYamlEditor = CodeMirror.fromTextArea(dataYamlArea, editorOpt)
43 | window.styleTxtEditor = CodeMirror.fromTextArea(styleTxtArea, editorOpt)
44 | window.editorSave = () => {
45 | dataYamlEditor.save()
46 | styleTxtEditor.save()
47 | return true
48 | }
49 | }
50 |
51 | function initPhotoBtn() {
52 | const fileInput = document.querySelector('#photoInput')
53 | if (fileInput) {
54 | const file = fileInput.files[0]
55 | if (file) {
56 | setPhotoBtn(file)
57 | }
58 | }
59 | }
60 |
61 | function setPhotoBtn(file) {
62 | let fileName = file.name
63 | if (fileName.length > 10) {
64 | const l = fileName.length
65 | fileName = '...' + fileName.substring(l - 10, l)
66 | }
67 | $('#photoBtn').text(fileName)
68 | }
69 |
--------------------------------------------------------------------------------
/public/style.css:
--------------------------------------------------------------------------------
1 | .main-container {
2 | padding: 3em;
3 | }
4 |
5 | .photo-area {
6 | display: none;
7 | }
8 |
9 | .code-area {
10 | border: solid 1px #ccc;
11 | border-radius: 5px;
12 | }
13 | .CodeMirror {
14 | font-family: Monaco, 'Andale Mono', 'Lucida Console', 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace;
15 | font-size: 10pt;
16 | height: 450px;
17 | border-radius: 5px;
18 | }
19 | .CodeMirror pre.CodeMirror-line {
20 | padding-left: 10px
21 | }
22 | .CodeMirror .CodeMirror-gutters {
23 | border-top-left-radius: 5px;
24 | border-bottom-left-radius: 5px;
25 | }
26 |
27 | @media screen and (min-width: 769px) {
28 | .error-container {
29 | min-height: calc(100vh - 250px)
30 | }
31 | }
32 |
33 | @media screen and (max-width: 1023px) {
34 | .main-container {
35 | padding: 1em;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/sample/README_origin.md:
--------------------------------------------------------------------------------
1 | YAMLによる履歴書作成スクリプト
2 | ===
3 |
4 | [](LICENSE)
5 |
6 | YAML形式で書かれたデータファイルと、YAMLもしくはテキストファイル形式で書かれたスタイルから履歴書PDFファイルを作成するRubyスクリプトです。
7 |
8 | ## 必要なライブラリ等
9 |
10 | * Prawn
11 | * IAPexフォント
12 |
13 | Prawnから日本語を出力するためにIPAexフォントを使っています。スクリプトと同じ場所にfontsディレクトリを用意して、[ここ](https://ipafont.ipa.go.jp/node26)からフォントをダウンロードして以下のように配置してください。
14 |
15 | ```
16 | ├── fonts
17 | │ ├── ipaexg.ttf
18 | │ └── ipaexm.ttf
19 | └── make_cv.rb
20 | ```
21 |
22 | ## 使い方
23 |
24 | 以下のように、`-i`に続けてデータファイル、`-s`に続けてスタイルファイル、`-o`に続けて出力ファイルを指定します。省略した場合のデフォルトはそれぞれ`data.yaml`、`style.txt`、`output.pdf`です。
25 |
26 | ```
27 | $ ruby make_cv -h
28 | Usage: make_cv [options]
29 | -i, --input [datafile]
30 | -s, --style [stylefile]
31 | -o, --output [output]
32 | ```
33 |
34 | YAML形式のデータファイル(例:`data.yaml`)とスタイルファイル(例:`style.txt`)を用意し、スクリプトを以下のように実行します。
35 |
36 | ```
37 | $ ruby make_cv -i data.yaml -s style.txt -o output.pdf
38 | ```
39 |
40 | 添付のサンプルでは以下のような出力が得られます。
41 |
42 | [PDFファイル](sample/output.pdf)
43 |
44 | 
45 | 
46 |
47 | また、スタイルファイルを変えることで、同じデータファイルから異なる出力を得られます。以下はアカデミックポスト向けのスタイルファイル`academic.txt`を使った場合です。
48 |
49 | ```
50 | $ ruby make_cv -i data.yaml -s academic.txt -o academic.pdf
51 | ```
52 |
53 | [PDFファイル](sample/academic.pdf)
54 |
55 | 
56 | 
57 |
58 | ## データの用意の仕方
59 |
60 | データはYAML形式で用意します。
61 |
62 | 以下はサンプルの`data.yaml`の一部です。
63 |
64 | ```YAML
65 | # 名前等
66 | date: 2018年 6月 5日現在
67 | name_kana: りれきしょ かくたろう
68 | name: 履歴書 書太郎
69 | birth_day: 1543年1月31日 (満 73 歳)
70 | gender: 男
71 | cell_phone: 090-1234-5678
72 | email: hoge@hogehoge.org
73 | photo: photo.jpg
74 |
75 | # 住所
76 | address_kana: とうきょうとちよだくちよだ
77 | address: 東京都千代田区千代田1-1-1
78 | address_zip: 100-0001
79 | tel: 0120-000-XXX
80 | fax: 0120-111-XXX
81 | # 連絡先
82 | address_kana2: ほっかいどう わっかないし そうやみさき
83 | address2: 北海道稚内市宗谷岬
84 | address_zip2: 098-6758
85 | tel2: 0120-222-XXX
86 | fax2: 0120-333-XXX
87 | ```
88 |
89 | 例えば、写真が`photo.jpg`として用意してある場合、
90 |
91 | ```YAML
92 | photo: photo.jpg
93 | ```
94 |
95 | とすれば写真が貼られます。もし写真ファイルを指定しなかった場合、例えば
96 |
97 | ```YAML
98 | # photo: photo.jpg
99 | ```
100 |
101 | としてコメントアウトすると、写真部分は
102 |
103 | 
104 |
105 | のような出力になります。
106 |
107 | ## スタイルファイル
108 |
109 | 履歴書のスタイルファイルは、一行に一要素ずつ記述していきます。例えば`academic.txt`は以下のような内容になっています。
110 |
111 | ```
112 | # ヘッダー
113 | string,5mm,247mm,履 歴 書,font_size=14,font_face=gothic
114 | string,110mm,245mm,$date,font_size=9
115 |
116 | # 住所・連絡先等
117 | box,145mm,204mm,30mm,40mm,line_style=dashed
118 | string,148mm,240mm,写真を貼る位置,font_size=9
119 | string,147mm,233mm,1. 縦36〜40 mm,font_size=8
120 | string,150mm,230mm,横24〜30 mm,font_size=8
121 | string,147mm,227mm,2. 本人単身胸から上,font_size=8
122 | string,147mm,224mm,3. 裏面にのりづけ,font_size=8
123 | string,147mm,221mm,4. 裏面に氏名記入,font_size=8
124 | ```
125 |
126 | 一行目の
127 |
128 | ```
129 | string,5mm,247mm,履 歴 書,font_size=14,font_face=gothic
130 | ```
131 |
132 | は、(5mm,247mm)の位置に「履 歴 書」という文字を、フォントサイズ14で、フォントはゴシックで記述する命令です。このうち必須なのは座標と文字列ですが、その後にオプションとしてフォントサイズやフォントの指定ができます。
133 |
134 | 次の行の
135 |
136 | ```
137 | string,110mm,245mm,$date,font_size=9
138 | ```
139 |
140 | も同様に(110mm, 245mm)の位置に文字列を出力する命令ですが、出力する文字列が`$date`となっています。これは、データファイルの`data`要素に置換されます。今、データファイルは
141 |
142 | ```yaml
143 | date: 2018年 6月 5日現在
144 | ```
145 |
146 | とあるので、
147 |
148 | ```
149 | string,110mm,245mm,$date,font_size=9
150 | ```
151 |
152 | は
153 |
154 | ```
155 | string,110mm,245mm,2018年 6月 5日現在,font_size=9
156 | ```
157 |
158 | に展開されます。
159 |
160 | テキスト形式の命令リストは以下の通りです。
161 |
162 | 命令| フォーマット| 説明
163 | -- | ---- | ----
164 | string | string, x, y, value[,font options] | (x,y)に文字列valueを出力
165 | line | line, x, y, dx, dy[,line options] | (x,y)から(x+dx, y+dy)に線を描画
166 | box | box,x,y,width,height[,line options]| (x,y)に指定された幅と高さのボックスを描画
167 | photo |photo, x, y, width, height | 指定位置、サイズに写真ファイル`$photo`を描画
168 | new_page |new_page | 改ページ
169 | textbox |textbox,x,y,width,height,value[,font options] |指定位置、サイズにテキストボックスを描画
170 | multi_lines| multi_lines, x,y,dx,dy,num,sx,sy| (x,y)から、(dx,dy)方向に、毎回(sx,sy)だけ座標をずらしながらnum回線を引きます
171 | ymbox| ymbox,title,height,num,$value | $valueをhistoryデータとして、高さyに、年月表を作るマクロです。
172 | miscbox| miscbox,title,y,height,$value | タイトル付きテキストボックスです。$valueの内容をテキストボックス内に展開します。
173 |
174 | ### 特別な命令
175 |
176 | #### history
177 |
178 | 年、月、内容をともなったデータを描画する命令です。ymboxやmiscboxの内部で呼ばれます。
179 |
180 | ```
181 | history, y, year_x, month_x, value_x, dy, value[,font options]
182 | ```
183 |
184 | * y: 描画を始めるy座標
185 | * year_x, month_x, value_x: それぞれ年、月、内容を書くx座標
186 | * dy: 改行時にどれだけ下に下げるか
187 | * value: 内容
188 |
189 | history環境に使われるデータは以下のように指定します。
190 |
191 | ```yaml
192 | licences:
193 | -
194 | year: 19XX
195 | month: 11
196 | value: 普通自動車免許
197 | -
198 | year: 20XX
199 | month: 11
200 | value: 履歴書検定1級
201 | ```
202 |
203 | `year`や`month`は省略可能です(空白になります)。
204 |
205 | #### education_experience
206 |
207 | 学歴、職歴を書く命令です。命令フォーマットは以下の通りです。
208 |
209 | ```
210 | education_experience, y, year_x, month_x, value_x, dy, caption_x, ijo_x, [,font options]
211 | ```
212 |
213 | * y: 描画を始めるy座標
214 | * year_x, month_x, value_x: それぞれ年、月、内容を書くx座標
215 | * dy: 改行時にどれだけ下に下げるか
216 | * caption_x: 「学歴」や「職歴」の文字のx座標
217 | * ijo_x: 「以上」の文字のx座標
218 |
219 | なお、学歴データは`$education`が、職歴データは`$experience$`が仮定されます。
220 |
221 | #### lines
222 |
223 | 複数の線を書く命令です。履歴書によくある右上が凹んだボックスを書くために用意してあります。命令フォーマットは以下の通りです。
224 |
225 | ```
226 | lines, num, x,y, dx, dy, ..., [,line options]
227 | ```
228 |
229 | 最初に「何個の点データがあるか」を`num`で指定します。その後、始点、次の点の相対座標・・・と続け、最後に線のオプションを指定します。なお、この命令だけのオプションとして「close」というものがあります。これを指定すると最後に線を閉じます。
230 |
231 | #### ymbox
232 |
233 | 「年、月、事柄」を書くマクロです。例えば
234 |
235 | ```
236 | ymbox,免許・資格,204mm,4,$licences
237 | ```
238 |
239 | は、「免許・資格」というタイトルの4行分の年月ボックスを、高さ204mmのところに配置する、という意味です。最後がデータのYAMLファイルの対応するレコードです。例えば、
240 |
241 | ```yaml
242 | # 免許・資格
243 | licences:
244 | -
245 | year: 19XX
246 | month: 11
247 | value: 普通自動車免許
248 | -
249 | year: 20XX
250 | month: 11
251 | value: 履歴書検定1級
252 | ```
253 |
254 | というデータだったとすると、
255 |
256 | 
257 |
258 | に展開されます。
259 |
260 | ```
261 | ymbox,免許・資格,204mm,4,$licences,font_size=9
262 | ```
263 |
264 | などのように、最後にフォントサイズを指定できます。
265 |
266 | #### miscbox
267 |
268 | タイトル付きのテキストボックスに展開されるマクロです。例えば、
269 |
270 | ```
271 | miscbox,教育歴,120mm,50mm,$teaching,font_size=12
272 | ```
273 |
274 | は、「教育歴」というタイトルの高さ(height)50mmのテキストボックスを、高さ(y座標)120mmのところに配置する、という意味です。最後のフォントサイズ指定は任意です。対応するYAMLレコードは\$teachingです。
275 |
276 | 例えば
277 |
278 | ```yaml
279 | # 教育歴
280 | teaching: |
281 | 「履歴書学特論」平成15年から17年まで
282 | 「PDF出力特論」平成18年から23年まで
283 | 「スタイルファイル特別演習」平成20年から29年まで
284 | ```
285 |
286 | というデータだったとすると、
287 |
288 | 
289 |
290 | に展開されます。
291 |
292 | ## スタイルファイル(YAML形式)
293 |
294 | 上記のテキスト形式で書かれたスタイルファイルは内部的にYAMLに変換されて処理されているため、スタイルファイルはYAML形式でも書くことができます。・・・が、実際やってみたら死ぬほど面倒だったので、通常はテキスト形式で書くことになろうかと思います。テキスト形式のスタイルファイルは`txt2yaml.rb`でYAML形式に変換できます。
295 |
296 | 例えば
297 |
298 | ```
299 | string,5mm,247mm,履 歴 書,font_size=14,font_face=gothic
300 | string,110mm,245mm,$date,font_size=9
301 | ```
302 |
303 | を`txt2yaml.rb`に食わせると、
304 |
305 |
306 | ```YAML
307 | ---
308 | - type: string
309 | x: 5mm
310 | y: 247mm
311 | value: 履 歴 書
312 | font_size: '14'
313 | font_face: gothic
314 | - type: string
315 | x: 110mm
316 | y: 245mm
317 | value: "$date"
318 | font_size: '9'
319 | ```
320 |
321 | が出力されます。同様にYAMLで書かれたスタイルファイルは`yaml2txt.rb`でテキスト形式に変換できます。
322 |
323 | ## 参考
324 |
325 | このスクリプトは、[PruneMazui](https://github.com/PruneMazui)さんの[resume-maker](https://github.com/PruneMazui/resume-maker)に影響されて開発したものです。
326 |
327 |
328 | ## 履歴
329 |
330 | - 2018年7月30日 ymboxマクロ及びmiscboxマクロを追加
331 | - 2018年6月6日 リリース
332 |
333 | ## Herokuメモ
334 |
335 | ```sh
336 | $ heroku create yaml-2-resume
337 | $ heroku stack:set container
338 | $ git push heroku master
339 | ```
--------------------------------------------------------------------------------
/sample/screen_pc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jerrywdlee/yaml_2_resume/70a14c94d6bdde66e8a645d3ff531ea9c3155ce9/sample/screen_pc.png
--------------------------------------------------------------------------------
/share/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jerrywdlee/yaml_2_resume/70a14c94d6bdde66e8a645d3ff531ea9c3155ce9/share/.gitkeep
--------------------------------------------------------------------------------
/spec/app_spec.rb:
--------------------------------------------------------------------------------
1 | # require File.expand_path '../spec_helper.rb', __FILE__
2 | require './app.rb'
3 | require './lib/util'
4 | include Util
5 |
6 | describe "Sinatra Application" do
7 | it "should allow accessing the home page" do
8 | get '/'
9 | expect(last_response).to be_ok
10 | end
11 |
12 | it "should receive form-data" do
13 | @date = Date.today
14 | data = {
15 | data_yml: load_as_erb("templates/data.yaml"),
16 | style_txt: load_as_erb("templates/style.txt"),
17 | }
18 | post '/create', data
19 | expect(last_response).to be_ok
20 | end
21 |
22 | it "should raise error" do
23 | data = {}
24 | post '/create', data
25 | expect(last_response).not_to be_ok
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/spec/cv_maker_spec.rb:
--------------------------------------------------------------------------------
1 | require 'securerandom'
2 |
3 | require './lib/cv_maker'
4 | require './lib/txt2yaml'
5 | require './lib/util'
6 |
7 | include Util
8 |
9 | describe "CVMaker" do
10 | before do
11 | @converter = TXT2YAMLConverter.new
12 | @date = Date.today
13 | @file_name = "_spec_#{SecureRandom.hex(8)}.pdf"
14 | end
15 |
16 | after do
17 | begin
18 | File.delete(@file_name)
19 | rescue
20 | p $!
21 | end
22 | end
23 |
24 | it "should create normal resume pdf" do
25 | data = YAML.load(load_as_erb('templates/data.yaml'))
26 | style = @converter.load_file('templates/style.txt')
27 | doc = CVMaker.new.generate(data, style)
28 | expect(doc).to be_truthy
29 | doc.render_file @file_name
30 | expect(File.exists?(@file_name)).to be_truthy
31 | end
32 |
33 | it "should create academic resume pdf" do
34 | data = YAML.load(load_as_erb('templates/academic.yaml'))
35 | style = @converter.load_file('templates/academic.txt')
36 | doc = CVMaker.new.generate(data, style)
37 | expect(doc).to be_truthy
38 | doc.render_file @file_name
39 | expect(File.exists?(@file_name)).to be_truthy
40 | end
41 |
42 | end
43 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | # spec/spec_helper.rb
2 | require 'rack/test'
3 | require 'rspec'
4 | require 'simplecov'
5 |
6 | SimpleCov.start
7 |
8 | ENV['RACK_ENV'] = 'test'
9 |
10 | module RSpecMixin
11 | include Rack::Test::Methods
12 | def app() Sinatra::Application end
13 | end
14 |
15 | RSpec.configure { |c| c.include RSpecMixin }
16 |
--------------------------------------------------------------------------------
/spec/txt2yaml_spec.rb:
--------------------------------------------------------------------------------
1 | require './lib/txt2yaml.rb'
2 |
3 | describe "TXT2YAMLConverter" do
4 | before do
5 | @converter = TXT2YAMLConverter.new
6 | end
7 |
8 | it "should convert style.txt to style array" do
9 | style = @converter.load_file('templates/style.txt')
10 | expect(style.size).to be > 0
11 | end
12 |
13 | it "should convert academic.txt to style array" do
14 | style = @converter.load_file('templates/academic.txt')
15 | expect(style.size).to be > 0
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/templates/academic.txt:
--------------------------------------------------------------------------------
1 | # ヘッダー
2 | string,5mm,247mm,履 歴 書,font_size=14,font_face=gothic
3 | string,110mm,245mm,$date,font_size=9
4 |
5 | # 住所・連絡先等
6 | box,145mm,204mm,30mm,40mm,line_style=dashed
7 | string,148mm,240mm,写真を貼る位置,font_size=9
8 | string,147mm,233mm,1. 縦36〜40 mm,font_size=8
9 | string,150mm,230mm,横24〜30 mm,font_size=8
10 | string,147mm,227mm,2. 本人単身胸から上,font_size=8
11 | string,147mm,224mm,3. 裏面にのりづけ,font_size=8
12 | string,147mm,221mm,4. 裏面に氏名記入,font_size=8
13 | photo,145mm,244mm,30mm,40mm
14 | lines,6,0mm,240mm,139mm,0mm,0mm,-41mm,38mm,0mm,0mm,-36mm,-177mm,0mm,line_width=2.0,close=true
15 | line,0,233mm,139mm,0,line_style=dashed
16 | string,2mm,238mm,ふりがな,font_size=9
17 | string,30mm,238mm,$name_kana,font_size=9
18 | string,2mm,231mm,氏 名,font_size=9
19 | string,30mm,231mm,$name,font_size=14
20 | line,0,218mm,139mm,0mm
21 | line,15mm,218mm,0,-13mm
22 | string,1.5mm,217mm,生年月日,font_size=9
23 | string,30mm,213mm,$birth_day,font_size=12
24 | line,110mm,218mm,0mm,-13mm
25 | string,121mm,214mm,$gender,font_size=12
26 | line,21mm,205mm,0,-6mm,line_style=dashed
27 | string,1.5mm,203.5mm,携帯電話番号,font_size=9
28 | line,0,205mm,139mm,0mm
29 | string,25mm,203.5mm,$cell_phone,font_size=9
30 | line,56mm,205mm,0mm,-6mm
31 | line,69mm,205mm,0mm,-6mm,line_style=dashed
32 | string,57mm,204mm,E-MAIL,font_size=9
33 | string,75mm,204mm,$email,font_size=9
34 | line,0,205mm,139mm,0mm
35 | line,0,199mm,139mm,0mm
36 | line,0,194mm,139mm,0,line_style=dashed
37 | line,0,181mm,177mm,0
38 | line,0,176mm,139mm,0,line_style=dashed
39 | line,139mm,199mm,0mm,-36mm
40 | string,141mm,198mm,電話,font_size=9
41 | string,143mm,190mm,$tel,font_size=9
42 | string,141mm,180mm,電話,font_size=9
43 | string,143mm,172mm,$tel2,font_size=9
44 | string,2mm,198mm,ふりがな,font_size=8
45 | string,20mm,198mm,$address_kana,font_size=8
46 | string,2mm,193mm,現住所 〒,font_size=8
47 | string,15mm,193mm,$address_zip,font_size=8
48 | string,15mm,188mm,$address,font_size=12
49 | string,2mm,180mm,ふりがな,font_size=8
50 | string,20mm,180mm,$address_kana2,font_size=8
51 | string,2mm,175mm,連絡先 〒,font_size=9
52 | string,15mm,175mm,$address_zip2,font_size=9
53 | string,15mm,169mm,$address2,font_size=12
54 |
55 | # 所属学会・学位論文など
56 | box,0mm,137mm,177mm,24mm,line_width=2
57 | line,0mm,145mm,177mm,0mm
58 | line,0mm,153mm,177mm,0mm
59 | line,25mm,137mm,0mm,24mm
60 | line,88mm,153mm,0mm,8mm
61 | line,113mm,153mm,0mm,8mm
62 |
63 | string,4mm,159mm,博士学位
64 | string,92mm,159mm,取得年度
65 | string,4mm,151mm,授与機関
66 | string,4mm,143mm,学位論文
67 | string,26mm,159mm,$degree
68 | string,117mm,159mm,$degree_year
69 | string,26mm,151mm,$degree_affiliation
70 | string,26mm,143mm,$thesis_title,font_face=Times-Roman
71 |
72 | # 学歴・職歴
73 | box,0mm,9mm,177mm,126mm,line_width=2
74 | multi_lines,0mm,16mm,177mm,0,17,0,7mm
75 | line,19mm,135mm,0,-126mm,line_style=dashed
76 | line,31mm,135mm,0,-126mm
77 | string,8mm,133mm,年,font_size=9
78 | string,24mm,133mm,月,font_size=9
79 | string,77mm,133mm,学歴・職歴(各項目ごとにまとめて書く),font_size=9
80 | education_experience,127mm,3mm,24mm,35mm,7mm,95mm,155mm,font_size=12
81 |
82 |
83 | # 2ページ目
84 | new_page
85 | ymbox,免許・資格,204mm,4,$licences
86 | ymbox,主な受賞・表彰等,173mm,3,$awards
87 | miscbox,教育歴,120mm,50mm,$teaching,font_size=12
88 | miscbox,所属学会等,84mm,33mm,$affiliated_society
89 | miscbox,その他特記事項,55mm,26mm,$notices,font_size=12
90 |
91 | # 署名欄
92 | string,113mm,36mm,上記のとおり相違ありません。
93 | string,140mm,24mm,年 月 日
94 | string,165mm,12mm,印
95 | string,85mm,12mm,氏名
96 | line,80mm,5mm,90mm,0
97 |
--------------------------------------------------------------------------------
/templates/academic.yaml:
--------------------------------------------------------------------------------
1 | # 名前等
2 | date: <%= @date.strftime("%Y年%m月%d日") %>現在
3 | name_kana: りれき たろう
4 | name: 履歴 太郎
5 | birth_day: <%= (@date << 30 * 12).strftime("%Y年%m月%d日") %> (満 30 歳)
6 | gender: 男
7 | cell_phone: 090-1234-5678
8 | email: rireki-taro@example.org
9 | # 写真をアップロードした場合、このフィールドが無視されます
10 | # photo: https://cdn.jsdelivr.net/gh/jerrywdlee/yaml_cv@master/photo.png
11 |
12 | # 住所
13 | address_kana: とうきょうとちよだくちよだ
14 | address: 東京都千代田区千代田1-1-1
15 | address_zip: 100-0001
16 | tel: 0120-000-XXX
17 | fax: 0120-111-XXX
18 | # 連絡先
19 | address_kana2: ほっかいどう わっかないし そうやみさき
20 | address2: 北海道稚内市宗谷岬
21 | address_zip2: 098-6758
22 | tel2: 0120-222-XXX
23 | fax2: 0120-333-XXX
24 |
25 | # 学位
26 | degree: 博士(工学)
27 | # 学位取得年度
28 | degree_year: <%= (@date << 12).year %>年度
29 | # 学位授与機関
30 | degree_affiliation: 履歴書大学
31 | # 学位論文
32 | thesis_title: How to write a resume without a spreadsheet
33 |
34 |
35 | # 学歴
36 | education:
37 | -
38 | year: <%= (@date << 9 * 12).year %>
39 | month: 4
40 | value: 履歴書大学履歴書学部 入学
41 | -
42 | year: <%= (@date << 5 * 12).year %>
43 | month: 3
44 | value: 同 卒業
45 | -
46 | year: <%= (@date << 5 * 12).year %>
47 | month: 4
48 | value: 履歴書大学履歴書研究科履歴書専攻博士前期課程 入学
49 | -
50 | year: <%= (@date << 3 * 12).year %>
51 | month: 3
52 | value: 同 修了
53 | -
54 | year: <%= (@date << 3 * 12).year %>
55 | month: 4
56 | value: 履歴書大学履歴書研究科履歴書専攻博士後期課程 入学
57 | -
58 | year: <%= (@date << 1 * 12).year %>
59 | month: 3
60 | value: 同 修了
61 |
62 |
63 |
64 | #職歴
65 | experience:
66 | -
67 | year: <%= (@date << 1 * 12).year %>
68 | month: 4
69 | value: 株式会社履歴書入社
70 | -
71 | year: <%= @date.year %>
72 | month: 10
73 | value: 株式会社履歴書退職
74 | -
75 | year: <%= @date.year %>
76 | month: 10
77 | value: 株式会社XXX 入社
78 | -
79 | value: 現在にいたる
80 |
81 | # 免許・資格
82 | licences:
83 | -
84 | year: <%= (@date << 9 * 12).year %>
85 | month: 11
86 | value: 普通自動車免許
87 | -
88 | year: <%= (@date << 5 * 12).year %>
89 | month: 11
90 | value: 英検1級
91 |
92 |
93 | # 主な受賞・表彰等
94 | awards:
95 | -
96 | year: <%= (@date << 7 * 12).year %>
97 | month:
98 | value: 第二回履歴書学会ポスター賞
99 | -
100 | year: <%= (@date << 4 * 12).year %>
101 | month:
102 | value: 第五回履歴書学会若手奨励賞
103 |
104 | # 教育歴
105 | teaching: |
106 | 「履歴書学特論」平成15年から17年まで
107 | 「PDF出力特論」平成18年から23年まで
108 | 「スタイルファイル特別演習」平成20年から29年まで
109 |
110 | # 所属学会
111 | affiliated_society: |
112 | 日本履歴書学会
113 | 神エクセル研究会
114 |
115 | # その他特記事項
116 | notices: |
117 | 着任可能時期: <%= (@date >> 12).year %>年4月1日
118 | 希望職位: 助教
119 |
120 | #通勤時間
121 | commuting_time: 1時間20分
122 |
123 | #扶養家族数(配偶者を除く)
124 | dependents: 2人
125 |
126 | #配偶者の有無
127 | spouse: 有
128 |
129 | #配偶者の扶養義務
130 | supporting_spouse: 有
131 |
132 | #趣味
133 | hobby: |
134 | 読書、音楽鑑賞
135 |
136 | #志望動機
137 | motivation: |
138 | 貴学校の研究室の設備が充実しており、過去実績も豊富しております。
139 | 是非とも貴学校で研究を行いたいと思います。
140 |
141 | # 本人希望記入欄
142 | request: |
143 | 所属研究室の規定に従います。
144 |
--------------------------------------------------------------------------------
/templates/data.yaml:
--------------------------------------------------------------------------------
1 | # 名前等
2 | # date が空白の時、今日の日付(和暦)が自動で入ります
3 | # date: <%= @date.strftime("%Jf") %>現在
4 | name_kana: りれき たろう
5 | name: 履歴 太郎
6 | birth_day: <%= (@date << 25 * 12).strftime("%Jf") %>
7 | # 年齢は誕生日を基づいて計算し、下記の書式になります
8 | # <%= (@date << 25 * 12).strftime("%Jf") %> (満 25 歳)
9 | gender: 男
10 | cell_phone: 090-1234-5678
11 | email: rireki-taro@example.org
12 | # 写真をアップロードした場合、このフィールドが無視されます
13 | photo: https://cdn.jsdelivr.net/gh/jerrywdlee/yaml_cv@master/photo.png
14 |
15 | # 住所
16 | address_kana: とうきょうとちよだくちよだ
17 | address: 東京都千代田区千代田1-1-1
18 | address_zip: 100-0001
19 | tel: 03-000-000
20 | # fax: 0120-111-XXX
21 | # 連絡先
22 | # address_kana2: ほっかいどう わっかないし そうやみさき
23 | # address2: 北海道稚内市宗谷岬
24 | # address_zip2: 098-6758
25 | # tel2: 0120-222-XXX
26 | # fax2: 0120-333-XXX
27 | address2: 同上
28 |
29 | # 学歴
30 | education:
31 | -
32 | year: <%= (@date << 10 * 12).strftime("%Jy") %>
33 | month: 4
34 | value: 履歴高校普通科 入学
35 | -
36 | year: <%= (@date << 7 * 12).strftime("%Jy") %>
37 | month: 3
38 | value: 同 卒業
39 | -
40 | year: <%= (@date << 7 * 12).strftime("%Jy") %>
41 | month: 4
42 | value: 履歴大学履歴書学部 入学
43 | -
44 | year: <%= (@date << 3 * 12).strftime("%Jy") %>
45 | month: 3
46 | value: 同 卒業
47 |
48 | #職歴
49 | experience:
50 | -
51 | year: <%= (@date << 3 * 12).strftime("%Jy") %>
52 | month: 4
53 | value: 株式会社履歴書 入社
54 | -
55 | year: <%= (@date << 1 * 12).strftime("%Jy") %>
56 | month: 10
57 | value: 株式会社履歴書 退職
58 | -
59 | year: <%= (@date << 1 * 12).strftime("%Jy") %>
60 | month: 11
61 | value: 株式会社XXX 入社
62 | -
63 | value: 現在にいたる
64 |
65 | # 免許・資格
66 | licences:
67 | -
68 | year: <%= (@date << 7 * 12).strftime("%Jy") %>
69 | month: 4
70 | value: 普通自動車免許
71 | -
72 | year: <%= (@date << 7 * 12).strftime("%Jy") %>
73 | month: 11
74 | value: 英検準1級
75 |
76 | #通勤時間
77 | commuting_time: 1時間20分
78 |
79 | #扶養家族数(配偶者を除く)
80 | dependents: 0人
81 |
82 | #配偶者の有無
83 | spouse: なし
84 |
85 | #配偶者の扶養義務
86 | supporting_spouse: なし
87 |
88 | #趣味
89 | hobby: |
90 | 読書、音楽鑑賞
91 |
92 | #志望動機
93 | motivation: |
94 | 貴社の事業に共感を持ち、是非ご一緒に働きたいと思います。
95 |
96 | # 本人希望記入欄
97 | request: |
98 | 貴社の規定に従います。
99 |
--------------------------------------------------------------------------------
/templates/style.txt:
--------------------------------------------------------------------------------
1 | # ヘッダー
2 | string,110mm,245mm,$date,font_size=9
3 | string,5mm,247mm,履 歴 書,font_size=14,font_face=gothic
4 |
5 | # 写真
6 | box,145mm,204mm,30mm,40mm,line_style=dashed
7 | string,148mm,240mm,写真を貼る位置,font_size=9
8 | string,147mm,233mm,1. 縦36〜40 mm,font_size=8
9 | string,150mm,230mm,横24〜30 mm,font_size=8
10 | string,147mm,227mm,2. 本人単身胸から上,font_size=8
11 | string,147mm,224mm,3. 裏面にのりづけ,font_size=8
12 | string,147mm,221mm,4. 裏面に氏名記入,font_size=8
13 | photo,145mm,244mm,30mm,40mm
14 | lines,6,0mm,240mm,139mm,0mm,0mm,-41mm,38mm,0mm,0mm,-53mm,-177mm,0mm,line_width=2.0,close=true
15 | line,0,233mm,139mm,0,line_style=dashed
16 | string,2mm,238mm,ふりがな,font_size=9
17 | string,30mm,238mm,$name_kana,font_size=9
18 | string,2mm,231mm,氏 名,font_size=9
19 | string,30mm,231mm,$name,font_size=14
20 | line,0,218mm,139mm,0mm
21 | line,15mm,218mm,0,-13mm
22 | string,1.5mm,217mm,生年月日,font_size=9
23 | string,30mm,213mm,$birth_day,font_size=12
24 | line,110mm,218mm,0mm,-13mm
25 | string,121mm,214mm,$gender,font_size=12
26 | line,21mm,205mm,0,-6mm,line_style=dashed
27 | string,1.5mm,203.5mm,携帯電話番号,font_size=9
28 | line,0,205mm,139mm,0mm
29 | string,25mm,203.5mm,$cell_phone,font_size=9
30 | line,56mm,205mm,0mm,-6mm
31 | line,69mm,205mm,0mm,-6mm,line_style=dashed
32 | string,57mm,204mm,E-MAIL,font_size=9
33 | string,75mm,204mm,$email,font_size=9
34 | line,0,205mm,139mm,0mm
35 | line,0,199mm,139mm,0mm
36 | line,0,192mm,139mm,0,line_style=dashed
37 | line,0,173mm,177mm,0
38 | line,0,166mm,139mm,0,line_style=dashed
39 | line,139mm,199mm,0mm,-53mm
40 | line,139mm,186mm,38mm,0mm,line_style=dashed
41 | string,141mm,198mm,電話,font_size=9
42 | string,143mm,192mm,$tel,font_size=9
43 | string,141mm,185mm,FAX,font_size=9
44 | string,143mm,179mm,$fax,font_size=9
45 | string,141mm,172mm,電話,font_size=9
46 | string,143mm,166mm,$tel2,font_size=9
47 | string,141mm,159mm,FAX,font_size=9
48 | string,143mm,153mm,$fax2,font_size=9
49 | line,139mm,160mm,38mm,0mm,line_style=dashed
50 | string,2mm,197mm,ふりがな,font_size=9
51 | string,20mm,197mm,$address_kana,font_size=9
52 | string,2mm,191mm,現住所 〒,font_size=9
53 | string,15mm,191mm,$address_zip,font_size=9
54 | string,15mm,185mm,$address,font_size=12
55 | string,2mm,171mm,ふりがな,font_size=9
56 | string,20mm,171mm,$address_kana2,font_size=9
57 | string,2mm,165mm,連絡先 〒,font_size=9
58 | string,15mm,165mm,$address_zip2,font_size=9
59 | string,15mm,159mm,$address2,font_size=12
60 | box,0mm,17mm,177mm,119mm,line_width=2
61 | multi_lines,0mm,24mm,177mm,0,16,0,7mm
62 | line,19mm,136mm,0,-119mm
63 | line,31mm,136mm,0,-119mm
64 | string,8mm,134mm,年,font_size=9
65 | string,24mm,134mm,月,font_size=9
66 | string,77mm,134mm,学歴・職歴(各項目ごとにまとめて書く),font_size=9
67 | education_experience,128mm,3mm,24mm,35mm,7mm,95mm,155mm,font_size=12
68 | string,1mm,14mm,記入上の注意,font_size=9
69 | string,22mm,14mm,数字はアラビア数字で、文字はくずさず正確に書く。,font_size=9
70 | new_page
71 | box,0,190mm,177mm,49mm,line_width=2
72 | line,19mm,239mm,0,-49mm
73 | line,31mm,239mm,0,-49mm
74 | multi_lines,0mm,232mm,177mm,0,6,0,-7mm
75 | string,8mm,237mm,年,font_size=9
76 | string,24mm,237mm,月,font_size=9
77 | string,90mm,237mm,免許・資格,font_size=9
78 | history,230mm,3mm,24mm,35mm,-7mm,$licences,font_size=12
79 | box,0,167mm,177mm,15mm,line_width=2
80 | string,2mm,180mm,通勤時間,font_size=9
81 | string,5mm,173mm,$commuting_time,font_size=12
82 | string,59mm,180mm,扶養家族,font_size=9
83 | string,59mm,173mm,(配偶者を除く),font_size=9
84 | string,85mm,173mm,$dependents,font_size=12
85 | string,99mm,180mm,配偶者,font_size=9
86 | string,116mm,173mm,$spouse,font_size=12
87 | string,139mm,180mm,配偶者の扶養義務,font_size=9
88 | string,155mm,173mm,$supporting_spouse,font_size=12
89 | line,57mm,167mm,0,15mm
90 | line,97mm,167mm,0,15mm
91 | line,137mm,167mm,0,15mm
92 | box,0,120mm,177mm,40mm,line_width=2
93 | string,2mm,158mm,趣味・特技,font_size=9
94 | textbox,2mm,152mm,173mm,30mm,$hobby,font_size=13
95 | box,0,73mm,177mm,40mm,line_width=2
96 | string,2mm,111mm,志望動機,font_size=9
97 | textbox,2mm,105mm,173mm,30mm,$motivation,font_size=13
98 | box,0,26mm,177mm,40mm,line_width=2
99 | string,2mm,64mm,本人希望記入欄,font_size=9
100 | textbox,2mm,58mm,173mm,30mm,$request,font_size=13
101 |
--------------------------------------------------------------------------------
/views/error.erb:
--------------------------------------------------------------------------------
1 | システムエラーが発生しました
6 | 下記のエラーが発生しました
8 | <%= @error_msg %>
9 |