@rafters/veneer 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { i as relativeFile } from "./lint-Tvq5uHHS.mjs";
3
- import { t as check } from "./check-CbVCXbX6.mjs";
2
+ import { i as relativeFile } from "./lint-9HD2n_oJ.mjs";
3
+ import { t as check } from "./check-BWUfShkM.mjs";
4
4
  import path from "node:path";
5
5
  import { existsSync, realpathSync } from "node:fs";
6
6
  import { parseArgs } from "node:util";
@@ -1,4 +1,4 @@
1
- import { a as resolveComponents, c as readConfig, n as report, o as ProjectError, r as compareCodePoints, s as openProject, t as lint } from "./lint-Tvq5uHHS.mjs";
1
+ import { a as resolveComponents, c as readConfig, n as report, o as ProjectError, r as compareCodePoints, s as openProject, t as lint } from "./lint-9HD2n_oJ.mjs";
2
2
  import path from "node:path";
3
3
  import { mkdir, rename, rm, writeFile } from "node:fs/promises";
4
4
  import { lstatSync } from "node:fs";
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { n as report, o as ProjectError, s as openProject, t as lint } from "./lint-Tvq5uHHS.mjs";
2
- import { n as writeDocs, t as check } from "./check-CbVCXbX6.mjs";
1
+ import { n as report, o as ProjectError, s as openProject, t as lint } from "./lint-9HD2n_oJ.mjs";
2
+ import { n as writeDocs, t as check } from "./check-BWUfShkM.mjs";
3
3
  export { ProjectError, check, lint, openProject, report, writeDocs };
@@ -812,6 +812,7 @@ const CLASS_ATTRIBUTES = /* @__PURE__ */ new Set([
812
812
  ]);
813
813
  const MAX_RESOLVE_STEPS = 8;
814
814
  const realPath = (file) => existsSync(file) ? realpathSync(file) : file;
815
+ const isClassesFile = (file) => file.endsWith(".classes.ts");
815
816
  function qualifies(reader, sourceFile) {
816
817
  const { fileName } = sourceFile;
817
818
  const stem = fileName.replace(/\.(tsx|astro)$/, "");
@@ -879,11 +880,21 @@ function utilityOf(className) {
879
880
  }
880
881
  return className.slice(start);
881
882
  }
882
- function constString(reader, identifier) {
883
+ function constInitializer(reader, identifier) {
883
884
  const { ts, tc } = reader;
884
885
  const declaration = resolveSymbol(reader, tc.getSymbolAtLocation(identifier))?.valueDeclaration;
885
- if (!declaration || !ts.isVariableDeclaration(declaration) || !(ts.getCombinedNodeFlags(declaration) & ts.NodeFlags.Const) || !declaration.initializer) return;
886
- return ts.isStringLiteralLike(declaration.initializer) ? declaration.initializer : void 0;
886
+ return declaration && ts.isVariableDeclaration(declaration) && ts.getCombinedNodeFlags(declaration) & ts.NodeFlags.Const ? declaration.initializer : void 0;
887
+ }
888
+ function constString(reader, identifier) {
889
+ const initializer = constInitializer(reader, identifier);
890
+ return initializer && reader.ts.isStringLiteralLike(initializer) ? initializer : void 0;
891
+ }
892
+ function constProperty(reader, { expression, name }) {
893
+ const { ts } = reader;
894
+ let object = ts.isIdentifier(expression) ? constInitializer(reader, expression) : void 0;
895
+ while (object && (ts.isAsExpression(object) || ts.isSatisfiesExpression(object))) object = object.expression;
896
+ if (!object || !ts.isObjectLiteralExpression(object)) return void 0;
897
+ for (const property of object.properties) if (ts.isPropertyAssignment(property) && ts.isIdentifier(property.name) && property.name.text === name.text) return ts.isStringLiteralLike(property.initializer) ? property.initializer : void 0;
887
898
  }
888
899
  function collectClassStrings(reader, sourceFile, isOwnSource, node, found) {
889
900
  const { ts } = reader;
@@ -894,9 +905,17 @@ function collectClassStrings(reader, sourceFile, isOwnSource, node, found) {
894
905
  if (!literal || !declaredIn) return;
895
906
  if (declaredIn === sourceFile) found.set(literal, literal);
896
907
  else if (isOwnSource(declaredIn.fileName)) found.set(node, literal);
897
- } else ts.forEachChild(node, (child) => {
898
- collectClassStrings(reader, sourceFile, isOwnSource, child, found);
899
- });
908
+ } else {
909
+ const literal = ts.isPropertyAccessExpression(node) ? constProperty(reader, node) : void 0;
910
+ const declaredIn = literal?.getSourceFile();
911
+ if (literal && declaredIn && (declaredIn === sourceFile || isOwnSource(declaredIn.fileName))) {
912
+ found.set(node, literal);
913
+ return;
914
+ }
915
+ ts.forEachChild(node, (child) => {
916
+ collectClassStrings(reader, sourceFile, isOwnSource, child, found);
917
+ });
918
+ }
900
919
  }
