10

我试图了解 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]

这些价值观是什么?

4

3 回答 3

3

我在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 列。

于 2013-11-20T23:04:21.020 回答
1

尽管我能找到一些例子,但我花了很长时间才了解编码/解码的真正工作原理。所以我认为我最好通过尝试以非常明确的方式一步一步地自己制作一些东西来学习。我从这个博客上对 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:'))))
于 2016-04-09T09:24:01.227 回答
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:sourceMapping 输出的“sources”数组中对应的源文件索引
  • n3:原始代码中的行号
  • n4:原始代码中的列号

我们从一开始就已经知道这指的是哪一行。所以使用我们上面的信息,我们了解到:

  • AAAA:生成代码的第 2 行第 1 列指向源 [0],第 0 行,第 0 列
  • IAAM:第 2 行,第 4 列生成的代码指向源 [0],第 0 行,第 6 列
  • WAAW:第 2 行,第 15 列生成的代码指向源 [0],第 0 行,第 17 列 ...

关于这个的两个很好的来源:

于 2020-11-20T19:55:04.703 回答