Use files-diff for diffing
							parent
							
								
									010da3fda6
								
							
						
					
					
						commit
						a66db340f4
					
				| 
						 | 
				
			
			@ -5442,6 +5442,16 @@
 | 
			
		|||
      "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
 | 
			
		||||
      "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="
 | 
			
		||||
    },
 | 
			
		||||
    "files-diff": {
 | 
			
		||||
      "version": "0.0.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/files-diff/-/files-diff-0.0.2.tgz",
 | 
			
		||||
      "integrity": "sha512-5uD9B8Ga0o4X5FqG1O8aSoyBKLIW1qKB/385F5JvT3HzDO6x+ykWhtpCgbWrDNN8QPaWWqSy8lk1bY/bNgfP5A==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "diff": "^4.0.2",
 | 
			
		||||
        "escape-html": "^1.0.3",
 | 
			
		||||
        "string-similarity": "^4.0.1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "filesize": {
 | 
			
		||||
      "version": "3.6.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,6 +44,7 @@
 | 
			
		|||
    "do-bulma": "git+https://github.com/do-community/do-bulma.git",
 | 
			
		||||
    "do-vue": "git+https://github.com/do-community/do-vue.git",
 | 
			
		||||
    "escape-html": "^1.0.3",
 | 
			
		||||
    "files-diff": "0.0.2",
 | 
			
		||||
    "memory-tar-create": "0.0.2",
 | 
			
		||||
    "pretty-checkbox-vue": "^1.1.9",
 | 
			
		||||
    "prismjs": "^1.20.0",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -100,7 +100,7 @@ THE SOFTWARE.
 | 
			
		|||
    import sha2_256 from 'simple-js-sha2-256';
 | 
			
		||||
    import escape from 'escape-html';
 | 
			
		||||
    import Header from 'do-vue/src/templates/header';
 | 
			
		||||
    import diff from '../util/diff';
 | 
			
		||||
    import diff from 'files-diff';
 | 
			
		||||
    import isChanged from '../util/is_changed';
 | 
			
		||||
    import importData from '../util/import_data';
 | 
			
		||||
    import isObject from '../util/is_object';
 | 
			
		||||
| 
						 | 
				
			
			@ -213,12 +213,18 @@ THE SOFTWARE.
 | 
			
		|||
            },
 | 
			
		||||
            updateDiff(newConf, oldConf) {
 | 
			
		||||
                // Calculate the diff & highlight after render
 | 
			
		||||
                this.$data.confFilesOutput = Object.values(diff(newConf, oldConf)).map(conf => {
 | 
			
		||||
                    const name = `${escape(this.$data.global.nginx.nginxConfigDirectory.computed)}/${conf[0]}`;
 | 
			
		||||
                const diffConf = diff(newConf, oldConf, {
 | 
			
		||||
                    highlightFunction: value => `<mark>${value}</mark>`,
 | 
			
		||||
                });
 | 
			
		||||
                this.$data.confFilesOutput = Object.values(diffConf).map(({ name, content }) => {
 | 
			
		||||
                    const diffName = name.filter(x => !x.removed).map(x => x.value).join('');
 | 
			
		||||
                    const confName = `${escape(this.$data.global.nginx.nginxConfigDirectory.computed)}/${diffName}`;
 | 
			
		||||
                    const diffContent = content.filter(x => !x.removed).map(x => x.value).join('');
 | 
			
		||||
 | 
			
		||||
                    return [
 | 
			
		||||
                        name,
 | 
			
		||||
                        conf[1],
 | 
			
		||||
                        `${sha2_256(name)}-${sha2_256(conf[1])}`,
 | 
			
		||||
                        confName,
 | 
			
		||||
                        diffContent,
 | 
			
		||||
                        `${sha2_256(confName)}-${sha2_256(diffContent)}`,
 | 
			
		||||
                    ];
 | 
			
		||||
                });
 | 
			
		||||
                this.$nextTick(() => this.$data.confWatcherWaiting = false);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,61 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2020 DigitalOcean
 | 
			
		||||
 | 
			
		||||
This code is licensed under the MIT License.
 | 
			
		||||
You may obtain a copy of the License at
 | 
			
		||||
https://github.com/digitalocean/nginxconfig.io/blob/master/LICENSE or https://mit-license.org/
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
in the Software without restriction, including without limitation the rights
 | 
			
		||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
 | 
			
		||||
copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
furnished to do so, subject to the following conditions :
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in
 | 
			
		||||
all copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
 | 
			
		||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
THE SOFTWARE.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
import { diffLines } from 'diff';
 | 
			
		||||
import escape from 'escape-html';
 | 
			
		||||
 | 
			
		||||
export default (newConfFile, oldConfFile) => {
 | 
			
		||||
    // Get the diff
 | 
			
		||||
    const diff = diffLines(oldConfFile, newConfFile);
 | 
			
		||||
 | 
			
		||||
    // Wrap additions in <mark>, drop removals
 | 
			
		||||
    return diff.map((change, index, array) => {
 | 
			
		||||
        if (change.removed) return '';
 | 
			
		||||
 | 
			
		||||
        const escaped = escape(change.value);
 | 
			
		||||
 | 
			
		||||
        // Don't mark as diff if nothing changed
 | 
			
		||||
        if (!change.added) return escaped;
 | 
			
		||||
 | 
			
		||||
        // Don't mark as diff if only whitespace changed
 | 
			
		||||
        if (index > 0 && array[index - 1].removed) {
 | 
			
		||||
            if (array[index - 1].value.replace(/\s/g, '') === change.value.replace(/\s/g, '')) {
 | 
			
		||||
                return escaped;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (index < array.length - 1 && array[index + 1].removed) {
 | 
			
		||||
            if (array[index + 1].value.replace(/\s/g, '') === change.value.replace(/\s/g, '')) {
 | 
			
		||||
                return escaped;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Mark the diff, without highlighting whitespace
 | 
			
		||||
        return escaped
 | 
			
		||||
            .split('\n')
 | 
			
		||||
            .map(part => part.replace(/^(\s*)(.*)(\s*)$/, '$1<mark>$2</mark>$3'))
 | 
			
		||||
            .join('\n');
 | 
			
		||||
    }).join('');
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -1,68 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2020 DigitalOcean
 | 
			
		||||
 | 
			
		||||
This code is licensed under the MIT License.
 | 
			
		||||
You may obtain a copy of the License at
 | 
			
		||||
https://github.com/digitalocean/nginxconfig.io/blob/master/LICENSE or https://mit-license.org/
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
in the Software without restriction, including without limitation the rights
 | 
			
		||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
 | 
			
		||||
copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
furnished to do so, subject to the following conditions :
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in
 | 
			
		||||
all copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
 | 
			
		||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
THE SOFTWARE.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
import escape from 'escape-html';
 | 
			
		||||
import renames from './renames';
 | 
			
		||||
import confLines from './conf_lines';
 | 
			
		||||
import names from './names';
 | 
			
		||||
 | 
			
		||||
export default (newConf, oldConf) => {
 | 
			
		||||
    // Consider renames
 | 
			
		||||
    const renameMap = renames(newConf, oldConf);
 | 
			
		||||
 | 
			
		||||
    // Store the diff config files
 | 
			
		||||
    const newFiles = {};
 | 
			
		||||
 | 
			
		||||
    // Work through each file in the new config
 | 
			
		||||
    for (const name in newConf) {
 | 
			
		||||
        if (!Object.prototype.hasOwnProperty.call(newConf, name)) continue;
 | 
			
		||||
 | 
			
		||||
        let newFileName = escape(name);
 | 
			
		||||
        let newFileConf = escape(newConf[name]);
 | 
			
		||||
 | 
			
		||||
        // If this file was in the old config (same name or renamed & similar)
 | 
			
		||||
        // Calculate the diff of the configs
 | 
			
		||||
        const old = oldConf && oldConf[renameMap[name]];
 | 
			
		||||
        if (old && old !== newConf[name]) {
 | 
			
		||||
            console.info(`Diffing ${name}...`);
 | 
			
		||||
            newFileConf = confLines(newConf[name], old);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // If the file was renamed we should diff that too
 | 
			
		||||
        if (name in renameMap && renameMap[name] !== name) {
 | 
			
		||||
            newFileName = names(name, renameMap[name]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Store!
 | 
			
		||||
        newFiles[name] = [
 | 
			
		||||
            newFileName,
 | 
			
		||||
            newFileConf,
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Done
 | 
			
		||||
    return newFiles;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -1,46 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2020 DigitalOcean
 | 
			
		||||
 | 
			
		||||
This code is licensed under the MIT License.
 | 
			
		||||
You may obtain a copy of the License at
 | 
			
		||||
https://github.com/digitalocean/nginxconfig.io/blob/master/LICENSE or https://mit-license.org/
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
in the Software without restriction, including without limitation the rights
 | 
			
		||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
 | 
			
		||||
copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
furnished to do so, subject to the following conditions :
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in
 | 
			
		||||
all copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
 | 
			
		||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
THE SOFTWARE.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
import { diffChars } from 'diff';
 | 
			
		||||
import escape from 'escape-html';
 | 
			
		||||
 | 
			
		||||
export default (newConfName, oldConfName) => {
 | 
			
		||||
    // Get the diff
 | 
			
		||||
    const diff = diffChars(oldConfName, newConfName);
 | 
			
		||||
 | 
			
		||||
    // Wrap additions in <mark>, drop removals
 | 
			
		||||
    return diff.map(change => {
 | 
			
		||||
        if (change.removed) return '';
 | 
			
		||||
 | 
			
		||||
        const escaped = escape(change.value);
 | 
			
		||||
 | 
			
		||||
        // Don't mark as diff if nothing changed
 | 
			
		||||
        if (!change.added) return escaped;
 | 
			
		||||
 | 
			
		||||
        // Mark the diff, without highlighting whitespace
 | 
			
		||||
        return escaped.replace(/^(\s*)(.*)(\s*)$/, '$1<mark>$2</mark>$3');
 | 
			
		||||
    }).join('');
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -1,60 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2020 DigitalOcean
 | 
			
		||||
 | 
			
		||||
This code is licensed under the MIT License.
 | 
			
		||||
You may obtain a copy of the License at
 | 
			
		||||
https://github.com/digitalocean/nginxconfig.io/blob/master/LICENSE or https://mit-license.org/
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
in the Software without restriction, including without limitation the rights
 | 
			
		||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
 | 
			
		||||
copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
furnished to do so, subject to the following conditions :
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in
 | 
			
		||||
all copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
 | 
			
		||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
THE SOFTWARE.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
import { compareTwoStrings } from 'string-similarity';
 | 
			
		||||
 | 
			
		||||
export default (newConf, oldConf) => {
 | 
			
		||||
    const newNames = Object.keys(newConf);
 | 
			
		||||
    const oldNames = Object.keys(oldConf);
 | 
			
		||||
    const removed = oldNames.filter(name => !newNames.includes(name));
 | 
			
		||||
    const added = newNames.filter(name => !oldNames.includes(name));
 | 
			
		||||
 | 
			
		||||
    // For each newly added file, compare it to all the old files
 | 
			
		||||
    const addedSimilarity = {};
 | 
			
		||||
    for (const newName of added) {
 | 
			
		||||
        addedSimilarity[newName] = { old: '', similarity: 0 };
 | 
			
		||||
 | 
			
		||||
        for (const oldName of removed) {
 | 
			
		||||
            const similarity = compareTwoStrings(newConf[newName], oldConf[oldName]);
 | 
			
		||||
 | 
			
		||||
            // Only care about > 50% similarity
 | 
			
		||||
            if (similarity <= .5) continue;
 | 
			
		||||
 | 
			
		||||
            // Store the most similar
 | 
			
		||||
            if (similarity > addedSimilarity[newName].similarity)
 | 
			
		||||
                addedSimilarity[newName] = { old: oldName, similarity };
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Create a rename map
 | 
			
		||||
    return newNames.reduce((prev, current) => {
 | 
			
		||||
        if (current in addedSimilarity && addedSimilarity[current].similarity)
 | 
			
		||||
            prev[current] = addedSimilarity[current].old;
 | 
			
		||||
        else
 | 
			
		||||
            prev[current] = current;
 | 
			
		||||
        return prev;
 | 
			
		||||
    }, {});
 | 
			
		||||
};
 | 
			
		||||
		Loading…
	
		Reference in New Issue