901
920
  function bracketsInLiteral(reader, file, sourceFile, at, literal) {
902
921
  return [...literal.getText(literal.getSourceFile()).slice(1, -1).matchAll(/\S+/g)].flatMap((match) => {
@@ -920,8 +939,12 @@ function bracketsInLiteral(reader, file, sourceFile, at, literal) {
920
939
  function bracketValues(reader, file, sourceFile, isOwnSource) {
921
940
  const { ts } = reader;
922
941
  const strings = /* @__PURE__ */ new Map();
942
+ const everyLiteral = isClassesFile(sourceFile.fileName);
943
+ if (everyLiteral && !isOwnSource(sourceFile.fileName)) return [];
923
944
  const visit = (node) => {
924
- if (ts.isJsxAttribute(node) && node.initializer) {
945
+ if (everyLiteral) {
946
+ if (ts.isStringLiteralLike(node)) strings.set(node, node);
947
+ } else if (ts.isJsxAttribute(node) && node.initializer) {
925
948
  const { name } = node;
926
949
  const attribute = ts.isJsxNamespacedName(name) ? `${name.namespace.text}:${name.name.text}` : name.text;
927
950
  if (CLASS_ATTRIBUTES.has(attribute)) collectClassStrings(reader, sourceFile, isOwnSource, node.initializer, strings);
@@ -968,8 +991,19 @@ function valueAttributes({ ts }, sourceFile) {
968
991
  visit(sourceFile);
969
992
  return found;
970
993
  }
994
+ const FREEHAND_HELP = "use Container or Grid for layout";
995
+ function openingElements({ ts }, sourceFile) {
996
+ const found = [];
997
+ const visit = (node) => {
998
+ if (ts.isJsxOpeningLikeElement(node)) found.push(node);
999
+ ts.forEachChild(node, visit);
1000
+ };
1001
+ visit(sourceFile);
1002
+ return found;
1003
+ }
1004
+ const isDiv = (ts, { tagName }) => ts.isIdentifier(tagName) && tagName.text === "div";
971
1005
  async function lint(project, options) {
972
- const files = options.files ?? project.checker.getRootFileNames().filter((file) => file.endsWith(".tsx") || file.endsWith(".astro")).map((file) => relativeFile(project.root, file));
1006
+ const files = options.files?.filter((file) => !file.endsWith(".ts") || isClassesFile(file)) ?? project.checker.getRootFileNames().filter((file) => file.endsWith(".tsx") || file.endsWith(".astro") || isClassesFile(file)).map((file) => relativeFile(project.root, file));
973
1007
  const perFile = [];
974
1008
  for (const file of files) perFile.push([file, await project.diagnostics(file)]);
975
1009
  const program = project.program();
@@ -1081,6 +1115,33 @@ async function lint(project, options) {
1081
1115
  }
1082
1116
  return flagged;
1083
1117
  };
1118
+ const isComponentUse = (element) => {
1119
+ if (isDiv(ts, element)) return false;
1120
+ const component = resolveTag(reader, element);
1121
+ const declaration = component?.valueDeclaration ?? component?.declarations?.[0];
1122
+ return declaration !== void 0 && isCheckedUse(declaration.getSourceFile());
1123
+ };
1124
+ const freehandDivs = (file, sourceFile) => {
1125
+ const elements = openingElements(reader, sourceFile);
1126
+ const divs = elements.filter((element) => isDiv(ts, element));
1127
+ if (divs.length === 0 || !elements.some(isComponentUse)) return [];
1128
+ return divs.flatMap(({ tagName }) => {
1129
+ const start = positionOf(reader, sourceFile, tagName.getStart(sourceFile));
1130
+ const end = positionOf(reader, sourceFile, tagName.end);
1131
+ if (!start || !end) return [];
1132
+ return [{
1133
+ file,
1134
+ line: start.line,
1135
+ column: start.column,
1136
+ endLine: end.line,
1137
+ endColumn: end.column,
1138
+ severity: "warning",
1139
+ code: "rafters(freehand-div)",
1140
+ message: "a div laid by hand around rafters components",
1141
+ help: FREEHAND_HELP
1142
+ }];
1143
+ });
1144
+ };
1084
1145
  const found = [];
1085
1146
  for (const [file, diagnostics] of perFile) {
1086
1147
  const absolute = path.join(project.root, file);
@@ -1093,17 +1154,18 @@ async function lint(project, options) {
1093
1154
  if (!isExempt(sourceFile)) {
1094
1155
  found.push(...bracketValues(reader, file, sourceFile, isOwnSource));
1095
1156
  found.push(...await badValues(file, sourceFile));
1157
+ found.push(...freehandDivs(file, sourceFile));
1096
1158
  }
1097
1159
  }
1098
1160
  return found.sort((a, b) => compareCodePoints(a.file, b.file) || a.line - b.line || a.column - b.column);
1099
1161
  }
1100
- function firstLine(message) {
1101
- return (typeof message === "string" ? message : message.value).split(/\r\n|\r|\n/, 1)[0] ?? "";
1162
+ function messageLines(message) {
1163
+ return (typeof message === "string" ? message : message.value).split(/\r\n|\r|\n/);
1102
1164
  }
1103
1165
  function report(diagnostics) {
1104
1166
  const lines = diagnostics.flatMap(({ file, line, column, severity, code, message, help }) => {
1105
- const entry = `${file}:${line}:${column} ${severity} ${code} ${firstLine(message)}`;
1106
- return help === void 0 ? [entry] : [entry, ` help: ${help}`];
1167
+ const entry = messageLines(message).map((text, index) => index === 0 ? `${file}:${line}:${column} ${severity} ${code} ${text}` : ` ${text}`);
1168
+ return help === void 0 ? entry : [...entry, ` help: ${help}`];
1107
1169
  });
1108
1170
  const count = diagnostics.length;
1109
1171
  lines.push(count === 1 ? "1 problem" : `${count} problems`);
package/dist/worker.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { c as readConfig, s as openProject, t as lint } from "./lint-Tvq5uHHS.mjs";
1
+ import { c as readConfig, s as openProject, t as lint } from "./lint-9HD2n_oJ.mjs";
2
2
  import path from "node:path";
3
3
  import { existsSync } from "node:fs";
4
4
  import { promisify } from "node:util";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rafters/veneer",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "Docs, rafters check and the composite compile for rafters projects",
5
5
  "license": "MIT",
6
6
  "repository": {