Skip to content

Commit

Permalink
feat(Import): load linked assets when importing from GitHub
Browse files Browse the repository at this point in the history
  • Loading branch information
hatemhosny committed Apr 16, 2024
1 parent af755ed commit bf0660d
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 4 deletions.
20 changes: 19 additions & 1 deletion src/livecodes/import/github-dir.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { User } from '../models';
// eslint-disable-next-line import/no-internal-modules
import { getGithubHeaders } from '../services/github';
import { populateConfig } from './utils';
import { addBaseTag } from './github';

export const importFromGithubDir = async (
url: string,
Expand Down Expand Up @@ -72,11 +73,28 @@ export const importFromGithubDir = async (
return {
filename,
content,
path: file.path,
};
}),
);

return populateConfig(files, params);
const config = populateConfig(files, params);

return addBaseTag(
config,
files
.filter((f) =>
[config.markup?.content, config.style?.content, config.script?.content].includes(
f.content,
),
)
.map((f) => ({
user,
repo: repository,
ref: branch,
path: f.path,
})),
);
} catch (error) {
// eslint-disable-next-line no-console
console.error('Cannot fetch directory: ' + url);
Expand Down
65 changes: 62 additions & 3 deletions src/livecodes/import/github.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/* eslint-disable import/no-internal-modules */
import { decode } from 'js-base64';
import type { Language, Config, User } from '../models';
import { getLanguageByAlias, getLanguageEditorId } from '../languages/utils';
import type { Language, Config, User, EditorId } from '../models';
import { getLanguageByAlias, getLanguageEditorId, getLanguageExtension } from '../languages/utils';
import { getGithubHeaders } from '../services/github';
import { modulesService } from '../services/modules';

const getValidUrl = (url: string) =>
url.startsWith('https://') ? new URL(url) : new URL('https://' + url);
Expand Down Expand Up @@ -78,13 +79,14 @@ const getContent = async (
: fileContent;
const language = getLanguageByAlias(extension) || 'html';
const editorId = getLanguageEditorId(language) || 'markup';
return {
const config = {
[editorId]: {
language,
content,
},
activeEditor: editorId,
};
return addBaseTag(config, [fileData]);
} catch (error) {
// eslint-disable-next-line no-console
console.error('Cannot fetch: ' + apiUrl);
Expand All @@ -100,3 +102,60 @@ export const importFromGithub = (
const fileData = getFileData(validUrl);
return getContent(fileData, loggedInUser);
};

export const addBaseTag = (
config: Partial<Config>,
files: Array<{ user: string; repo: string; ref: string; path: string }>,
): Partial<Config> => {
const markupLanguages = ['html', 'markdown', 'mdx'];
const markupFile = files.find((file) =>
markupLanguages.find((lang) => file.path.endsWith(`.${getLanguageExtension(lang)}`)),
);
const getFile = (editorId: EditorId) =>
files.find((file) => {
const extension = file.path.split('.')[file.path.split('.').length - 1];
return editorId === getLanguageEditorId(extension);
});
const styleFile = getFile('style');
const scriptFile = getFile('script');
if (
!markupFile ||
!config.markup?.language ||
!markupLanguages.includes(config.markup?.language || '') ||
config.markup.content?.includes('<base')
) {
return config;
}
const { user, repo, ref, path } = markupFile;
const baseUrl = modulesService.getUrl(`gh:${user}/${repo}@${ref}/${path}`);
const baseTag = `<base href="${baseUrl}">`;

const removeTags = (markupContent: string, tag: 'link' | 'script') => {
const file = tag === 'link' ? styleFile : scriptFile;
if (!file) return markupContent;
const filename = file.path.split('/')[file.path.split('/').length - 1];
if (!markupContent.includes(filename)) return markupContent;
const linkPattern = new RegExp(
`<link[^>]{1,200}?href=["']((?!http(s)?:\\/\\/).){0,200}?${filename}["'][^>]{0,200}?>`,
'g',
);
const scriptPattern = new RegExp(
`<script[\\s\\S]{1,200}?src=["']((?!http(s)?:\\/\\/).){0,200}?${filename}["'][\\s\\S]{0,200}?</script>`,
'g',
);
const pattern = tag === 'link' ? linkPattern : scriptPattern;
return markupContent.replace(pattern, '');
};

let content = removeTags(config.markup.content || '', 'link');
content = removeTags(content, 'script');

return {
...config,
markup: {
...config.markup,
content,
hiddenContent: baseTag,
},
};
};

0 comments on commit bf0660d

Please sign in to comment.