jekyll-tsc 0.0.2

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3ea5560f47a48dbde778b57ec1f170b9c3570b3554e2babef0a19e581a0f34e3
4
+ data.tar.gz: 1a671aac61e08773b3e963451a0eb1f62e5bf6590dd3959f11049b72510780c5
5
+ SHA512:
6
+ metadata.gz: 00e3916c10baad4f0a2704b6faad9ba93f6228b79f42bb0ea3ede0c4b10e0367a36188956b9e7151519eee97a9e4abda6e4f83966e51da5aea8b5261005ef2d3
7
+ data.tar.gz: bcda3a7c08938c2641505609183589ddb2f69ab5e471765d461725dcea0652b19ef1d175e0e443918f83e4346447c5734e7ebafd3ad29eff6126c1515843aa99
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Typescript
5
+ # module adding methods to access the config variables for this
6
+ # plugin from the users _config.yml.
7
+ #
8
+ # these methods are also expected to attach the default values for
9
+ # these options should they be unassigned.
10
+ #
11
+ module Config
12
+ def ts_extensions
13
+ @ts_extensions ||= Array(config['extensions']) || %w[.ts .tsx]
14
+ end
15
+
16
+ def copy_extensions
17
+ @copy_extensions ||= Array(config['copy_ext']) || []
18
+ end
19
+
20
+ def temp_dir
21
+ @temp_dir ||= config['temp_dir'] || '.typescript'
22
+ end
23
+
24
+ def tsc_command
25
+ @tsc_command ||= Array(config['command']) || ['tsc']
26
+ end
27
+
28
+ private
29
+
30
+ def config
31
+ @config ||= site.config['typescript']
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Typescript
5
+ # This class just makes jekyll change the extensions of any typescript
6
+ # files to .js.
7
+ #
8
+ # To see where the actual conversion takes place, see ./manager.rb
9
+ class TypescriptConverter < Jekyll::Converter
10
+ priority :low
11
+
12
+ def matches(ext)
13
+ Manager.instance.typescript_ext?(ext)
14
+ end
15
+
16
+ def output_ext(_)
17
+ '.js'
18
+ end
19
+
20
+ def convert(content)
21
+ content
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Typescript
5
+ # Generator to ensure Manager is aware of any typescript (or related)
6
+ # files it may need to process. This in affect forces typescript files
7
+ # to be processed, even when they lack front matter.
8
+ #
9
+ class TypescriptGenerator < Jekyll::Generator
10
+ def generate(site)
11
+ @site = site
12
+ Manager.instance.site ||= site
13
+ Manager.instance.static_files.clear
14
+
15
+ ts_files = []
16
+ site.static_files.each do |file|
17
+ if Manager.instance.typescript_file?(file)
18
+ ts_files << file
19
+ elsif Manager.instance.copy_file?(file)
20
+ Manager.instance.static_files << file
21
+ end
22
+ end
23
+
24
+ # turn any needed typescript files into regular pages.
25
+ site.static_files -= ts_files
26
+ site.pages += ts_files.map do |static_file|
27
+ base = static_file.instance_variable_get('@base')
28
+ dir = static_file.instance_variable_get('@dir')
29
+ name = static_file.instance_variable_get('@name')
30
+ Jekyll::Page.new(@site, base, dir, name)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,160 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'singleton'
4
+ require 'fileutils'
5
+ require 'shellwords'
6
+ require_relative './config'
7
+ require_relative './tsconfig'
8
+
9
+ module Jekyll
10
+ module Typescript
11
+ # manages typescript
12
+ class Manager
13
+ SyntaxError = Class.new(ArgumentError)
14
+
15
+ include ::Singleton
16
+ include Config
17
+ include TSConfig
18
+
19
+ # whether :ext is associated with a typescript extension.
20
+ #
21
+ def typescript_ext?(ext)
22
+ ts_extensions.include? ext
23
+ end
24
+
25
+ # whether :ext is associated with an extension tsc will need
26
+ # in the compilation directory, eg. .js
27
+ #
28
+ def copy_ext?(ext)
29
+ typescript_ext?(ext) || copy_extensions.include?(ext)
30
+ end
31
+
32
+ # whether :page has a typescript extension.
33
+ #
34
+ def typescript_file?(page)
35
+ typescript_ext? File.extname(page.name).downcase
36
+ end
37
+
38
+ # whether :page has a copy_file extension.
39
+ #
40
+ def copy_file?(page)
41
+ copy_ext? File.extname(page.name).downcase
42
+ end
43
+
44
+ def setup
45
+ unless @setup
46
+ FileUtils.mkdir_p(temp_dir)
47
+ @setup = true
48
+ end
49
+ end
50
+
51
+ def static_files
52
+ @static_files ||= []
53
+ end
54
+
55
+ attr_accessor :site, :pages
56
+
57
+ # Typescript hook run before the site is rendered. This is used to reset
58
+ # the typescript pages array and to assign the site instance used for the
59
+ # compilation.
60
+ #
61
+ def pre_render(site, _)
62
+ self.site = site
63
+ @pages = []
64
+ Jekyll.logger.debug('Typescript', 'clearing out temporary build directory.')
65
+ FileUtils.rm_rf(Dir.glob(File.join(temp_dir, '*')))
66
+ end
67
+
68
+ # Typescript hook run after a page has been rendered. This is used to add a
69
+ # a page to typescripts memory if that page is needed for typescript
70
+ # compilation.
71
+ #
72
+ def add_page(page)
73
+ @pages << page if copy_ext? page.ext
74
+ end
75
+
76
+ # Once all the site files have been processed, compile and replace the content
77
+ # of any typescript files.
78
+ #
79
+ def post_render(*args)
80
+ setup
81
+
82
+ populate_temp_dir
83
+ @pages.each do |page|
84
+ next unless typescript_ext? page.ext
85
+
86
+ # change the output extension. it's a hack... but it works so good enough.
87
+ page.send(:_renderer).instance_variable_set(:@output_ext, '.js')
88
+
89
+ command = compile_command(in_temp_dir(page.relative_path))
90
+ Jekyll.logger.debug('Typescript') {
91
+ "running compile command: #{Shellwords.join(command[1..])}" }
92
+ compile_output = IO.popen(command, &:read).chomp # spawn a cmd & read process output.
93
+
94
+ unless $?.success?
95
+ raise SyntaxError, "typescript failed to convert: #{page.path}\n" + compile_output
96
+ end
97
+
98
+ output_file = File.join(temp_dir,
99
+ File.dirname(page.relative_path),
100
+ File.basename(page.relative_path, '.*') + '.js')
101
+
102
+ page.output = File.open(output_file, 'r', &:read)
103
+ end
104
+ end
105
+
106
+ private
107
+
108
+ # return :path but from the typescript temporary directory.
109
+ #
110
+ def in_temp_dir(path)
111
+ File.join(temp_dir, path)
112
+ end
113
+
114
+ # copy all of the pages in pages to this plugins temporary directory.
115
+ #
116
+ def populate_temp_dir
117
+ Dir.chdir(temp_dir) do
118
+ (@pages + static_files).each do |page|
119
+
120
+ if page.is_a?(StaticFile)
121
+ FileUtils.mkdir_p('./' + page.instance_variable_get(:@dir))
122
+ FileUtils.copy(site.in_source_dir(page.relative_path),
123
+ './' + page.relative_path)
124
+ else
125
+ FileUtils.mkdir_p('./' + page.dir) # make temp container for file
126
+ File.open(page.relative_path, 'w') { |fd| fd.write(page.content) }
127
+ end
128
+ end
129
+ end
130
+ end
131
+
132
+ # get a tsc compile command for use with popen, append :args to the end of it.
133
+ #
134
+ def compile_command(*args)
135
+ [ENV, *tsc_command, '--pretty', '--rootDir', temp_dir, *tsconfig_args, *args]
136
+ end
137
+
138
+ # value of the tsconfig.json file as an array of command flags.
139
+ #
140
+ def tsconfig_args
141
+ unless @tsconfig_args
142
+ config_file = 'tsconfig.json'
143
+
144
+ @tsconfig_args = if File.exists?(config_file)
145
+ parse_tsconfig(dumb_read_json(config_file))
146
+ else
147
+ Jekyll.logger.warn('Typescript', "no config file found at #{config_file}")
148
+ []
149
+ end
150
+ end
151
+
152
+ @tsconfig_args
153
+ end
154
+
155
+ Jekyll::Hooks.register(:site, :pre_render, &instance.method(:pre_render))
156
+ Jekyll::Hooks.register(:pages, :post_render, &instance.method(:add_page))
157
+ Jekyll::Hooks.register(:site, :post_render, &instance.method(:post_render))
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Typescript
5
+ # Module providing methods to aid in the parsing of tsconfig.json files.
6
+ #
7
+ # WARN, some of this file is basically me ranting about how absurd tsc
8
+ # and some of the general web app standards are, as a Unix lover.
9
+ #
10
+ module TSConfig
11
+ # Parse a tsconfig.json JSON object into an array of equivalent commands
12
+ # line flags.
13
+ #
14
+ # For some dumb reason, tsc just outright ignores your tsconfig.json file
15
+ # when you're compiling a single file, instead of a project. See issue
16
+ # 6591 on Microsoft/Typescript.
17
+ #
18
+ def parse_tsconfig(json)
19
+ args = []
20
+ json['compilerOptions'].each_pair do |option, value|
21
+ flag = "--#{option}"
22
+
23
+ case value
24
+ when TrueClass, FalseClass
25
+ args << flag if value
26
+ when String
27
+ args << flag
28
+ args << value
29
+ when Array
30
+ args << flag
31
+ args << value.join(',')
32
+ else
33
+ Jekyll.logger.warn('Typescript',
34
+ "unknown option type for #{option} of type #{value.class}")
35
+ end
36
+ end
37
+ args
38
+ end
39
+
40
+ private
41
+
42
+ # read a json file at :path, but allow for comments in the file.
43
+ #
44
+ # RANT
45
+ # Why in the great stallmans name does everyone use JSON as a config
46
+ # format when it doesn't support comments?
47
+ #
48
+ # RANT
49
+ # Why in gods name does JSON forbid comments when their pretty much
50
+ # ubiquotous?
51
+ #
52
+ # Adding an option to most parsers to allow comments doesn't seem too
53
+ # unreasonable, I mean it's not like JSON is solely used as a web
54
+ # interchange format anymore.
55
+ #
56
+ def dumb_read_json(path)
57
+ File.open(path, 'r') do |file|
58
+ # regxp partially sourced from https://stackoverflow.com/questions/19910002/remove-comments-from-json-data
59
+ JSON.parse(file.read.gsub(/(?:\/\/[^\n]+$)|(?:\/\*(?:[^*]+|\*+(?!\/))*\*\/)/m, ''))
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Typescript
5
+ VERSION = '0.0.2'
6
+ end
7
+ end
data/lib/jekyll_tsc.rb ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './jekyll/typescript/manager'
4
+ require_relative './jekyll//typescript/generator'
5
+ require_relative './jekyll/typescript/converter'
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jekyll-tsc
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Mohsin Kaleem
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-02-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: jekyll
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.8'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.8'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.17.2
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.17.2
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.9'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.9'
55
+ description: |
56
+ provides automatic compilation of typescript files to javascript
57
+ files for your jekyll blog.
58
+ email: mohkalsin@gmail.com
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - lib/jekyll/typescript/config.rb
64
+ - lib/jekyll/typescript/converter.rb
65
+ - lib/jekyll/typescript/generator.rb
66
+ - lib/jekyll/typescript/manager.rb
67
+ - lib/jekyll/typescript/tsconfig.rb
68
+ - lib/jekyll/typescript/version.rb
69
+ - lib/jekyll_tsc.rb
70
+ homepage:
71
+ licenses:
72
+ - MIT
73
+ metadata: {}
74
+ post_install_message:
75
+ rdoc_options: []
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ requirements: []
89
+ rubygems_version: 3.0.3
90
+ signing_key:
91
+ specification_version: 4
92
+ summary: compile typescript files on your jekyll blog.
93
+ test_files: []