|  | 
| 1 |  | -import postcss from 'postcss' | 
| 2 |  | -import replaceSymbols, {replaceAll} from 'icss-replace-symbols' | 
|  | 1 | +'use strict'; | 
| 3 | 2 | 
 | 
| 4 |  | -const matchImports = /^(.+?|\([\s\S]+?\))\s+from\s+("[^"]*"|'[^']*'|[\w-]+)$/ | 
| 5 |  | -const matchValueDefinition = /(?:\s+|^)([\w-]+):?\s+(.+?)\s*$/g | 
| 6 |  | -const matchImport = /^([\w-]+)(?:\s+as\s+([\w-]+))?/ | 
| 7 |  | -let options = {} | 
| 8 |  | -let importIndex = 0 | 
| 9 |  | -let createImportedName = options && options.createImportedName || ((importName/*, path*/) => `i__const_${importName.replace(/\W/g, '_')}_${importIndex++}`) | 
|  | 3 | +const postcss = require('postcss'); | 
|  | 4 | +const ICSSReplaceSymbols = require('icss-replace-symbols'); | 
|  | 5 | +const replaceSymbols = require('icss-replace-symbols'); | 
| 10 | 6 | 
 | 
| 11 |  | -export default postcss.plugin('postcss-modules-values', () => (css, result) => { | 
| 12 |  | -  let importAliases = [] | 
| 13 |  | -  let definitions = {} | 
|  | 7 | +const matchImports = /^(.+?|\([\s\S]+?\))\s+from\s+("[^"]*"|'[^']*'|[\w-]+)$/; | 
|  | 8 | +const matchValueDefinition = /(?:\s+|^)([\w-]+):?\s+(.+?)\s*$/g; | 
|  | 9 | +const matchImport = /^([\w-]+)(?:\s+as\s+([\w-]+))?/; | 
| 14 | 10 | 
 | 
| 15 |  | -  const addDefinition = atRule => { | 
| 16 |  | -    let matches | 
| 17 |  | -    while (matches = matchValueDefinition.exec(atRule.params)) { | 
| 18 |  | -      let [/*match*/, key, value] = matches | 
| 19 |  | -      // Add to the definitions, knowing that values can refer to each other | 
| 20 |  | -      definitions[key] = replaceAll(definitions, value) | 
| 21 |  | -      atRule.remove() | 
| 22 |  | -    } | 
| 23 |  | -  } | 
|  | 11 | +let options = {}; | 
|  | 12 | +let importIndex = 0; | 
|  | 13 | +let createImportedName = | 
|  | 14 | +  (options && options.createImportedName) || | 
|  | 15 | +  ((importName /*, path*/) => | 
|  | 16 | +    `i__const_${importName.replace(/\W/g, '_')}_${importIndex++}`); | 
| 24 | 17 | 
 | 
| 25 |  | -  const addImport = atRule => { | 
| 26 |  | -    let matches = matchImports.exec(atRule.params) | 
| 27 |  | -    if (matches) { | 
| 28 |  | -      let [/*match*/, aliases, path] = matches | 
| 29 |  | -      // We can use constants for path names | 
| 30 |  | -      if (definitions[path]) path = definitions[path] | 
| 31 |  | -      let imports = aliases.replace(/^\(\s*([\s\S]+)\s*\)$/, '$1').split(/\s*,\s*/).map(alias => { | 
| 32 |  | -        let tokens = matchImport.exec(alias) | 
| 33 |  | -        if (tokens) { | 
| 34 |  | -          let [/*match*/, theirName, myName = theirName] = tokens | 
| 35 |  | -          let importedName = createImportedName(myName) | 
| 36 |  | -          definitions[myName] = importedName | 
| 37 |  | -          return { theirName, importedName } | 
| 38 |  | -        } else { | 
| 39 |  | -          throw new Error(`@import statement "${alias}" is invalid!`) | 
| 40 |  | -        } | 
| 41 |  | -      }) | 
| 42 |  | -      importAliases.push({ path, imports }) | 
| 43 |  | -      atRule.remove() | 
| 44 |  | -    } | 
| 45 |  | -  } | 
|  | 18 | +module.exports = postcss.plugin( | 
|  | 19 | +  'postcss-modules-values', | 
|  | 20 | +  () => (css, result) => { | 
|  | 21 | +    const importAliases = []; | 
|  | 22 | +    const definitions = {}; | 
| 46 | 23 | 
 | 
| 47 |  | -  /* Look at all the @value statements and treat them as locals or as imports */ | 
| 48 |  | -  css.walkAtRules('value', atRule => { | 
| 49 |  | -    if (matchImports.exec(atRule.params)) { | 
| 50 |  | -      addImport(atRule) | 
| 51 |  | -    } else { | 
| 52 |  | -      if (atRule.params.indexOf('@value') !== -1) { | 
| 53 |  | -        result.warn('Invalid value definition: ' + atRule.params) | 
|  | 24 | +    const addDefinition = atRule => { | 
|  | 25 | +      let matches; | 
|  | 26 | +      while ((matches = matchValueDefinition.exec(atRule.params))) { | 
|  | 27 | +        let [, /*match*/ key, value] = matches; | 
|  | 28 | +        // Add to the definitions, knowing that values can refer to each other | 
|  | 29 | +        definitions[key] = replaceSymbols.replaceAll(definitions, value); | 
|  | 30 | +        atRule.remove(); | 
| 54 | 31 |       } | 
|  | 32 | +    }; | 
| 55 | 33 | 
 | 
| 56 |  | -      addDefinition(atRule) | 
| 57 |  | -    } | 
| 58 |  | -  }) | 
|  | 34 | +    const addImport = atRule => { | 
|  | 35 | +      const matches = matchImports.exec(atRule.params); | 
|  | 36 | +      if (matches) { | 
|  | 37 | +        let [, /*match*/ aliases, path] = matches; | 
|  | 38 | +        // We can use constants for path names | 
|  | 39 | +        if (definitions[path]) { | 
|  | 40 | +          path = definitions[path]; | 
|  | 41 | +        } | 
|  | 42 | +        const imports = aliases | 
|  | 43 | +          .replace(/^\(\s*([\s\S]+)\s*\)$/, '$1') | 
|  | 44 | +          .split(/\s*,\s*/) | 
|  | 45 | +          .map(alias => { | 
|  | 46 | +            const tokens = matchImport.exec(alias); | 
|  | 47 | +            if (tokens) { | 
|  | 48 | +              const [, /*match*/ theirName, myName = theirName] = tokens; | 
|  | 49 | +              const importedName = createImportedName(myName); | 
|  | 50 | +              definitions[myName] = importedName; | 
|  | 51 | +              return { theirName, importedName }; | 
|  | 52 | +            } else { | 
|  | 53 | +              throw new Error(`@import statement "${alias}" is invalid!`); | 
|  | 54 | +            } | 
|  | 55 | +          }); | 
|  | 56 | +        importAliases.push({ path, imports }); | 
|  | 57 | +        atRule.remove(); | 
|  | 58 | +      } | 
|  | 59 | +    }; | 
| 59 | 60 | 
 | 
| 60 |  | -  /* We want to export anything defined by now, but don't add it to the CSS yet or | 
|  | 61 | +    /* Look at all the @value statements and treat them as locals or as imports */ | 
|  | 62 | +    css.walkAtRules('value', atRule => { | 
|  | 63 | +      if (matchImports.exec(atRule.params)) { | 
|  | 64 | +        addImport(atRule); | 
|  | 65 | +      } else { | 
|  | 66 | +        if (atRule.params.indexOf('@value') !== -1) { | 
|  | 67 | +          result.warn('Invalid value definition: ' + atRule.params); | 
|  | 68 | +        } | 
|  | 69 | + | 
|  | 70 | +        addDefinition(atRule); | 
|  | 71 | +      } | 
|  | 72 | +    }); | 
|  | 73 | + | 
|  | 74 | +    /* We want to export anything defined by now, but don't add it to the CSS yet or | 
| 61 | 75 |    it well get picked up by the replacement stuff */ | 
| 62 |  | -  let exportDeclarations = Object.keys(definitions).map(key => postcss.decl({ | 
| 63 |  | -    value: definitions[key], | 
| 64 |  | -    prop: key, | 
| 65 |  | -    raws: { before: "\n  " } | 
| 66 |  | -  })) | 
|  | 76 | +    const exportDeclarations = Object.keys(definitions).map(key => | 
|  | 77 | +      postcss.decl({ | 
|  | 78 | +        value: definitions[key], | 
|  | 79 | +        prop: key, | 
|  | 80 | +        raws: { before: '\n  ' } | 
|  | 81 | +      }) | 
|  | 82 | +    ); | 
| 67 | 83 | 
 | 
| 68 |  | -  /* If we have no definitions, don't continue */ | 
| 69 |  | -  if (!Object.keys(definitions).length) return | 
|  | 84 | +    /* If we have no definitions, don't continue */ | 
|  | 85 | +    if (!Object.keys(definitions).length) { | 
|  | 86 | +      return; | 
|  | 87 | +    } | 
| 70 | 88 | 
 | 
| 71 |  | -  /* Perform replacements */ | 
| 72 |  | -  replaceSymbols(css, definitions) | 
|  | 89 | +    /* Perform replacements */ | 
|  | 90 | +    ICSSReplaceSymbols.default(css, definitions); | 
| 73 | 91 | 
 | 
| 74 |  | -  /* Add export rules if any */ | 
| 75 |  | -  if (exportDeclarations.length > 0) { | 
| 76 |  | -    let exportRule = postcss.rule({ | 
| 77 |  | -      selector: `:export`, | 
| 78 |  | -      raws: { after: "\n" } | 
| 79 |  | -    }) | 
| 80 |  | -    exportRule.append(exportDeclarations) | 
| 81 |  | -    css.prepend(exportRule) | 
| 82 |  | -  } | 
|  | 92 | +    /* Add export rules if any */ | 
|  | 93 | +    if (exportDeclarations.length > 0) { | 
|  | 94 | +      const exportRule = postcss.rule({ | 
|  | 95 | +        selector: ':export', | 
|  | 96 | +        raws: { after: '\n' } | 
|  | 97 | +      }); | 
|  | 98 | +      exportRule.append(exportDeclarations); | 
|  | 99 | +      css.prepend(exportRule); | 
|  | 100 | +    } | 
| 83 | 101 | 
 | 
| 84 |  | -  /* Add import rules */ | 
| 85 |  | -  importAliases.reverse().forEach(({ path, imports }) => { | 
| 86 |  | -    let importRule = postcss.rule({ | 
| 87 |  | -      selector: `:import(${path})`, | 
| 88 |  | -      raws: { after: "\n" } | 
| 89 |  | -    }) | 
| 90 |  | -    imports.forEach(({ theirName, importedName }) => { | 
| 91 |  | -      importRule.append({ | 
| 92 |  | -        value: theirName, | 
| 93 |  | -        prop: importedName, | 
| 94 |  | -        raws: { before: "\n  " } | 
| 95 |  | -      }) | 
| 96 |  | -    }) | 
|  | 102 | +    /* Add import rules */ | 
|  | 103 | +    importAliases.reverse().forEach(({ path, imports }) => { | 
|  | 104 | +      const importRule = postcss.rule({ | 
|  | 105 | +        selector: `:import(${path})`, | 
|  | 106 | +        raws: { after: '\n' } | 
|  | 107 | +      }); | 
|  | 108 | +      imports.forEach(({ theirName, importedName }) => { | 
|  | 109 | +        importRule.append({ | 
|  | 110 | +          value: theirName, | 
|  | 111 | +          prop: importedName, | 
|  | 112 | +          raws: { before: '\n  ' } | 
|  | 113 | +        }); | 
|  | 114 | +      }); | 
| 97 | 115 | 
 | 
| 98 |  | -    css.prepend(importRule) | 
| 99 |  | -  }) | 
| 100 |  | -}) | 
|  | 116 | +      css.prepend(importRule); | 
|  | 117 | +    }); | 
|  | 118 | +  } | 
|  | 119 | +); | 
0 commit comments