如何读取 Base64 VLQ 代码



我试图了解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:'))))

最新更新