framer-code-link 0.4.6 → 0.4.8
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/index.mjs +28 -25
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -156,6 +156,13 @@ function normalizePath$1(filePath) {
|
|
|
156
156
|
if (isAbsolute) return `/${normalized}`;
|
|
157
157
|
return normalized;
|
|
158
158
|
}
|
|
159
|
+
function normalizeCodeFilePath(filePath) {
|
|
160
|
+
const normalized = normalizePath$1(filePath);
|
|
161
|
+
return normalized.startsWith("/") ? normalized.slice(1) : normalized;
|
|
162
|
+
}
|
|
163
|
+
function canonicalFileName(filePath) {
|
|
164
|
+
return normalizeCodeFilePath(filePath);
|
|
165
|
+
}
|
|
159
166
|
function sanitizeFilePath(input, capitalizeReactComponent = true) {
|
|
160
167
|
const trimmed = input.trim();
|
|
161
168
|
const [inputName, extension] = splitExtension(filename(trimmed));
|
|
@@ -174,6 +181,13 @@ function isSupportedExtension$1(filePath) {
|
|
|
174
181
|
return /\.(tsx?|jsx?|json)$/i.test(filePath);
|
|
175
182
|
}
|
|
176
183
|
/**
|
|
184
|
+
* Returns a normalized, lowercase key for case-insensitive file lookups.
|
|
185
|
+
* Use this for Map keys on operating systems where "File.tsx" and "file.tsx" are the same file.
|
|
186
|
+
*/
|
|
187
|
+
function fileKeyForLookup(filePath) {
|
|
188
|
+
return canonicalFileName(filePath).toLowerCase();
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
177
191
|
* Pluralize a word based on count
|
|
178
192
|
* @example pluralize(1, "file") => "1 file"
|
|
179
193
|
* @example pluralize(3, "file") => "3 files"
|
|
@@ -712,11 +726,7 @@ const SUPPORTED_EXTENSIONS = [
|
|
|
712
726
|
".json"
|
|
713
727
|
];
|
|
714
728
|
const DEFAULT_EXTENSION = ".tsx";
|
|
715
|
-
const DEFAULT_REMOTE_DRIFT_MS =
|
|
716
|
-
/** Normalize file name for case-insensitive comparison (macOS/Windows compat) */
|
|
717
|
-
function normalizeForComparison(fileName) {
|
|
718
|
-
return fileName.toLowerCase();
|
|
719
|
-
}
|
|
729
|
+
const DEFAULT_REMOTE_DRIFT_MS = 2e3;
|
|
720
730
|
/**
|
|
721
731
|
* Lists all supported files in the files directory
|
|
722
732
|
*/
|
|
@@ -759,17 +769,17 @@ async function detectConflicts(remoteFiles, filesDir, options = {}) {
|
|
|
759
769
|
const detect = options.detectConflicts ?? true;
|
|
760
770
|
const preferRemote = options.preferRemote ?? false;
|
|
761
771
|
const persistedState = options.persistedState;
|
|
762
|
-
const getPersistedState = (fileName) => persistedState?.get(
|
|
772
|
+
const getPersistedState = (fileName) => persistedState?.get(fileKeyForLookup(fileName));
|
|
763
773
|
debug(`Detecting conflicts for ${String(remoteFiles.length)} remote files`);
|
|
764
774
|
const localFiles = await listFiles(filesDir);
|
|
765
|
-
const localFileMap = new Map(localFiles.map((f) => [
|
|
775
|
+
const localFileMap = new Map(localFiles.map((f) => [fileKeyForLookup(f.name), f]));
|
|
766
776
|
const remoteFileMap = new Map(remoteFiles.map((f) => {
|
|
767
|
-
return [
|
|
777
|
+
return [fileKeyForLookup(resolveRemoteReference(filesDir, f.name).relativePath), f];
|
|
768
778
|
}));
|
|
769
779
|
const processedFiles = /* @__PURE__ */ new Set();
|
|
770
780
|
for (const remote of remoteFiles) {
|
|
771
781
|
const normalized = resolveRemoteReference(filesDir, remote.name);
|
|
772
|
-
const normalizedKey =
|
|
782
|
+
const normalizedKey = fileKeyForLookup(normalized.relativePath);
|
|
773
783
|
const local = localFileMap.get(normalizedKey);
|
|
774
784
|
processedFiles.add(normalizedKey);
|
|
775
785
|
const persisted = getPersistedState(normalized.relativePath);
|
|
@@ -820,7 +830,7 @@ async function detectConflicts(remoteFiles, filesDir, options = {}) {
|
|
|
820
830
|
});
|
|
821
831
|
}
|
|
822
832
|
for (const local of localFiles) {
|
|
823
|
-
const localKey =
|
|
833
|
+
const localKey = fileKeyForLookup(local.name);
|
|
824
834
|
if (!processedFiles.has(localKey)) {
|
|
825
835
|
const persisted = getPersistedState(local.name);
|
|
826
836
|
if (persisted) {
|
|
@@ -841,8 +851,8 @@ async function detectConflicts(remoteFiles, filesDir, options = {}) {
|
|
|
841
851
|
});
|
|
842
852
|
}
|
|
843
853
|
}
|
|
844
|
-
if (persistedState) for (const
|
|
845
|
-
const normalizedKey =
|
|
854
|
+
if (persistedState) for (const fileName of persistedState.keys()) {
|
|
855
|
+
const normalizedKey = fileKeyForLookup(fileName);
|
|
846
856
|
const inLocal = localFileMap.has(normalizedKey);
|
|
847
857
|
const inRemote = remoteFileMap.has(normalizedKey);
|
|
848
858
|
if (!inLocal && !inRemote) debug(`[AUTO-RESOLVE] ${fileName}: deleted on both sides, no conflict`);
|
|
@@ -1615,13 +1625,6 @@ function initWatcher(filesDir) {
|
|
|
1615
1625
|
|
|
1616
1626
|
//#endregion
|
|
1617
1627
|
//#region src/utils/file-metadata-cache.ts
|
|
1618
|
-
/**
|
|
1619
|
-
* In-memory cache on top of state-persistence.
|
|
1620
|
-
*/
|
|
1621
|
-
/** Normalize file name for case-insensitive lookup (macOS/Windows compat) */
|
|
1622
|
-
function normalizeKey(fileName) {
|
|
1623
|
-
return fileName.toLowerCase();
|
|
1624
|
-
}
|
|
1625
1628
|
var FileMetadataCache = class {
|
|
1626
1629
|
metadata = /* @__PURE__ */ new Map();
|
|
1627
1630
|
persisted = /* @__PURE__ */ new Map();
|
|
@@ -1634,7 +1637,7 @@ var FileMetadataCache = class {
|
|
|
1634
1637
|
const loaded = await loadPersistedState(projectDir);
|
|
1635
1638
|
this.persisted = loaded;
|
|
1636
1639
|
this.metadata = /* @__PURE__ */ new Map();
|
|
1637
|
-
for (const [fileName, state] of loaded.entries()) this.metadata.set(
|
|
1640
|
+
for (const [fileName, state] of loaded.entries()) this.metadata.set(fileKeyForLookup(fileName), {
|
|
1638
1641
|
localHash: state.contentHash,
|
|
1639
1642
|
lastSyncedHash: state.contentHash,
|
|
1640
1643
|
lastRemoteTimestamp: state.timestamp
|
|
@@ -1642,10 +1645,10 @@ var FileMetadataCache = class {
|
|
|
1642
1645
|
this.initialized = true;
|
|
1643
1646
|
}
|
|
1644
1647
|
get(fileName) {
|
|
1645
|
-
return this.metadata.get(
|
|
1648
|
+
return this.metadata.get(fileKeyForLookup(fileName));
|
|
1646
1649
|
}
|
|
1647
1650
|
has(fileName) {
|
|
1648
|
-
return this.metadata.has(
|
|
1651
|
+
return this.metadata.has(fileKeyForLookup(fileName));
|
|
1649
1652
|
}
|
|
1650
1653
|
size() {
|
|
1651
1654
|
return this.metadata.size;
|
|
@@ -1654,7 +1657,7 @@ var FileMetadataCache = class {
|
|
|
1654
1657
|
return this.persisted;
|
|
1655
1658
|
}
|
|
1656
1659
|
recordRemoteWrite(fileName, content, remoteModifiedAt) {
|
|
1657
|
-
const key =
|
|
1660
|
+
const key = fileKeyForLookup(fileName);
|
|
1658
1661
|
const contentHash = hashFileContent(content);
|
|
1659
1662
|
this.metadata.set(key, {
|
|
1660
1663
|
localHash: contentHash,
|
|
@@ -1668,7 +1671,7 @@ var FileMetadataCache = class {
|
|
|
1668
1671
|
this.schedulePersist();
|
|
1669
1672
|
}
|
|
1670
1673
|
recordSyncedSnapshot(fileName, contentHash, remoteModifiedAt) {
|
|
1671
|
-
const key =
|
|
1674
|
+
const key = fileKeyForLookup(fileName);
|
|
1672
1675
|
this.metadata.set(key, {
|
|
1673
1676
|
localHash: contentHash,
|
|
1674
1677
|
lastSyncedHash: contentHash,
|
|
@@ -1681,7 +1684,7 @@ var FileMetadataCache = class {
|
|
|
1681
1684
|
this.schedulePersist();
|
|
1682
1685
|
}
|
|
1683
1686
|
recordDelete(fileName) {
|
|
1684
|
-
const key =
|
|
1687
|
+
const key = fileKeyForLookup(fileName);
|
|
1685
1688
|
this.metadata.delete(key);
|
|
1686
1689
|
this.persisted.delete(key);
|
|
1687
1690
|
this.schedulePersist();
|