diff --git a/README.md b/README.md
index 032b293..e28a214 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
-
+
PlantUML class generator for JavaScript
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index adb5d85..3c12a74 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -1,6 +1,25 @@
# Changelog
All notable changes to this project will be documented in this file.
+## [0.9.9] - 2023-10-17
+### Added
+- `Linker` class, `set_regexes ( )` function to set regexes for each identified class
+
+### Changed
+- `Linker` class
+ - `self.classes` global variable to `self.classSources` for specificity
+ - renamed `read_files ( )` to `get_objects ( )`
+ - refactored:
+ - `get_objects ( )`
+ - `match_files ( )`
+ - `find_files ( )`
+ - `link_objects ( )`
+ - `compose_image ( )`
+- `get_commands.py` to parse output to `_output` directory, instead of `output`
+
+### Fixed
+- `Generator` class, fixed issue where tag title parses regardless of no tag elements
+
## [0.8.9] - 2023-10-11
### Changed
- Refactored and cleaned `linker` class
@@ -172,9 +191,11 @@ All notable changes to this project will be documented in this file.
---
-| Version | Date | Commit | Comments |
+| Version | Date | Commit | Comments |
| :-----: | :--------: | :----------------------------------------------------------------------: | :---------------------------------------------------------------- |
-| 0.7.8 | 2023-05-03 | Current | Help menu implemented
+| 0.9.9 | 2023-10-17 | Current | Fixed linker class issues
+| 0.8.9 | 2023-10-11 | [cd79df5](https://github.com/Justin-Byrne/ClassGenerator/commit/cd79df5) | Refactored linker class
+| 0.8.8 | 2023-10-11 | [6154c3e](https://github.com/Justin-Byrne/ClassGenerator/commit/6154c3e) | Major refactoring of project
| 0.7.7 | 2023-05-03 | [bb4ef56](https://github.com/Justin-Byrne/ClassGenerator/commit/bb4ef56) | PlantUml program executable location management
| 0.7.6 | 2023-05-02 | [63dab81](https://github.com/Justin-Byrne/ClassGenerator/commit/63dab81) | Fully implemented class linker
| 0.6.5 | 2023-04-29 | [ed8937b](https://github.com/Justin-Byrne/ClassGenerator/commit/ed8937b) | Expanded config, validation, and debugging
diff --git a/source/app/core/generator.py b/source/app/core/generator.py
index e4b1b1a..dfd1885 100644
--- a/source/app/core/generator.py
+++ b/source/app/core/generator.py
@@ -307,10 +307,10 @@ def compose_members ( self ):
for tag_type in self.tags:
- members += f"{self.tags [ tag_type ]}\n".lstrip ( )
+ if self.template [ tag_type ] [ 'names' ]:
+ members += f"{self.tags [ tag_type ]}\n".lstrip ( )
- if self.template [ tag_type ] [ 'names' ]:
for i, name in enumerate ( self.template [ tag_type ] [ 'names' ] ):
diff --git a/source/app/core/linker.py b/source/app/core/linker.py
index 993cb4c..b837d54 100644
--- a/source/app/core/linker.py
+++ b/source/app/core/linker.py
@@ -20,7 +20,7 @@ def __init__( self, arguments ):
########################################
- self.classes = [ ]
+ self.classSources = [ ]
self.objects = [ ]
@@ -43,13 +43,13 @@ def process ( self ):
for file in self.files:
- self.read_file ( file )
+ self.get_objects ( file )
self.match_files ( )
#### GETTERS ########################################################
- def get_files ( self ):
+ def get_files ( self ):
for ( root, dirs, file ) in os.walk ( self.arguments [ 'destination' ] ):
@@ -61,140 +61,152 @@ def get_files ( self ):
self.files.append ( f"{root}/{entry}" )
- #### UTILITIES ########################################################
- def read_file ( self, file ):
+ def get_objects ( self, file ):
- self.file = file
+ self.objects = [ ] # clear self.objects
- data = open ( file, 'r' ).read ( )
- self.objects = set ( re.findall ( r'(\w+)\s{2,}\{([^\}]+)\}', data ) )
+ data = open ( file, 'r' ).read ( )
+ objects = re.findall ( r'(\w+)\s{2,}\{([^\}]+)\}', data )
- def match_files ( self ):
- self.find_files ( )
+ for object in objects: # Filter objects
- self.match_objects ( )
+ if object [ 1 ] not in self.objects:
- self.link_objects ( )
+ self.objects.append ( object [ 1 ] )
- def find_files ( self ):
+ if self.objects: # If objects, store present file
- self.regexes = [ ] # clear self.regexes
+ self.file = file
- if self.objects:
+ def get_classes ( self ):
- for object in self.objects:
+ self.classSources = [ ] # clear self.classSources
- regex = ''
- object = object [ 1 ]
+ if self.files:
+ for regex in self.regexes:
- object_lo, object_up = object.lower ( ), object.upper ( )
+ files = ''.join ( self.files )
+ file = re.search ( regex, files )
- for i in range ( len ( object ) ):
- regex += f'[{object_lo [ i ]}|{object_up [ i ]}]'
+ if file:
+ file = file.group ( 0 ).lstrip ( '/' )
- regex = f'({regex})'
+ source = f"{self.arguments [ 'destination' ]}/{file}"
- self.regexes.append ( regex )
+ self.classSources.append ( source )
+ #### SETTERS ########################################################
- def match_objects ( self ):
+ def set_regexes ( self ):
- self.classes = [ ] # clear self.classes
+ self.regexes = [ ] # clear self.regexes
- if self.files:
+ if self.objects:
- for file in self.files:
+ for object in self.objects:
- for regex in self.regexes:
+ regex = ''
+
+ object_lo, object_up = object.lower ( ), object.upper ( )
+
+
+ for i in range ( len ( object ) ):
+
+ regex += f'[{object_lo [ i ]}|{object_up [ i ]}]'
- filename = re.findall ( regex, file )
+ self.regexes.append ( f"\/{regex}\.txt" )
- if filename:
+ #### UTILITIES ########################################################
+
+ def match_files ( self ):
- source = f"{self.arguments [ 'destination' ]}/{filename [ 0 ]}.txt"
+ self.set_regexes ( )
+ self.get_classes ( )
- if source == file:
+ self.link_objects ( )
- self.classes.append ( source )
+ def link_objects ( self ):
- def link_objects ( self ):
+ links = [ ]
- links = [ ]
- file = self.file.replace ( '.txt', '-linked.txt' )
+ if self.classSources:
- data = open ( self.file, 'r' ).read ( )
+ destination = f"{self.arguments [ 'destination' ]}/linked"
- header = re.findall ( r'class\s*([^\s]+)\s*', data ) [ 0 ]
+ filename = os.path.basename ( self.file ).replace ( '.txt', '-linked.txt' )
+ data = open ( self.file, 'r' ).read ( )
- for object in self.objects:
+ thisClass = re.findall ( r'class\s*([^\s]+)\s*', data ) [ 0 ]
- links.append ( f"{header} *-- {object [ 1 ]}" )
+ for object in self.objects:
- links.append ( '@enduml\n' )
+ links.append ( f"{thisClass} o-- {object}" )
- data = data.replace ( '@enduml', '\n'.join ( links ) )
+ data = data.replace ( '@enduml', '\n'.join ( links ) ) + '\n\n@enduml'
- for entry in self.classes:
- CLASS_UML = open ( entry, 'r' ).read ( )
+ for classSource in self.classSources:
- data += f'\n{CLASS_UML}\n'
+ CLASS_UML = open ( classSource, 'r' ).read ( )
+ data += f'\n{CLASS_UML}\n'
- data = re.sub ( r'@enduml\s*@startuml', '', data )
+ data = re.sub ( r'@enduml\s*@startuml', '', data ) # clean penultimate '@enduml' tags
- with open ( file, 'w' ) as writer:
+ file = Util.set_file ( filename.rstrip ( '.txt' ), destination )
- writer.write ( data )
+ with open ( file, 'w' ) as writer: # write file
- print ( '>> [ output ]\n', file )
+ writer.write ( data )
+ print ( '>> [ output ] Linker\n', file )
- self.compose_image ( file )
+
+ if 'plant_path' in self.arguments.keys ( ):
+
+ self.compose_image ( destination )
#### RENDERERS ########################################################
def compose_image ( self, file ):
- if 'plant_path' in self.arguments.keys ( ):
-
- for image_type in self.arguments [ 'make_image' ]:
+ for image_type in self.arguments [ 'make_image' ]:
- output_path = f"{os.path.dirname ( file )}/images"
+ output_path = f"{os.path.dirname ( file )}/images/linked"
- command = f"java -jar {self.arguments [ 'plant_path' ]} \"{file}\" -o \"{output_path}\" -{image_type}"
+ command = f"java -jar {self.arguments [ 'plant_path' ]} \"{file}\" -o \"{output_path}\" -{image_type}"
- filename = os.path.basename ( file ).replace ( 'txt', image_type )
+ filename = os.path.basename ( self.file ).replace ( '.txt', f"-linked.{image_type}" )
- if Util.is_directory ( output_path ) is False:
+ if Util.is_directory ( output_path ) is False:
- os.makedirs ( output_path )
+ os.makedirs ( output_path )
- subprocess.run ( command, shell=True )
+ subprocess.run ( command, shell=True )
- print ( f" {output_path}/{filename}\n" )
+ print ( f" {output_path}/{filename}\n" )
diff --git a/source/app/utilities/system/get_commands.py b/source/app/utilities/system/get_commands.py
index e8d5376..93b353e 100644
--- a/source/app/utilities/system/get_commands.py
+++ b/source/app/utilities/system/get_commands.py
@@ -78,11 +78,11 @@ def get_commands ( commands ):
if is_directory ( arguments [ 'source'] ):
- arguments [ 'destination' ] = f"{arguments [ 'source' ]}/output"
+ arguments [ 'destination' ] = f"{arguments [ 'source' ]}/_output"
elif is_file ( arguments [ 'source' ], None ):
- arguments [ 'destination' ] = f"{os.path.dirname ( arguments [ 'source' ] )}/output"
+ arguments [ 'destination' ] = f"{os.path.dirname ( arguments [ 'source' ] )}/_output"
return arguments