1
1
import { MultiMap , ObjectDictionary } from "@opticss/util" ;
2
- import * as crypto from "crypto" ;
3
- import * as debugGenerator from "debug" ;
4
2
import {
5
3
CompoundSelector ,
6
4
ParsedSelector ,
7
5
parseSelector ,
8
6
postcss ,
9
7
postcssSelectorParser as selectorParser ,
10
8
} from "opticss" ;
11
- import * as process from "process" ;
12
9
13
10
import { isAttributeNode , isClassNode } from "../BlockParser" ;
14
11
import { isRootNode , toAttrToken } from "../BlockParser" ;
@@ -22,31 +19,25 @@ import { BlockClass } from "./BlockClass";
22
19
import { Inheritable } from "./Inheritable" ;
23
20
import { Styles } from "./Styles" ;
24
21
25
- const DEBUG = debugGenerator ( "css-blocks:caching" ) ;
26
-
27
22
/**
28
- * Generates a 5 digit, unique identifier from a given input identifier. This
29
- * generated identifier hash will remain consistent for the tuple of (machine,
30
- * user, css blocks installation location).
31
- * @param identifier Input Block identifier.
32
- * @returns This Block's guid hash.
23
+ * In-memory representation of a Block. If you're thinking of CSS Blocks
24
+ * in relation to the BEM architecture for CSS, this is the... well... "Block".
25
+ * Well, with a slight caveat....
26
+ *
27
+ * The Block is always the root node of a BlockTree. The Block may be the
28
+ * parent to any number of BlockClass nodes. Notably, the Block class only
29
+ * stores meta information about the block. Any CSS properties assigned to the
30
+ * `:scope` selector are stored on a special BlockClass node that is a child of
31
+ * the Block. You can access this node directly through the
32
+ * `rootClass` property.
33
+ *
34
+ * Block nodes store all data related to any `@block` imports, the
35
+ * `block-name`, implemented Blocks, the inherited Block, and any other
36
+ * metadata stored in the Block file.
33
37
*/
34
- function gen_guid ( identifier : string ) : string {
35
- let hash = crypto . createHash ( "md5" )
36
- . update ( process . getuid ( ) . toString ( ) )
37
- . update ( __filename )
38
- . update ( identifier )
39
- . digest ( "hex" )
40
- . slice ( 0 , 5 ) ;
41
- DEBUG ( "guid is %s for %s" , hash , identifier ) ;
42
- return hash ;
43
- }
44
-
45
38
export class Block
46
39
extends Inheritable < Block , Block , never , BlockClass > {
47
40
48
- public static GUIDS_USED = new Map < string , string [ ] > ( ) ;
49
-
50
41
private _blockReferences : ObjectDictionary < Block > = { } ;
51
42
private _blockReferencesReverseLookup : Map < Block , string > = new Map ( ) ;
52
43
private _blockExports : ObjectDictionary < Block > = { } ;
@@ -56,6 +47,14 @@ export class Block
56
47
private _blockErrors : CssBlockError [ ] = [ ] ;
57
48
private hasHadNameReset = false ;
58
49
50
+ /**
51
+ * A unique identifier for this Block. Generally created from a hash
52
+ * of the FileIdentifier and other process information.
53
+ *
54
+ * For caching to work properly, this GUID must be unique to the block and
55
+ * shouldn't change between recompiles. You shouldn't use file contents to
56
+ * create this hash.
57
+ */
59
58
public readonly guid : string ;
60
59
61
60
/**
@@ -65,52 +64,36 @@ export class Block
65
64
*/
66
65
private _dependencies : Set < string > ;
67
66
67
+ /**
68
+ * A direct reference to the BlockClass that holds style information for the
69
+ * `:scope` selector of this Block. The rootClass is also available through
70
+ * other traversal methods, as you would access any other BlockClass that
71
+ * belongs to this Block.
72
+ */
68
73
public readonly rootClass : BlockClass ;
74
+
75
+ /**
76
+ * The PostCSS AST of the stylesheet this Block was built from. Used
77
+ * primarily for error reporting, if present.
78
+ */
69
79
public stylesheet : postcss . Root | undefined ;
70
80
71
- constructor ( name : string , identifier : FileIdentifier , stylesheet ?: postcss . Root , incomingGuid ?: string ) {
81
+ /**
82
+ * Creates a new Block.
83
+ *
84
+ * @param name - The default name for this block. This can be reset once (and only once)
85
+ * using the `setName()` method.
86
+ * @param identifier - An unique ID referencing the file/blob this Block is created from.
87
+ * @param guid - The GUID for this block. This GUID should be unique. (BlockFactory is
88
+ * responsible for enforcing uniqueness.)
89
+ * @param stylesheet - The PostCSS AST of the stylesheet this block is built from.
90
+ */
91
+ constructor ( name : string , identifier : FileIdentifier , guid : string , stylesheet ?: postcss . Root ) {
72
92
super ( name ) ;
73
93
this . _identifier = identifier ;
74
94
this . _dependencies = new Set < string > ( ) ;
75
95
this . rootClass = new BlockClass ( ROOT_CLASS , this ) ;
76
96
this . stylesheet = stylesheet ;
77
-
78
- // If we found a GUID from the :scope rule, use that. Otherwise, generate one.
79
- let guid = incomingGuid || gen_guid ( identifier ) ;
80
-
81
- // We insist that each block have a unique GUID. In the event that we've somehow
82
- // ended up with two blocks that have the same GUID, our options depend on whether
83
- // we got a preset GUID passed in or not.
84
- if ( Block . GUIDS_USED . has ( guid ) ) {
85
- if ( incomingGuid ) {
86
- // If the GUID was already generated prior to creating the block, we have to
87
- // bail out. (There's likely Compiled CSS that depends on that GUID.)
88
- throw new CssBlockError ( "Block uses a GUID that has already been used!" , {
89
- filename : identifier ,
90
- } ) ;
91
- } else {
92
- // Ok, we autogenerated this. Let's append some gobbledygook to recover.
93
- const guidBaseList = Block . GUIDS_USED . get ( guid ) ;
94
- if ( ! guidBaseList ) {
95
- // Ah crumbs. There should be a list but there isn't.
96
- throw new CssBlockError ( "Block uses a GUID that has already been used!" , {
97
- filename : identifier ,
98
- } ) ;
99
- }
100
- guid = `${ guid } ${ guidBaseList . length } ` ;
101
- if ( guidBaseList . includes ( guid ) || Block . GUIDS_USED . has ( guid ) ) {
102
- // Ah crumbs. Our safety check to make sure the GUID really hasn't been used failed.
103
- throw new CssBlockError ( "Block uses a GUID that has already been used!" , {
104
- filename : identifier ,
105
- } ) ;
106
- }
107
- // Phew, okay, appending a numerical id works. Let's go with that.
108
- guidBaseList . push ( guid ) ;
109
- }
110
- } else {
111
- // Hey, this is unique! Cool, let's remember it in case we see it again later.
112
- Block . GUIDS_USED . set ( guid , [ ] ) ;
113
- }
114
97
this . guid = guid ;
115
98
116
99
this . addClass ( this . rootClass ) ;
0 commit comments