Repository: 11ty/eleventy (JavaScript)

Issue:
Dots in Global Data Files are used for dot-pathing instead of preserved in key name
**Describe the bug**
If a data file has dots in the file name, the dots describe an object path that the data in the file is available at.

**To Reproduce**
In an eleventy project:

1. Create a file at `_data/sites/11ty.dev.json` that just contains:
    ```json
    {}
    ```
2. Create a file at `index.liquid` that just contains:
    ```liquid
    {{sites | log}}
    ```
3. Run `npx @11ty/eleventy`
4. See console output:
    ```js
    { '11ty': { dev: {} } }
    ```

**Expected behavior**
I don't know if this is actually expected behaviour, but I would have assumed it would output 

```js
{ '11ty.dev': {} }
```

The 11ty docs seem to operate under this assumption, because [sites with dots in the filename don't show up on the leaderboard due to the unexpected dot-path behaviour](https://github.com/11ty/11ty-website/issues/639).

**Environment:**

- OS and Version: macOS 10.15.5
- Eleventy Version: 0.11.0

**Additional context**
* 11ty/11ty-website#639
* Dermah/eleventy@0b88d8d could be turned in to a PR if this is actually a bug.


Discussion:
Yes this is absolutely a bug!
I would love a PR on this although I don’t think https://github.com/Dermah/eleventy/commit/0b88d8d is quite accurate? `folder["sub.folder"]` works but `fol.der["subfolder"]` wouldn’t?
Merged #1912, this will ship with 2.0.0-canary.10.

Thank you @Snapstromegon!



Patch:
diff --git a/src/TemplateData.js b/src/TemplateData.js
index b615c304c..e675c1aee 100755
--- a/src/TemplateData.js
+++ b/src/TemplateData.js
@@ -250,7 +250,7 @@ class TemplateData {
     let folders = parsed.dir ? parsed.dir.split("/") : [];
     folders.push(parsed.name);
 
-    return folders.join(".");
+    return folders;
   }
 
   async getAllGlobalData() {
@@ -265,21 +265,27 @@ class TemplateData {
     let dataFileConflicts = {};
 
     for (let j = 0, k = files.length; j < k; j++) {
-      let objectPathTarget = await this.getObjectPathForDataFile(files[j]);
       let data = await this.getDataValue(files[j], rawImports);
+      let objectPathTarget = this.getObjectPathForDataFile(files[j]);
+
+      // Since we're joining directory paths and an array is not useable as an objectkey since two identical arrays are not double equal,
+      // we can just join the array by a forbidden character ("/"" is chosen here, since it works on Linux, Mac and Windows).
+      // If at some point this isn't enough anymore, it would be possible to just use JSON.stringify(objectPathTarget) since that
+      // is guaranteed to work but is signifivcantly slower.
+      let objectPathTargetString = objectPathTarget.join("/");
 
       // if two global files have the same path (but different extensions)
       // and conflict, let’s merge them.
-      if (dataFileConflicts[objectPathTarget]) {
+      if (dataFileConflicts[objectPathTargetString]) {
         debugWarn(
-          `merging global data from ${files[j]} with an already existing global data file (${dataFileConflicts[objectPathTarget]}). Overriding existing keys.`
+          `merging global data from ${files[j]} with an already existing global data file (${dataFileConflicts[objectPathTargetString]}). Overriding existing keys.`
         );
 
         let oldData = lodashget(globalData, objectPathTarget);
         data = TemplateData.mergeDeep(this.config, oldData, data);
       }
 
-      dataFileConflicts[objectPathTarget] = files[j];
+      dataFileConflicts[objectPathTargetString] = files[j];
       debug(
         `Found global data file ${files[j]} and adding as: ${objectPathTarget}`
       );


Test patch:
diff --git a/test/TemplateDataTest.js b/test/TemplateDataTest.js
index 408589bb0..311ce68fb 100644
--- a/test/TemplateDataTest.js
+++ b/test/TemplateDataTest.js
@@ -448,6 +448,29 @@ test("Parent directory for data (Issue #337)", async (t) => {
   });
 });
 
+test("Dots in datafile path (Issue #1242)", async (t) => {
+  let eleventyConfig = new TemplateConfig({
+    dataTemplateEngine: false,
+    dir: {
+      input: "./test/stubs-1242/",
+      data: "_data/",
+    },
+  });
+  let dataObj = new TemplateData("./test/stubs-1242/", eleventyConfig);
+  dataObj.setInputDir("./test/stubs-1242/");
+
+  let data = await dataObj.getData();
+
+  t.deepEqual(data, {
+    "xyz.dottest": {
+      hi: "bye",
+      test: {
+        abc: 42,
+      },
+    },
+  });
+});
+
 test("addGlobalData values", async (t) => {
   let eleventyConfig = new TemplateConfig();
   eleventyConfig.userConfig.addGlobalData("myFunction", () => "fn-value");
diff --git a/test/stubs-1242/_data/xyz.dottest.json b/test/stubs-1242/_data/xyz.dottest.json
new file mode 100644
index 000000000..6c820361c
--- /dev/null
+++ b/test/stubs-1242/_data/xyz.dottest.json
@@ -0,0 +1,3 @@
+{
+  "hi": "bye"
+}
diff --git a/test/stubs-1242/_data/xyz.dottest/test.json b/test/stubs-1242/_data/xyz.dottest/test.json
new file mode 100644
index 000000000..d6f996357
--- /dev/null
+++ b/test/stubs-1242/_data/xyz.dottest/test.json
@@ -0,0 +1,3 @@
+{
+  "abc": 42
+}
diff --git a/test/stubs-1242/empty.md b/test/stubs-1242/empty.md
new file mode 100644
index 000000000..e69de29bb