importmap-plus 2.0.0 → 2.0.1
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/CHANGELOG.md +14 -0
- data/lib/importmap/import_scanner.rb +17 -6
- data/lib/importmap/module_inspector.rb +13 -2
- data/lib/importmap/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1d0e4b656e7047b77938a8b92681f72ec7af73034c2c94517ef2ff37d725b76d
|
|
4
|
+
data.tar.gz: 9a83c644e76fab4892e074ea8f254877b4351c55b071294f4edd3c965167054f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 39c36fbd0719746f4ca30e21632731f1d91ebc4e524132c2592b2d0a1432315cf8e2d3e7b70fffa935cbc4d3135a14d561dd86d52c6de3a18fd41030f91209a1
|
|
7
|
+
data.tar.gz: c9eaf6a0f2b07be30f46487d07ffa17ebaa538efd443d23d677fd8e95509b4d50b193162a136dec8d9d6888b5414cbfe7b832d0929b0d0f9d6373de35ad2f0bf
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **`bin/importmap doctor` no longer reports comments and prose as unpinned
|
|
8
|
+
imports.** The import scanner read `from "…"` and `import "…"` wherever the
|
|
9
|
+
text appeared, so a line comment such as `// e.g. 'en' from 'en-US'` and
|
|
10
|
+
strings such as turbo_power's `` `…provided in the "from" attribute for
|
|
11
|
+
the "…` `` came back as `error … imports " attribute for the ", which isn't
|
|
12
|
+
pinned`. Line comments are now discounted before scanning (strings and
|
|
13
|
+
regex literals are still consumed whole, so `"https://…"` is safe), and a
|
|
14
|
+
quoted text that can't be a module specifier — whitespace, a backtick, a
|
|
15
|
+
`${` interpolation, or no word character at all — is not reported.
|
|
16
|
+
|
|
3
17
|
## 1.2.0
|
|
4
18
|
|
|
5
19
|
### Added
|
|
@@ -6,16 +6,19 @@ require "importmap/module_inspector"
|
|
|
6
6
|
#
|
|
7
7
|
# Like Importmap::ModuleInspector and Importmap::PackageGraph::IMPORT_REGEXP
|
|
8
8
|
# this reads the source with regexes rather than parsing JavaScript, so an
|
|
9
|
-
# import statement spelled out inside a string literal is reported too
|
|
10
|
-
#
|
|
9
|
+
# import statement spelled out inside a string literal is reported too — unless
|
|
10
|
+
# what it names can't be a module specifier at all — and a form the regexp
|
|
11
|
+
# can't read — a magic comment between the keyword and the
|
|
11
12
|
# specifier, a specifier built at runtime — isn't reported at all. Both
|
|
12
13
|
# mistakes are the cautious direction for the one caller: a specifier reported
|
|
13
14
|
# that the browser never asks for costs a pin, and a specifier missed leaves
|
|
14
15
|
# the app exactly as broken as it was before anyone ran the check.
|
|
15
16
|
#
|
|
16
|
-
#
|
|
17
|
-
# published bundle is
|
|
18
|
-
#
|
|
17
|
+
# Comments are discounted first, through
|
|
18
|
+
# ModuleInspector#code_without_line_comments, because a published bundle is
|
|
19
|
+
# full of `/** @typedef {import('./slide.js').Slide} */` — type annotations
|
|
20
|
+
# naming files the package never loads — and app code is full of prose like
|
|
21
|
+
# `// 'en' from 'en-US'`.
|
|
19
22
|
class Importmap::ImportScanner
|
|
20
23
|
Import = Struct.new(:specifier, :kind, keyword_init: true) # :nodoc:
|
|
21
24
|
|
|
@@ -38,6 +41,12 @@ class Importmap::ImportScanner
|
|
|
38
41
|
(?:from|import)\s*(["'])([^"'\n]*)\3
|
|
39
42
|
)
|
|
40
43
|
/x.freeze # :nodoc:
|
|
44
|
+
# What a quoted `from "…"` or `import "…"` has to hold to name a module
|
|
45
|
+
# rather than be prose the regexp above found in a string: something, no
|
|
46
|
+
# whitespace or backtick, no `${` interpolation, and at least one word
|
|
47
|
+
# character — `"from" attribute for the "`, `["import",","]` and
|
|
48
|
+
# `` `import("${url}")` `` are all strings, never specifiers.
|
|
49
|
+
SPECIFIER_REGEXP = /\A(?!.*\$\{)[^\s`]*\w[^\s`]*\z/.freeze # :nodoc:
|
|
41
50
|
|
|
42
51
|
attr_reader :source
|
|
43
52
|
|
|
@@ -46,7 +55,9 @@ class Importmap::ImportScanner
|
|
|
46
55
|
end
|
|
47
56
|
|
|
48
57
|
def imports
|
|
49
|
-
@imports ||= Importmap::ModuleInspector.new(source).
|
|
58
|
+
@imports ||= Importmap::ModuleInspector.new(source).code_without_line_comments.scan(IMPORT_REGEXP).filter_map do |_, dynamic, _, static|
|
|
59
|
+
next unless (dynamic || static).match?(SPECIFIER_REGEXP)
|
|
60
|
+
|
|
50
61
|
dynamic ? Import.new(specifier: dynamic, kind: :dynamic) : Import.new(specifier: static, kind: :static)
|
|
51
62
|
end
|
|
52
63
|
end
|
|
@@ -144,6 +144,14 @@ class Importmap::ModuleInspector
|
|
|
144
144
|
@code ||= without_block_comments
|
|
145
145
|
end
|
|
146
146
|
|
|
147
|
+
# #code with its line comments discounted too, for Importmap::ImportScanner:
|
|
148
|
+
# prose such as `// e.g. 'en' from 'en-US'` reads as an import otherwise.
|
|
149
|
+
# Strings and regex literals are still consumed whole first, so the `//` of
|
|
150
|
+
# `"https://…"` or `/\/\//` never opens a comment.
|
|
151
|
+
def code_without_line_comments
|
|
152
|
+
@code_without_line_comments ||= without_block_comments(line_comments: true)
|
|
153
|
+
end
|
|
154
|
+
|
|
147
155
|
private
|
|
148
156
|
def statements
|
|
149
157
|
@statements ||= without_block_comments(statements_only: true)
|
|
@@ -170,12 +178,15 @@ class Importmap::ModuleInspector
|
|
|
170
178
|
# reads as an import statement while the text inside it stops being read
|
|
171
179
|
# as code at all. That mode feeds only the ES-module check, where the
|
|
172
180
|
# `[//]` trap above can at worst send a package on to the next CDN.
|
|
173
|
-
|
|
181
|
+
# With +line_comments+ alone they go but literals are kept, for the import
|
|
182
|
+
# scanner: the trap there can at worst miss an import in the doctor's
|
|
183
|
+
# report, where prose in a comment is a false error on every run.
|
|
184
|
+
def without_block_comments(statements_only: false, line_comments: statements_only)
|
|
174
185
|
scanner = StringScanner.new(source)
|
|
175
186
|
kept = +""
|
|
176
187
|
|
|
177
188
|
until scanner.eos?
|
|
178
|
-
if scanner.skip(BLOCK_COMMENT_REGEXP) || (
|
|
189
|
+
if scanner.skip(BLOCK_COMMENT_REGEXP) || (line_comments && scanner.skip(LINE_COMMENT_REGEXP))
|
|
179
190
|
next
|
|
180
191
|
elsif (literal = scanner.scan(STRING_REGEXP)) ||
|
|
181
192
|
(regexp_literal_next?(kept, scanner) && (literal = scanner.scan(REGEXP_LITERAL_REGEXP)))
|
data/lib/importmap/version.rb
CHANGED