我试图了解css源映射的工作原理。我创建了一个非常简单的scss文件。
#navbar {
color: black;
}
当我编译上面的scss时,我得到以下地图文件。
{
"version": "3",
"mappings": "AAAA,OAAQ;EACP,KAAK,EAAE,KAAK",
"sources": ["test.scss"],
"file": "test.css"
}
当我解码"映射"时,我得到以下值。
0) [0,0,0,0], [7,0,0,8]
1) [2,0,1,-7], [5,0,0,5], [2,0,0,2], [5,0,0,5]
这些价值观是什么?
我在 http://www.thecssninja.com/javascript/source-mapping 的"Base64 VLQ 并保持源映射较小"部分下找到了一个例子。
上图 AAgBC 一旦进一步处理,将返回 0、0、32、16、1 – 32 是有助于构建以下值 16 的延续位。纯粹在 Base64 中解码的 B 是 1。因此,使用的重要值是 0、0、16、1。然后,这让我们知道生成的文件的第 1 行(行由分号保持计数(第 0 列映射到文件 0(文件数组 0 是 foo.js(,第 16 行在第 1 列。
即使在阅读了答案之后,我仍然不清楚解释。以下是简单的英语解释,以防它对某人有所帮助:
像;;AAAA,IAAM,WAAW,SAAX;...
这样的东西意味着<line0 info>;<line1 info>;...
所以对于;;AAAA;IAAM,WAAW,SAAX;...
,第 0 行和第 1 行没有任何重要信息(空格等(
那么对于第 2 行,我们有AAAA,IAAM,WAAW,SAAX
我们使用 base64 字符映射将这些组中的每一个转换为二进制:
BASE64_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
所以我们基本上在上面的这个BASE64_ALPHABET
中找到索引,并将索引转换为 6 位二进制(6 位,因为我们使用 base64(。 例如,A 的索引为 0,因此在 6 位二进制文件中为 000000。 所以AAAA将是000000 000000 000000 000000
然后,如果我们用IAAM
这样做,我们会得到: 001000 000000 000000 001100
.
那么这个位表示是 4 个数字的 VLQ 编码版本。 我们从左块开始,删除符号和延续位,保留位。 并在延续位为 1 时继续添加它位。
eg. 001000 is (cont)0100(sign)
so cont = 0 (no other block will be added to this number)
sign=0 (its positive)
bits = 0100 --> so it is 4 in decimal
-- note that we only remove sign bit for the first time. so if we had
101000 001000
we would say
0100 (cont=1, sign=0) 01000 (cont=0)
so we would have had +010001000 = 136
当我们继续这样做时,我们将得到这 4 个数字(延续位应该正好是 0 4 次(。
- AAAA 将映射到 (0,0,0,0(
- IAAM 将映射到 (4,0,0,6(
- WAAW 将映射到 (11,0,0,11(...
现在,这些中的每一个都意味着相对数字。 所以我们纠正这些:
- AAAA实际上指向:(0,0,0,0( IAAM 实际上指向:(0+4, 0+0, 0+
- 0, 0+6( = (4,0,0,6(
- WAAW 实际上指向:(4+11, 0+0, 0+0, 6+11( = (15,0,0,17(//我们在 IAAAM 实际指向的地方添加了它
。
所以这里的数字(N1,N2,N3,N4(代表
- N1:生成的代码中的列
- n2:源映射输出的"源"数组中对应的源文件索引
- N3:原始代码中的行号
- N4:原始代码中的列号
我们从一开始就已经知道这指的是哪一行。 因此,使用我们上面的信息,我们了解到:
- AAAA:生成的代码的第 2 行,第 1 列指向源代码 [0],第 0 行,第 0 列
- IAAM:生成的代码的第 2 行,第 4 列指向源代码 [0],第 0 行,第 6 列
- WAAW:生成的代码的第 2 行,第 15 列指向源代码 [0],第 0 行,第 17 列...
关于这一点的两个很好的来源:
- 有关 VLQ 编码的更多信息
- 更多关于如何解释/解码的信息
尽管我可以找到一些例子,但我花了相当长的时间来理解编码/解码的真正工作原理。所以我想我最好通过尝试自己以一种非常明确、循序渐进的方式制作一些东西来学习。我从这个博客上对VLQ的解释开始,
我使用以下 Python 函子为 Transcrypt 生成源映射。代码很简单,我认为可以很好地了解编码/解码原则上的工作原理。为了在简单的情况下实现速度,它会缓存前 256 个数字,这些数字最常用于生成 v3 源映射。
import math
class GetBase64Vlq:
def __init__ (self):
self.nBits32 = 5
self.encoding = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
self.prefabSize = 256
self.prefab = [self (i, True) for i in range (self.prefabSize)]
def __call__ (self, anInteger, init = False):
if not init and 0 < anInteger < self.prefabSize:
return self.prefab [anInteger]
else:
signed = bin (abs (anInteger)) [2 : ] + ('1' if anInteger < 0 else '0')
nChunks = math.ceil (len (signed) / float (self.nBits32))
padded = (self.nBits32 * '0' + signed) [-nChunks * self.nBits32 : ]
chunks = [('1' if iChunk else '0') + padded [iChunk * self.nBits32 : (iChunk + 1) * self.nBits32] for iChunk in range (nChunks - 1, -1, -1)]
return ''.join ([self.encoding [int (chunk, 2)] for chunk in chunks])
getBase64Vlq = GetBase64Vlq ()
使用示例:
while (True):
print (getBase64Vlq (int (input ('Give number:'))))