node.d.ts 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. import AtRule = require('./at-rule.js')
  2. import { AtRuleProps } from './at-rule.js'
  3. import Comment, { CommentProps } from './comment.js'
  4. import Container, { NewChild } from './container.js'
  5. import CssSyntaxError from './css-syntax-error.js'
  6. import Declaration, { DeclarationProps } from './declaration.js'
  7. import Document from './document.js'
  8. import Input from './input.js'
  9. import { Stringifier, Syntax } from './postcss.js'
  10. import Result from './result.js'
  11. import Root from './root.js'
  12. import Rule, { RuleProps } from './rule.js'
  13. import Warning, { WarningOptions } from './warning.js'
  14. declare namespace Node {
  15. export type ChildNode = AtRule.default | Comment | Declaration | Rule
  16. export type AnyNode =
  17. | AtRule.default
  18. | Comment
  19. | Declaration
  20. | Document
  21. | Root
  22. | Rule
  23. export type ChildProps =
  24. | AtRuleProps
  25. | CommentProps
  26. | DeclarationProps
  27. | RuleProps
  28. export interface Position {
  29. /**
  30. * Source line in file. In contrast to `offset` it starts from 1.
  31. */
  32. column: number
  33. /**
  34. * Source column in file.
  35. */
  36. line: number
  37. /**
  38. * Source offset in file. It starts from 0.
  39. */
  40. offset: number
  41. }
  42. export interface Range {
  43. /**
  44. * End position, exclusive.
  45. */
  46. end: Position
  47. /**
  48. * Start position, inclusive.
  49. */
  50. start: Position
  51. }
  52. /**
  53. * Source represents an interface for the {@link Node.source} property.
  54. */
  55. export interface Source {
  56. /**
  57. * The inclusive ending position for the source
  58. * code of a node.
  59. *
  60. * However, `end.offset` of a non `Root` node is the exclusive position.
  61. * See https://github.com/postcss/postcss/pull/1879 for details.
  62. *
  63. * ```js
  64. * const root = postcss.parse('a { color: black }')
  65. * const a = root.first
  66. * const color = a.first
  67. *
  68. * // The offset of `Root` node is the inclusive position
  69. * css.source.end // { line: 1, column: 19, offset: 18 }
  70. *
  71. * // The offset of non `Root` node is the exclusive position
  72. * a.source.end // { line: 1, column: 18, offset: 18 }
  73. * color.source.end // { line: 1, column: 16, offset: 16 }
  74. * ```
  75. */
  76. end?: Position
  77. /**
  78. * The source file from where a node has originated.
  79. */
  80. input: Input
  81. /**
  82. * The inclusive starting position for the source
  83. * code of a node.
  84. */
  85. start?: Position
  86. }
  87. /**
  88. * Interface represents an interface for an object received
  89. * as parameter by Node class constructor.
  90. */
  91. export interface NodeProps {
  92. source?: Source
  93. }
  94. export interface NodeErrorOptions {
  95. /**
  96. * An ending index inside a node's string that should be highlighted as
  97. * source of error.
  98. */
  99. endIndex?: number
  100. /**
  101. * An index inside a node's string that should be highlighted as source
  102. * of error.
  103. */
  104. index?: number
  105. /**
  106. * Plugin name that created this error. PostCSS will set it automatically.
  107. */
  108. plugin?: string
  109. /**
  110. * A word inside a node's string, that should be highlighted as source
  111. * of error.
  112. */
  113. word?: string
  114. }
  115. // eslint-disable-next-line @typescript-eslint/no-shadow
  116. class Node extends Node_ {}
  117. export { Node as default }
  118. }
  119. /**
  120. * It represents an abstract class that handles common
  121. * methods for other CSS abstract syntax tree nodes.
  122. *
  123. * Any node that represents CSS selector or value should
  124. * not extend the `Node` class.
  125. */
  126. declare abstract class Node_ {
  127. /**
  128. * It represents parent of the current node.
  129. *
  130. * ```js
  131. * root.nodes[0].parent === root //=> true
  132. * ```
  133. */
  134. parent: Container | Document | undefined
  135. /**
  136. * It represents unnecessary whitespace and characters present
  137. * in the css source code.
  138. *
  139. * Information to generate byte-to-byte equal node string as it was
  140. * in the origin input.
  141. *
  142. * The properties of the raws object are decided by parser,
  143. * the default parser uses the following properties:
  144. *
  145. * * `before`: the space symbols before the node. It also stores `*`
  146. * and `_` symbols before the declaration (IE hack).
  147. * * `after`: the space symbols after the last child of the node
  148. * to the end of the node.
  149. * * `between`: the symbols between the property and value
  150. * for declarations, selector and `{` for rules, or last parameter
  151. * and `{` for at-rules.
  152. * * `semicolon`: contains true if the last child has
  153. * an (optional) semicolon.
  154. * * `afterName`: the space between the at-rule name and its parameters.
  155. * * `left`: the space symbols between `/*` and the comment’s text.
  156. * * `right`: the space symbols between the comment’s text
  157. * and <code>*&#47;</code>.
  158. * - `important`: the content of the important statement,
  159. * if it is not just `!important`.
  160. *
  161. * PostCSS filters out the comments inside selectors, declaration values
  162. * and at-rule parameters but it stores the origin content in raws.
  163. *
  164. * ```js
  165. * const root = postcss.parse('a {\n color:black\n}')
  166. * root.first.first.raws //=> { before: '\n ', between: ':' }
  167. * ```
  168. */
  169. raws: any
  170. /**
  171. * It represents information related to origin of a node and is required
  172. * for generating source maps.
  173. *
  174. * The nodes that are created manually using the public APIs
  175. * provided by PostCSS will have `source` undefined and
  176. * will be absent in the source map.
  177. *
  178. * For this reason, the plugin developer should consider
  179. * duplicating nodes as the duplicate node will have the
  180. * same source as the original node by default or assign
  181. * source to a node created manually.
  182. *
  183. * ```js
  184. * decl.source.input.from //=> '/home/ai/source.css'
  185. * decl.source.start //=> { line: 10, column: 2 }
  186. * decl.source.end //=> { line: 10, column: 12 }
  187. * ```
  188. *
  189. * ```js
  190. * // Incorrect method, source not specified!
  191. * const prefixed = postcss.decl({
  192. * prop: '-moz-' + decl.prop,
  193. * value: decl.value
  194. * })
  195. *
  196. * // Correct method, source is inherited when duplicating.
  197. * const prefixed = decl.clone({
  198. * prop: '-moz-' + decl.prop
  199. * })
  200. * ```
  201. *
  202. * ```js
  203. * if (atrule.name === 'add-link') {
  204. * const rule = postcss.rule({
  205. * selector: 'a',
  206. * source: atrule.source
  207. * })
  208. *
  209. * atrule.parent.insertBefore(atrule, rule)
  210. * }
  211. * ```
  212. */
  213. source?: Node.Source
  214. /**
  215. * It represents type of a node in
  216. * an abstract syntax tree.
  217. *
  218. * A type of node helps in identification of a node
  219. * and perform operation based on it's type.
  220. *
  221. * ```js
  222. * const declaration = new Declaration({
  223. * prop: 'color',
  224. * value: 'black'
  225. * })
  226. *
  227. * declaration.type //=> 'decl'
  228. * ```
  229. */
  230. type: string
  231. constructor(defaults?: object)
  232. /**
  233. * Insert new node after current node to current node’s parent.
  234. *
  235. * Just alias for `node.parent.insertAfter(node, add)`.
  236. *
  237. * ```js
  238. * decl.after('color: black')
  239. * ```
  240. *
  241. * @param newNode New node.
  242. * @return This node for methods chain.
  243. */
  244. after(
  245. newNode: Node | Node.ChildProps | readonly Node[] | string | undefined
  246. ): this
  247. /**
  248. * It assigns properties to an existing node instance.
  249. *
  250. * ```js
  251. * decl.assign({ prop: 'word-wrap', value: 'break-word' })
  252. * ```
  253. *
  254. * @param overrides New properties to override the node.
  255. *
  256. * @return `this` for method chaining.
  257. */
  258. assign(overrides: object): this
  259. /**
  260. * Insert new node before current node to current node’s parent.
  261. *
  262. * Just alias for `node.parent.insertBefore(node, add)`.
  263. *
  264. * ```js
  265. * decl.before('content: ""')
  266. * ```
  267. *
  268. * @param newNode New node.
  269. * @return This node for methods chain.
  270. */
  271. before(
  272. newNode: Node | Node.ChildProps | readonly Node[] | string | undefined
  273. ): this
  274. /**
  275. * Clear the code style properties for the node and its children.
  276. *
  277. * ```js
  278. * node.raws.before //=> ' '
  279. * node.cleanRaws()
  280. * node.raws.before //=> undefined
  281. * ```
  282. *
  283. * @param keepBetween Keep the `raws.between` symbols.
  284. */
  285. cleanRaws(keepBetween?: boolean): void
  286. /**
  287. * It creates clone of an existing node, which includes all the properties
  288. * and their values, that includes `raws` but not `type`.
  289. *
  290. * ```js
  291. * decl.raws.before //=> "\n "
  292. * const cloned = decl.clone({ prop: '-moz-' + decl.prop })
  293. * cloned.raws.before //=> "\n "
  294. * cloned.toString() //=> -moz-transform: scale(0)
  295. * ```
  296. *
  297. * @param overrides New properties to override in the clone.
  298. *
  299. * @return Duplicate of the node instance.
  300. */
  301. clone(overrides?: object): this
  302. /**
  303. * Shortcut to clone the node and insert the resulting cloned node
  304. * after the current node.
  305. *
  306. * @param overrides New properties to override in the clone.
  307. * @return New node.
  308. */
  309. cloneAfter(overrides?: object): this
  310. /**
  311. * Shortcut to clone the node and insert the resulting cloned node
  312. * before the current node.
  313. *
  314. * ```js
  315. * decl.cloneBefore({ prop: '-moz-' + decl.prop })
  316. * ```
  317. *
  318. * @param overrides Mew properties to override in the clone.
  319. *
  320. * @return New node
  321. */
  322. cloneBefore(overrides?: object): this
  323. /**
  324. * It creates an instance of the class `CssSyntaxError` and parameters passed
  325. * to this method are assigned to the error instance.
  326. *
  327. * The error instance will have description for the
  328. * error, original position of the node in the
  329. * source, showing line and column number.
  330. *
  331. * If any previous map is present, it would be used
  332. * to get original position of the source.
  333. *
  334. * The Previous Map here is referred to the source map
  335. * generated by previous compilation, example: Less,
  336. * Stylus and Sass.
  337. *
  338. * This method returns the error instance instead of
  339. * throwing it.
  340. *
  341. * ```js
  342. * if (!variables[name]) {
  343. * throw decl.error(`Unknown variable ${name}`, { word: name })
  344. * // CssSyntaxError: postcss-vars:a.sass:4:3: Unknown variable $black
  345. * // color: $black
  346. * // a
  347. * // ^
  348. * // background: white
  349. * }
  350. * ```
  351. *
  352. * @param message Description for the error instance.
  353. * @param options Options for the error instance.
  354. *
  355. * @return Error instance is returned.
  356. */
  357. error(message: string, options?: Node.NodeErrorOptions): CssSyntaxError
  358. /**
  359. * Returns the next child of the node’s parent.
  360. * Returns `undefined` if the current node is the last child.
  361. *
  362. * ```js
  363. * if (comment.text === 'delete next') {
  364. * const next = comment.next()
  365. * if (next) {
  366. * next.remove()
  367. * }
  368. * }
  369. * ```
  370. *
  371. * @return Next node.
  372. */
  373. next(): Node.ChildNode | undefined
  374. /**
  375. * Get the position for a word or an index inside the node.
  376. *
  377. * @param opts Options.
  378. * @return Position.
  379. */
  380. positionBy(opts?: Pick<WarningOptions, 'index' | 'word'>): Node.Position
  381. /**
  382. * Convert string index to line/column.
  383. *
  384. * @param index The symbol number in the node’s string.
  385. * @return Symbol position in file.
  386. */
  387. positionInside(index: number): Node.Position
  388. /**
  389. * Returns the previous child of the node’s parent.
  390. * Returns `undefined` if the current node is the first child.
  391. *
  392. * ```js
  393. * const annotation = decl.prev()
  394. * if (annotation.type === 'comment') {
  395. * readAnnotation(annotation.text)
  396. * }
  397. * ```
  398. *
  399. * @return Previous node.
  400. */
  401. prev(): Node.ChildNode | undefined
  402. /**
  403. * Get the range for a word or start and end index inside the node.
  404. * The start index is inclusive; the end index is exclusive.
  405. *
  406. * @param opts Options.
  407. * @return Range.
  408. */
  409. rangeBy(
  410. opts?: Pick<WarningOptions, 'end' | 'endIndex' | 'index' | 'start' | 'word'>
  411. ): Node.Range
  412. /**
  413. * Returns a `raws` value. If the node is missing
  414. * the code style property (because the node was manually built or cloned),
  415. * PostCSS will try to autodetect the code style property by looking
  416. * at other nodes in the tree.
  417. *
  418. * ```js
  419. * const root = postcss.parse('a { background: white }')
  420. * root.nodes[0].append({ prop: 'color', value: 'black' })
  421. * root.nodes[0].nodes[1].raws.before //=> undefined
  422. * root.nodes[0].nodes[1].raw('before') //=> ' '
  423. * ```
  424. *
  425. * @param prop Name of code style property.
  426. * @param defaultType Name of default value, it can be missed
  427. * if the value is the same as prop.
  428. * @return {string} Code style value.
  429. */
  430. raw(prop: string, defaultType?: string): string
  431. /**
  432. * It removes the node from its parent and deletes its parent property.
  433. *
  434. * ```js
  435. * if (decl.prop.match(/^-webkit-/)) {
  436. * decl.remove()
  437. * }
  438. * ```
  439. *
  440. * @return `this` for method chaining.
  441. */
  442. remove(): this
  443. /**
  444. * Inserts node(s) before the current node and removes the current node.
  445. *
  446. * ```js
  447. * AtRule: {
  448. * mixin: atrule => {
  449. * atrule.replaceWith(mixinRules[atrule.params])
  450. * }
  451. * }
  452. * ```
  453. *
  454. * @param nodes Mode(s) to replace current one.
  455. * @return Current node to methods chain.
  456. */
  457. replaceWith(...nodes: NewChild[]): this
  458. /**
  459. * Finds the Root instance of the node’s tree.
  460. *
  461. * ```js
  462. * root.nodes[0].nodes[0].root() === root
  463. * ```
  464. *
  465. * @return Root parent.
  466. */
  467. root(): Root
  468. /**
  469. * Fix circular links on `JSON.stringify()`.
  470. *
  471. * @return Cleaned object.
  472. */
  473. toJSON(): object
  474. /**
  475. * It compiles the node to browser readable cascading style sheets string
  476. * depending on it's type.
  477. *
  478. * ```js
  479. * new Rule({ selector: 'a' }).toString() //=> "a {}"
  480. * ```
  481. *
  482. * @param stringifier A syntax to use in string generation.
  483. * @return CSS string of this node.
  484. */
  485. toString(stringifier?: Stringifier | Syntax): string
  486. /**
  487. * It is a wrapper for {@link Result#warn}, providing convenient
  488. * way of generating warnings.
  489. *
  490. * ```js
  491. * Declaration: {
  492. * bad: (decl, { result }) => {
  493. * decl.warn(result, 'Deprecated property: bad')
  494. * }
  495. * }
  496. * ```
  497. *
  498. * @param result The `Result` instance that will receive the warning.
  499. * @param message Description for the warning.
  500. * @param options Options for the warning.
  501. *
  502. * @return `Warning` instance is returned
  503. */
  504. warn(result: Result, message: string, options?: WarningOptions): Warning
  505. /**
  506. * If this node isn't already dirty, marks it and its ancestors as such. This
  507. * indicates to the LazyResult processor that the {@link Root} has been
  508. * modified by the current plugin and may need to be processed again by other
  509. * plugins.
  510. */
  511. protected markDirty(): void
  512. }
  513. declare class Node extends Node_ {}
  514. export = Node